1 /*
2  * Copyright (C) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "utils.h"
17 
18 #include <hisysevent.h>
19 
20 #include "bundle_mgr_client.h"
21 #include "hilog_wrapper.h"
22 #include "nlohmann/json.hpp"
23 #include "ipc_skeleton.h"
24 
25 namespace OHOS {
26 namespace Accessibility {
27 namespace {
28     const std::string KEY_ACCESSIBILITY_ABILITY_TYPES = "accessibilityAbilityTypes";
29     const std::string KEY_ACCESSIBILITY_CAPABILITIES = "accessibilityCapabilities";
30     const std::string KEY_SETTINGS_ABILITY = "settingsAbility";
31     const std::string KEY_ACCESSIBILITY_CAPABILITIES_RATIONALE = "accessibilityCapabilityRationale";
32     const std::string KEY_IS_IMPORTANT = "isImportant";
33     const std::string KEY_NEED_HIDE = "needHide";
34 
35     // The json value of accessibilityAbility type
36     const std::string ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_SPOKEN = "spoken";
37     const std::string ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_HAPIC = "haptic";
38     const std::string ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_AUDIBLE = "audible";
39     const std::string ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_VISUAL = "visual";
40     const std::string ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_GENERIC = "generic";
41     const std::string ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_ALL = "all";
42 
43     // The json value of capabilities
44     const std::string CAPABILITIES_JSON_VALUE_RETRIEVE = "retrieve";
45     const std::string CAPABILITIES_JSON_VALUE_TOUCH_GUIDE = "touchGuide";
46     const std::string CAPABILITIES_JSON_VALUE_KEY_EVENT_OBSERVER = "keyEventObserver";
47     const std::string CAPABILITIES_JSON_VALUE_ZOOM = "zoom";
48     const std::string CAPABILITIES_JSON_VALUE_GESTURE = "gesture";
49 
50     const int32_t STRING_LEN_MAX = 10240;
51     constexpr int32_t BASE_USER_RANGE = 200000;
52     constexpr int32_t INVALID_ID = -1;
53     constexpr int32_t INVALID_USER_ID = -1;
54 } // namespace
55 
56 class JsonUtils {
57 public:
GetStringFromJson(const nlohmann::json & json,const std::string & key,std::string & value)58     static bool GetStringFromJson(const nlohmann::json &json, const std::string &key, std::string &value)
59     {
60         HILOG_DEBUG("start.");
61         if (!json.is_object()) {
62             HILOG_ERROR("json is not object.");
63             return false;
64         }
65         if (json.find(key) != json.end() && json.at(key).is_string()) {
66             HILOG_DEBUG("Find key[%{public}s] successful.", key.c_str());
67             value = json.at(key).get<std::string>();
68         }
69         return true;
70     }
71 
GetStringVecFromJson(const nlohmann::json & json,const std::string & key,std::vector<std::string> & value)72     static bool GetStringVecFromJson(const nlohmann::json &json, const std::string &key,
73         std::vector<std::string> &value)
74     {
75         HILOG_DEBUG("start.");
76         if (!json.is_object()) {
77             HILOG_ERROR("json is not object.");
78             return false;
79         }
80         if (json.find(key) != json.end() && json.at(key).is_array()) {
81             HILOG_DEBUG("Find key[%{public}s] successful.", key.c_str());
82             value = json.at(key).get<std::vector<std::string>>();
83         }
84         return true;
85     }
86 
GetBoolFromJson(const nlohmann::json & json,const std::string & key,bool & value)87     static bool GetBoolFromJson(const nlohmann::json &json, const std::string &key, bool &value)
88     {
89         HILOG_DEBUG("start.");
90         if (!json.is_object()) {
91             HILOG_ERROR("json is not object.");
92             return false;
93         }
94         if (json.find(key) != json.end() && json.at(key).is_boolean()) {
95             HILOG_DEBUG("Find key[%{public}s] successful.", key.c_str());
96             value = json.at(key).get<bool>();
97         }
98         return true;
99     }
100 };
101 
102 class PraseVecUtils {
103 public:
ParseAbilityTypesFromVec(const std::vector<std::string> & abilities)104     static uint32_t ParseAbilityTypesFromVec(const std::vector<std::string> &abilities)
105     {
106         HILOG_DEBUG("start.");
107         uint32_t abilityTypes = 0;
108 
109         for (const auto &ability : abilities) {
110             if (ability == ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_SPOKEN) {
111                 abilityTypes |= AccessibilityAbilityTypes::ACCESSIBILITY_ABILITY_TYPE_SPOKEN;
112             }
113 
114             if (ability == ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_HAPIC) {
115                 abilityTypes |= AccessibilityAbilityTypes::ACCESSIBILITY_ABILITY_TYPE_HAPTIC;
116             }
117 
118             if (ability == ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_AUDIBLE) {
119                 abilityTypes |= AccessibilityAbilityTypes::ACCESSIBILITY_ABILITY_TYPE_AUDIBLE;
120             }
121 
122             if (ability == ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_VISUAL) {
123                 abilityTypes |= AccessibilityAbilityTypes::ACCESSIBILITY_ABILITY_TYPE_VISUAL;
124             }
125 
126             if (ability == ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_GENERIC) {
127                 abilityTypes |= AccessibilityAbilityTypes::ACCESSIBILITY_ABILITY_TYPE_GENERIC;
128             }
129 
130             if (ability == ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_ALL) {
131                 abilityTypes |= AccessibilityAbilityTypes::ACCESSIBILITY_ABILITY_TYPE_ALL;
132             }
133         }
134         return abilityTypes;
135     }
136 
ParseCapabilitiesFromVec(const std::vector<std::string> & capabilities)137     static uint32_t ParseCapabilitiesFromVec(const std::vector<std::string> &capabilities)
138     {
139         HILOG_DEBUG("start.");
140         uint32_t capabilitiesValue = 0;
141 
142         for (const auto &capability : capabilities) {
143             if (capability == CAPABILITIES_JSON_VALUE_RETRIEVE) {
144                 capabilitiesValue |= Capability::CAPABILITY_RETRIEVE;
145             }
146 
147             if (capability == CAPABILITIES_JSON_VALUE_TOUCH_GUIDE) {
148                 capabilitiesValue |= Capability::CAPABILITY_TOUCH_GUIDE;
149             }
150 
151             if (capability == CAPABILITIES_JSON_VALUE_KEY_EVENT_OBSERVER) {
152                 capabilitiesValue |= Capability::CAPABILITY_KEY_EVENT_OBSERVER;
153             }
154 
155             if (capability == CAPABILITIES_JSON_VALUE_ZOOM) {
156                 capabilitiesValue |= Capability::CAPABILITY_ZOOM;
157             }
158 
159             if (capability == CAPABILITIES_JSON_VALUE_GESTURE) {
160                 capabilitiesValue |= Capability::CAPABILITY_GESTURE;
161             }
162         }
163         return capabilitiesValue;
164     }
165 };
166 
Parse(const AppExecFwk::ExtensionAbilityInfo & abilityInfo,AccessibilityAbilityInitParams & initParams)167 void Utils::Parse(const AppExecFwk::ExtensionAbilityInfo &abilityInfo, AccessibilityAbilityInitParams &initParams)
168 {
169     HILOG_DEBUG("start.");
170     initParams.name = abilityInfo.name;
171     initParams.bundleName = abilityInfo.bundleName;
172     initParams.moduleName = abilityInfo.moduleName;
173     initParams.description = abilityInfo.description;
174     initParams.label = abilityInfo.label;
175 
176     std::vector<std::string> profileInfos;
177     std::string metadataName = "ohos.accessibleability";
178     AppExecFwk::BundleMgrClient bundleMgrClient;
179     bundleMgrClient.GetResConfigFile(abilityInfo, metadataName, profileInfos);
180     if (profileInfos.empty()) {
181         HILOG_ERROR("profileInfos is empty.");
182         return;
183     }
184 
185     if (!nlohmann::json::accept(profileInfos[0])) {
186         HILOG_ERROR("profileInfos is not json format.");
187         return;
188     }
189     nlohmann::json sourceJson = nlohmann::json::parse(profileInfos[0]);
190 
191     // accessibilityCapabilities
192     std::vector<std::string> capabilities;
193     if (!JsonUtils::GetStringVecFromJson(sourceJson, KEY_ACCESSIBILITY_CAPABILITIES, capabilities)) {
194         HILOG_ERROR("Get accessibilityCapabilities from json failed.");
195         return;
196     }
197     initParams.staticCapabilities = PraseVecUtils::ParseCapabilitiesFromVec(capabilities);
198 
199     // accessibilityAbilityTypes
200     std::vector<std::string> abilityTypes;
201     if (!JsonUtils::GetStringVecFromJson(sourceJson, KEY_ACCESSIBILITY_ABILITY_TYPES, abilityTypes)) {
202         HILOG_ERROR("Get accessibilityAbilityTypes from json failed.");
203         return;
204     }
205     initParams.abilityTypes = PraseVecUtils::ParseAbilityTypesFromVec(abilityTypes);
206 
207     // accessibilityCapabilityRationale
208     if (!JsonUtils::GetStringFromJson(sourceJson, KEY_ACCESSIBILITY_CAPABILITIES_RATIONALE, initParams.rationale)) {
209         HILOG_ERROR("Get accessibilityCapabilityRationale from json failed.");
210         return;
211     }
212 
213     // settingsAbility
214     if (!JsonUtils::GetStringFromJson(sourceJson, KEY_SETTINGS_ABILITY, initParams.settingsAbility)) {
215         HILOG_ERROR("Get settingsAbility from json failed.");
216         return;
217     }
218 
219     // isImportant
220     if (!JsonUtils::GetBoolFromJson(sourceJson, KEY_IS_IMPORTANT, initParams.isImportant)) {
221         HILOG_ERROR("Get isImportant from json failed.");
222         return;
223     }
224 
225     // needHide
226     if (!JsonUtils::GetBoolFromJson(sourceJson, KEY_NEED_HIDE, initParams.needHide)) {
227         HILOG_ERROR("Get needHide from json failed.");
228         return;
229     }
230 }
231 
GetSystemTime()232 int64_t Utils::GetSystemTime()
233 {
234     HILOG_DEBUG("start.");
235 
236     struct timespec times = {0, 0};
237     clock_gettime(CLOCK_MONOTONIC, &times);
238     int64_t millisecond = static_cast<int64_t>(times.tv_sec * 1000 + times.tv_nsec / 1000000);
239 
240     return millisecond;
241 }
242 
GetUri(const OHOS::AppExecFwk::ElementName & elementName)243 std::string Utils::GetUri(const OHOS::AppExecFwk::ElementName &elementName)
244 {
245     HILOG_DEBUG("bundle name(%{public}s) ability name(%{public}s)",
246         elementName.GetBundleName().c_str(), elementName.GetAbilityName().c_str());
247     return elementName.GetBundleName() + "/" + elementName.GetAbilityName();
248 }
249 
GetUri(const std::string & bundleName,const std::string & abilityName)250 std::string Utils::GetUri(const std::string &bundleName, const std::string &abilityName)
251 {
252     HILOG_DEBUG("bundle name(%{public}s) ability name(%{public}s)", bundleName.c_str(), abilityName.c_str());
253     return bundleName + "/" + abilityName;
254 }
255 
GetAbilityAutoStartStateKey(const std::string & bundleName,const std::string & abilityName,int32_t accountId)256 std::string Utils::GetAbilityAutoStartStateKey(const std::string &bundleName, const std::string &abilityName,
257     int32_t accountId)
258 {
259     HILOG_DEBUG("bundle name(%{public}s) ability name(%{public}s) accountId(%{public}d)",
260         bundleName.c_str(), abilityName.c_str(), accountId);
261     return bundleName + "/" + abilityName + "/" + std::to_string(accountId);
262 }
263 
SelectUsefulFromVecWithSameBundle(std::vector<std::string> & selectVec,std::vector<std::string> & cmpVec,bool & hasDif,const std::string & bundleName)264 void Utils::SelectUsefulFromVecWithSameBundle(std::vector<std::string> &selectVec, std::vector<std::string> &cmpVec,
265     bool &hasDif, const std::string &bundleName)
266 {
267     HILOG_DEBUG();
268     for (auto iter = selectVec.begin(); iter != selectVec.end();) {
269         if (iter->substr(0, iter->find("/")) != bundleName) {
270             ++iter;
271             continue;
272         }
273         auto it = cmpVec.begin();
274         for (; it != cmpVec.end(); ++it) {
275             if ((*it) == (*iter)) {
276                 break;
277             }
278         }
279         if (it == cmpVec.end()) {
280             iter = selectVec.erase(iter);
281             hasDif = true;
282         } else {
283             ++iter;
284         }
285     }
286 }
287 
RecordUnavailableEvent(A11yUnavailableEvent event,A11yError errCode,const std::string & bundleName,const std::string & abilityName)288 void Utils::RecordUnavailableEvent(A11yUnavailableEvent event, A11yError errCode,
289     const std::string &bundleName, const std::string &abilityName)
290 {
291     if (!(errCode > A11yError::ERROR_NEED_REPORT_BASE && errCode < A11yError::ERROR_NEED_REPORT_END)) {
292         return;
293     }
294     std::ostringstream oss;
295     oss << "accessibility function is unavailable: " << "event: " << TransferUnavailableEventToString(event)
296         << ", errCode: " << static_cast<int32_t>(errCode)
297         << ", bundleName: " << bundleName << ", abilityName: " << abilityName << ";";
298     std::string info = oss.str();
299     HILOG_DEBUG("accessibility function is unavailable: %{public}s", info.c_str());
300     int32_t ret = HiSysEventWrite(
301         OHOS::HiviewDFX::HiSysEvent::Domain::ACCESSIBILITY,
302         "UNAVAILABLE",
303         OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
304         "MSG", info);
305     if (ret != 0) {
306         HILOG_ERROR("Write HiSysEvent error, ret:%{public}d", ret);
307     }
308 }
309 
TransferUnavailableEventToString(A11yUnavailableEvent type)310 std::string Utils::TransferUnavailableEventToString(A11yUnavailableEvent type)
311 {
312     std::string event;
313     switch (type) {
314         case A11yUnavailableEvent::READ_EVENT:
315             event = "READ";
316             break;
317         case A11yUnavailableEvent::CONNECT_EVENT:
318             event = "CONNECT";
319             break;
320         case A11yUnavailableEvent::QUERY_EVENT:
321             event = "QUERY";
322             break;
323         default:
324             event = "UNDEFINE";
325             break;
326     }
327     return event;
328 }
329 
RecordStartingA11yEvent(uint32_t flag)330 void Utils::RecordStartingA11yEvent(uint32_t flag)
331 {
332     std::ostringstream oss;
333     oss << "starting accessibility: " << "event: " << "system" << ", id: " << flag << ";";
334     HILOG_DEBUG("starting accessibility: %{public}s", oss.str().c_str());
335     int32_t ret = HiSysEventWrite(
336         OHOS::HiviewDFX::HiSysEvent::Domain::ACCESSIBILITY,
337         "STARTING_FUNCTION",
338         OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
339         "MSG", oss.str());
340     if (ret != 0) {
341         HILOG_ERROR("Write HiSysEvent error, ret:%{public}d", ret);
342     }
343 }
344 
RecordStartingA11yEvent(const std::string & name)345 void Utils::RecordStartingA11yEvent(const std::string &name)
346 {
347     std::ostringstream oss;
348     oss << "starting accessibility: " << "event: " << "extension" << ", name: " << name << ";";
349     HILOG_DEBUG("starting accessibility: %{public}s", oss.str().c_str());
350     int32_t ret = HiSysEventWrite(
351         OHOS::HiviewDFX::HiSysEvent::Domain::ACCESSIBILITY,
352         "STARTING_FUNCTION",
353         OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
354         "MSG", oss.str());
355     if (ret != 0) {
356         HILOG_ERROR("Write HiSysEvent error, ret:%{public}d", ret);
357     }
358 }
359 
RecordEnableShortkeyAbilityEvent(const std::string & name)360 void Utils::RecordEnableShortkeyAbilityEvent(const std::string &name)
361 {
362     std::string MSG_NAME = "enable single targets";
363     HILOG_DEBUG("starting RecordEnableShortkeyAbilityEvent enable single targets: %{public}s", name.c_str());
364     int32_t ret = HiSysEventWrite(
365         OHOS::HiviewDFX::HiSysEvent::Domain::ACCESSIBILITY_UE,
366         "ENABLE_SHORTKEY_ABILITY_SINGLE",
367         OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
368         "MSG_NAME", MSG_NAME, "MSG_VALUE", name);
369     if (ret != 0) {
370         HILOG_ERROR("Write HiSysEvent RecordEnableShortkeyAbilityEvent error, ret:%{public}d", ret);
371     }
372 }
373 
RecordOnZoomGestureEvent(const std::string & state)374 void Utils::RecordOnZoomGestureEvent(const std::string &state)
375 {
376     std::string MSG_NAME = "on zoom gesture state";
377     HILOG_DEBUG("starting RecordOnZoomGestureEvent on zoom gesture state: %{public}s", state.c_str());
378     int32_t ret = HiSysEventWrite(
379         OHOS::HiviewDFX::HiSysEvent::Domain::ACCESSIBILITY_UE,
380         "ZOOM_GESTURE_ACTION",
381         OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
382         "MSG_NAME", MSG_NAME, "MSG_VALUE", state);
383     if (ret != 0) {
384         HILOG_ERROR("Write HiSysEvent RecordOnZoomGestureEvent error, ret:%{public}d", ret);
385     }
386 }
387 
VectorToString(const std::vector<std::string> & vectorVal,std::string & stringOut)388 void Utils::VectorToString(const std::vector<std::string> &vectorVal, std::string &stringOut)
389 {
390     HILOG_DEBUG();
391     int32_t i = 0;
392     for (auto& var : vectorVal) {
393         if (i > 0) {
394             stringOut = stringOut + ',';
395         }
396         stringOut = stringOut + var.c_str();
397         i++;
398     }
399     HILOG_DEBUG("stringOUT = %{public}s .", stringOut.c_str());
400 }
401 
StringToVector(const std::string & stringIn,std::vector<std::string> & vectorResult)402 void Utils::StringToVector(const std::string &stringIn, std::vector<std::string> &vectorResult)
403 {
404     HILOG_DEBUG();
405     int32_t strLength = static_cast<int32_t>(stringIn.size());
406     std::vector<int32_t> position;
407 
408     if (strLength <= 0 || strLength > STRING_LEN_MAX) {
409         return;
410     }
411 
412     for (int32_t j = 0; j < strLength; j++) {
413         if (stringIn[j] == ',') {
414             position.push_back(j);
415         }
416     }
417 
418     int32_t wrodCount = static_cast<int32_t>(position.size());
419     if (wrodCount == 0) {
420         vectorResult.push_back(stringIn);
421     } else {
422         int32_t startWrod = 0;
423         int32_t length = 0;
424         for (int32_t i = 0; i <= wrodCount; i++) {
425             if (i == 0) {
426                 length = position[i];
427                 vectorResult.push_back(stringIn.substr(startWrod, length)); // First string
428             } else if (i < wrodCount) {
429                 startWrod = position[i - 1] + 1;
430                 length = position[i] - position[i - 1] - 1;
431                 vectorResult.push_back(stringIn.substr(startWrod, length)); // Second string to last-1 string
432             } else {
433                 startWrod = position[i - 1] + 1;
434                 length = strLength - position[i - 1] - 1;
435                 vectorResult.push_back(stringIn.substr(startWrod, length)); // Last string
436             }
437         }
438     }
439     HILOG_DEBUG("strLength = %{public}d, wrodCount = %{public}d, stringIn : %{public}s",
440         strLength, wrodCount, stringIn.c_str());
441     for (auto& var : vectorResult) {
442         HILOG_DEBUG("vectorResult = %{public}s ", var.c_str());
443     }
444 }
445 
GetUserIdByCallingUid()446 int32_t Utils::GetUserIdByCallingUid()
447 {
448     int32_t uid = IPCSkeleton::GetCallingUid();
449     if (uid <= INVALID_ID) {
450         return INVALID_USER_ID;
451     }
452     return (uid / BASE_USER_RANGE);
453 }
454 } // namespace Accessibility
455 } // namespace OHOS