• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 "parse_util.h"
17 
18 #include <cinttypes>
19 #include <dlfcn.h>
20 #include <fstream>
21 #include <unistd.h>
22 #include <memory>
23 #include <sstream>
24 #include <vector>
25 #include <algorithm>
26 
27 #include "datetime_ex.h"
28 #include "hisysevent_adapter.h"
29 #include "hitrace_meter.h"
30 #include "sam_log.h"
31 #include "string_ex.h"
32 #include "samgr_xcollie.h"
33 
34 namespace OHOS {
35 using std::string;
36 
37 namespace {
38 constexpr const char* EVENT_TYPE = "eventId";
39 constexpr const char* EVENT_NAME = "name";
40 constexpr const char* EVENT_VALUE = "value";
41 constexpr const char* SA_TAG_SYSTEM_ABILITY = "systemability";
42 constexpr const char* SA_TAG_PROCESS = "process";
43 constexpr const char* SA_TAG_LIB_PATH = "libpath";
44 constexpr const char* SA_TAG_NAME = "name";
45 constexpr const char* SA_TAG_DEPEND = "depend";
46 constexpr const char* SA_TAG_DEPEND_TIMEOUT = "depend-time-out";
47 constexpr const char* SA_TAG_DEPEND_TIMEOUT_COMPATIBILITY = "depend_time_out";
48 constexpr const char* SA_TAG_RUN_ON_CREATE = "run-on-create";
49 constexpr const char* SA_TAG_MODULE_UPDATE = "module-update";
50 constexpr const char* SA_TAG_AUTO_RESTART = "auto-restart";
51 constexpr const char* SA_TAG_DISTRIBUTED = "distributed";
52 constexpr const char* SA_TAG_CACHE_COMMON_EVENT = "cache-common-event";
53 constexpr const char* SA_TAG_DUMP_LEVEL = "dump-level";
54 constexpr const char* SA_TAG_CAPABILITY = "capability";
55 constexpr const char* SA_TAG_PERMISSION = "permission";
56 constexpr const char* SA_TAG_BOOT_PHASE = "bootphase";
57 constexpr const char* SA_TAG_SAID = "said";
58 constexpr const char* SA_TAG_START_ON_DEMAND = "start-on-demand";
59 constexpr const char* SA_TAG_STOP_ON_DEMAND = "stop-on-demand";
60 constexpr const char* SA_TAG_ALLOW_UPDATE = "allow-update";
61 constexpr const char* SA_TAG_RECYCLE_DELAYTIME = "recycle-delaytime";
62 constexpr const char* SA_TAG_DEVICE_ON_LINE = "deviceonline";
63 constexpr const char* SA_TAG_SETTING_SWITCH = "settingswitch";
64 constexpr const char* SA_TAG_COMMON_EVENT = "commonevent";
65 constexpr const char* SA_TAG_PARAM = "param";
66 constexpr const char* SA_TAG_TIEMD_EVENT = "timedevent";
67 constexpr const char* SA_TAG_RECYCLE_STRATEGY = "recycle-strategy";
68 constexpr const char* SA_TAG_EXTENSION = "extension";
69 constexpr const char* SA_TAG_UNREF_UNLOAD = "unreferenced-unload";
70 constexpr const char* SA_TAG_LONGTIMEUNUSED_UNLOAD = "longtimeunused-unload";
71 constexpr int32_t MAX_JSON_OBJECT_SIZE = 50 * 1024;
72 constexpr int32_t MAX_JSON_STRING_LENGTH = 128;
73 constexpr int32_t FIRST_SYS_ABILITY_ID = 0x00000000;
74 constexpr int32_t LAST_SYS_ABILITY_ID = 0x00ffffff;
75 constexpr int32_t MAX_EXTENSIONO_NUM = 100;
76 constexpr int32_t MAX_DLOPEN_SECONDS = 60;
77 constexpr const char* BOOT_START_PHASE = "BootStartPhase";
78 constexpr const char* CORE_START_PHASE = "CoreStartPhase";
79 constexpr const char* HIGH_LOAD_PRIORITY = "HighPriority";
80 constexpr const char* MEDIUM_LOAD_PRIORITY = "MediumPriority";
81 
82 enum {
83     BOOT_START = 1,
84     CORE_START = 2,
85     OTHER_START = 3,
86 };
87 
88 enum {
89     EQ = 1,
90     GREATER_EQ = 2,
91     GREATER = 3,
92     LESS_EQ = 4,
93     LESS = 5
94 };
95 }
96 
~ParseUtil()97 ParseUtil::~ParseUtil()
98 {
99     ClearResource();
100 }
101 
CloseHandle(SaProfile & saProfile)102 void ParseUtil::CloseHandle(SaProfile& saProfile)
103 {
104     if (saProfile.handle == nullptr) {
105         return;
106     }
107     int32_t ret = dlclose(saProfile.handle);
108     if (ret) {
109         HILOGW("close handle failed with errno:%{public}d!", errno);
110     }
111     saProfile.handle = nullptr;
112 }
113 
CloseSo()114 void ParseUtil::CloseSo()
115 {
116     for (auto& saProfile : saProfiles_) {
117         CloseHandle(saProfile);
118     }
119 }
120 
CloseSo(int32_t systemAbilityId)121 void ParseUtil::CloseSo(int32_t systemAbilityId)
122 {
123     for (auto& saProfile : saProfiles_) {
124         if (saProfile.saId == systemAbilityId) {
125             CloseHandle(saProfile);
126             break;
127         }
128     }
129 }
130 
ClearResource()131 void ParseUtil::ClearResource()
132 {
133     CloseSo();
134     saProfiles_.clear();
135 }
136 
OpenSo(uint32_t bootPhase)137 void ParseUtil::OpenSo(uint32_t bootPhase)
138 {
139     for (auto& saProfile : saProfiles_) {
140         if (saProfile.runOnCreate && saProfile.bootPhase == bootPhase) {
141             OpenSo(saProfile);
142         }
143     }
144 }
145 
OpenSo(SaProfile & saProfile)146 void ParseUtil::OpenSo(SaProfile& saProfile)
147 {
148     if (saProfile.handle == nullptr) {
149         string dlopenTag = ToString(saProfile.saId) + "_DLOPEN";
150         HITRACE_METER_NAME(HITRACE_TAG_SAMGR, dlopenTag);
151         int64_t begin = GetTickCount();
152         DlHandle handle = nullptr;
153         if (saProfile.runOnCreate) {
154             handle = dlopen(saProfile.libPath.c_str(), RTLD_NOW);
155         } else {
156             SamgrXCollie samgrXCollie("safwk--openso_" + ToString(saProfile.saId), MAX_DLOPEN_SECONDS);
157             handle = dlopen(saProfile.libPath.c_str(), RTLD_NOW);
158         }
159         int64_t duration = GetTickCount() - begin;
160         KHILOGI("SA:%{public}d OpenSo %{public}" PRId64 "ms",
161             saProfile.saId, duration);
162         if (handle == nullptr) {
163             std::vector<string> libPathVec;
164             string fileName = "";
165             SplitStr(saProfile.libPath, "/", libPathVec);
166             if (libPathVec.size() > 0) {
167                 fileName = libPathVec[libPathVec.size() - 1];
168             }
169             ReportAddSystemAbilityFailed(saProfile.saId, getpid(), getuid(), fileName);
170             HILOGE("SA:%{public}d dlopen %{public}s failed with errno:%{public}s!",
171                 saProfile.saId, fileName.c_str(), dlerror());
172             return;
173         } else {
174             ReportSaLoadDuration(saProfile.saId, SA_LOAD_OPENSO, duration);
175         }
176         saProfile.handle = handle;
177     } else {
178         KHILOGI("SA:%{public}d handle is not null", saProfile.saId);
179     }
180 }
181 
LoadSaLib(int32_t systemAbilityId)182 bool ParseUtil::LoadSaLib(int32_t systemAbilityId)
183 {
184     for (auto& saProfile : saProfiles_) {
185         if (saProfile.saId == systemAbilityId) {
186             OpenSo(saProfile);
187             return true;
188         }
189     }
190     return false;
191 }
192 
GetAllSaProfiles() const193 const std::list<SaProfile>& ParseUtil::GetAllSaProfiles() const
194 {
195     return saProfiles_;
196 }
197 
GetProfile(int32_t saId,SaProfile & saProfile)198 bool ParseUtil::GetProfile(int32_t saId, SaProfile& saProfile)
199 {
200     auto iter = std::find_if(saProfiles_.begin(), saProfiles_.end(), [saId](auto saProfile) {
201         return saProfile.saId == saId;
202     });
203     if (iter != saProfiles_.end()) {
204         saProfile = *iter;
205         return true;
206     }
207     return false;
208 }
209 
RemoveSaProfile(int32_t saId)210 void ParseUtil::RemoveSaProfile(int32_t saId)
211 {
212     saProfiles_.remove_if([saId] (auto saInfo) -> bool { return saInfo.saId == saId; });
213 }
214 
GetBootPriorityPara(const std::string & bootPhase)215 uint32_t ParseUtil::GetBootPriorityPara(const std::string& bootPhase)
216 {
217     if (bootPhase == BOOT_START_PHASE) {
218         return static_cast<uint32_t>(BOOT_START);
219     } else if (bootPhase == CORE_START_PHASE) {
220         return static_cast<uint32_t>(CORE_START);
221     } else {
222         return static_cast<uint32_t>(OTHER_START);
223     }
224 }
225 
GetOndemandPriorityPara(const std::string & loadPriority)226 uint32_t ParseUtil::GetOndemandPriorityPara(const std::string& loadPriority)
227 {
228     if (loadPriority == HIGH_LOAD_PRIORITY) {
229         return static_cast<uint32_t>(HIGH_PRIORITY);
230     } else if (loadPriority == MEDIUM_LOAD_PRIORITY) {
231         return static_cast<uint32_t>(MEDIUM_PRIORITY);
232     } else {
233         return static_cast<uint32_t>(LOW_PRIORITY);
234     }
235 }
236 
ParseSaProfiles(const string & profilePath)237 bool ParseUtil::ParseSaProfiles(const string& profilePath)
238 {
239     HILOGD("profilePath:%{private}s", profilePath.c_str());
240     string realPath = GetRealPath(profilePath);
241     if (!CheckPathExist(realPath.c_str())) {
242         HILOGE("bad profile path!");
243         return false;
244     }
245 
246     if (Endswith(realPath, ".json")) {
247         return ParseJsonFile(realPath);
248     } else {
249         HILOGE("Invalid file format, please use json file!");
250         return false;
251     }
252 }
253 
Endswith(const std::string & src,const std::string & sub)254 bool ParseUtil::Endswith(const std::string& src, const std::string& sub)
255 {
256     return (src.length() >= sub.length() && (src.rfind(sub) == (src.length() - sub.length())));
257 }
258 
StringToMap(const std::string & eventStr)259 std::unordered_map<std::string, std::string> ParseUtil::StringToMap(const std::string& eventStr)
260 {
261     nlohmann::json eventJson = StringToJsonObj(eventStr);
262     std::unordered_map<std::string, std::string> eventMap = JsonObjToMap(eventJson);
263     return eventMap;
264 }
265 
StringToJsonObj(const std::string & eventStr)266 nlohmann::json ParseUtil::StringToJsonObj(const std::string& eventStr)
267 {
268     nlohmann::json jsonObj = nlohmann::json::object();
269     if (eventStr.empty()) {
270         return jsonObj;
271     }
272     nlohmann::json eventJson = nlohmann::json::parse(eventStr, nullptr, false);
273     if (eventJson.is_discarded()) {
274         HILOGE("parse eventStr to json failed");
275         return jsonObj;
276     }
277     if (!eventJson.is_object()) {
278         HILOGE("eventStr converted result is not a jsonObj");
279         return jsonObj;
280     }
281     return eventJson;
282 }
283 
JsonObjToMap(const nlohmann::json & eventJson)284 std::unordered_map<std::string, std::string> ParseUtil::JsonObjToMap(const nlohmann::json& eventJson)
285 {
286     std::unordered_map<std::string, std::string> eventMap;
287     if (eventJson.contains(EVENT_TYPE) && eventJson[EVENT_TYPE].is_string()) {
288         eventMap[EVENT_TYPE] = eventJson[EVENT_TYPE];
289     } else {
290         eventMap[EVENT_TYPE] = "";
291     }
292     if (eventJson.contains(EVENT_NAME) && eventJson[EVENT_NAME].is_string()) {
293         eventMap[EVENT_NAME] = eventJson[EVENT_NAME];
294     } else {
295         eventMap[EVENT_NAME] = "";
296     }
297     if (eventJson.contains(EVENT_VALUE) && eventJson[EVENT_VALUE].is_string()) {
298         eventMap[EVENT_VALUE] = eventJson[EVENT_VALUE];
299     } else {
300         eventMap[EVENT_VALUE] = "";
301     }
302     return eventMap;
303 }
304 
ParseJsonFile(const string & realPath)305 bool ParseUtil::ParseJsonFile(const string& realPath)
306 {
307     nlohmann::json profileJson;
308     bool result = ParseJsonObj(profileJson, realPath);
309     if (!result) {
310         HILOGE("json file parse error!");
311         return false;
312     }
313     HILOGD("profileJson:%{private}s", profileJson.dump().c_str());
314     string process;
315     GetStringFromJson(profileJson, SA_TAG_PROCESS, process);
316     if (process.empty()) {
317         HILOGE("profile format error: no process tag");
318         return false;
319     }
320     if (process.length() > MAX_JSON_STRING_LENGTH) {
321         HILOGE("profile format error: process is too long");
322         return false;
323     }
324     procName_ = Str8ToStr16(process);
325     if (profileJson.find(SA_TAG_SYSTEM_ABILITY) == profileJson.end()) {
326         HILOGE("system ability parse error!");
327         return false;
328     }
329     nlohmann::json& systemAbilityJson = profileJson.at(SA_TAG_SYSTEM_ABILITY);
330     HILOGD("systemAbilityJson:%{private}s", systemAbilityJson.dump().c_str());
331     if (!systemAbilityJson.is_array()) {
332         HILOGE("system ability is not array!");
333         return false;
334     }
335     size_t size = systemAbilityJson.size();
336     for (size_t i = 0; i < size; i++) {
337         SaProfile saProfile = { procName_ };
338         if (!ParseSystemAbility(saProfile, systemAbilityJson[i])) {
339             continue;
340         }
341         saProfiles_.emplace_back(saProfile);
342     }
343     return !saProfiles_.empty();
344 }
345 
ParseSystemAbilityGetExtension(SaProfile & saProfile,nlohmann::json & systemAbilityJson)346 bool ParseUtil::ParseSystemAbilityGetExtension(SaProfile& saProfile, nlohmann::json& systemAbilityJson)
347 {
348     if ((systemAbilityJson.find(SA_TAG_EXTENSION) != systemAbilityJson.end()) &&
349         (systemAbilityJson[SA_TAG_EXTENSION].is_array())) {
350         for (auto& item : systemAbilityJson[SA_TAG_EXTENSION]) {
351             std::string extension = item.get<std::string>();
352             if (extension.length() > MAX_JSON_STRING_LENGTH) {
353                 HILOGE("profile format error: extension() len exceed limit");
354                 return false;
355             }
356             if (saProfile.extension.size() >= MAX_EXTENSIONO_NUM) {
357                 HILOGE("profile format error: extension num exceed limit");
358                 return false;
359             }
360 
361             if (std::find(saProfile.extension.begin(), saProfile.extension.end(), extension) ==
362                 saProfile.extension.end()) {
363                 saProfile.extension.push_back(extension);
364             }
365         }
366     }
367     return true;
368 }
369 
ParseSystemAbilityGetSaBaseInfo(SaProfile & saProfile,nlohmann::json & systemAbilityJson)370 bool ParseUtil::ParseSystemAbilityGetSaBaseInfo(SaProfile& saProfile, nlohmann::json& systemAbilityJson)
371 {
372     GetInt32FromJson(systemAbilityJson, SA_TAG_NAME, saProfile.saId);
373     if (saProfile.saId == 0) {
374         HILOGE("profile format error: no name tag");
375         return false;
376     }
377     if (saProfile.saId < FIRST_SYS_ABILITY_ID || saProfile.saId > LAST_SYS_ABILITY_ID) {
378         HILOGE("profile format error: saId error");
379         return false;
380     }
381     GetStringFromJson(systemAbilityJson, SA_TAG_LIB_PATH, saProfile.libPath);
382     if (saProfile.libPath.empty()) {
383         HILOGE("profile format error: no libPath tag");
384         return false;
385     }
386     if (saProfile.libPath.length() > MAX_JSON_STRING_LENGTH) {
387         HILOGE("profile format error: libPath is too long");
388         return false;
389     }
390     return true;
391 }
392 
ParseSystemAbilityGetSaExtInfo(SaProfile & saProfile,nlohmann::json & systemAbilityJson)393 bool ParseUtil::ParseSystemAbilityGetSaExtInfo(SaProfile& saProfile, nlohmann::json& systemAbilityJson)
394 {
395     GetBoolFromJson(systemAbilityJson, SA_TAG_RUN_ON_CREATE, saProfile.runOnCreate);
396     GetBoolFromJson(systemAbilityJson, SA_TAG_MODULE_UPDATE, saProfile.moduleUpdate);
397     GetBoolFromJson(systemAbilityJson, SA_TAG_AUTO_RESTART, saProfile.autoRestart);
398     GetBoolFromJson(systemAbilityJson, SA_TAG_DISTRIBUTED, saProfile.distributed);
399     GetBoolFromJson(systemAbilityJson, SA_TAG_CACHE_COMMON_EVENT, saProfile.cacheCommonEvent);
400     GetIntArrayFromJson(systemAbilityJson, SA_TAG_DEPEND, saProfile.dependSa);
401     GetInt32FromJson(systemAbilityJson, SA_TAG_DEPEND_TIMEOUT, saProfile.dependTimeout);
402     if (saProfile.dependTimeout == 0) {
403         GetInt32FromJson(systemAbilityJson, SA_TAG_DEPEND_TIMEOUT_COMPATIBILITY, saProfile.dependTimeout);
404     }
405     GetInt32FromJson(systemAbilityJson, SA_TAG_DUMP_LEVEL, saProfile.dumpLevel);
406     string capability;
407     GetStringFromJson(systemAbilityJson, SA_TAG_CAPABILITY, capability);
408     saProfile.capability = capability.length() <= MAX_JSON_STRING_LENGTH ? Str8ToStr16(capability) : u"";
409     string permission;
410     GetStringFromJson(systemAbilityJson, SA_TAG_PERMISSION, permission);
411     saProfile.permission = permission.length() <= MAX_JSON_STRING_LENGTH ? Str8ToStr16(permission) : u"";
412     string bootPhase;
413     GetStringFromJson(systemAbilityJson, SA_TAG_BOOT_PHASE, bootPhase);
414     saProfile.bootPhase = GetBootPriorityPara(bootPhase);
415     // parse start-on-demand tag
416     ParseStartOndemandTag(systemAbilityJson, SA_TAG_START_ON_DEMAND, saProfile.startOnDemand);
417     // parse stop-on-demand tag
418     ParseStopOndemandTag(systemAbilityJson, SA_TAG_STOP_ON_DEMAND, saProfile.stopOnDemand);
419     string recycleStrategy;
420     GetStringFromJson(systemAbilityJson, SA_TAG_RECYCLE_STRATEGY, recycleStrategy);
421     if (!CheckRecycleStrategy(recycleStrategy, saProfile.recycleStrategy)) {
422         HILOGE("profile format error: recycleStrategy: %{public}s is not immediately or low-memory",
423             recycleStrategy.c_str());
424         return false;
425     }
426     if (!ParseSystemAbilityGetExtension(saProfile, systemAbilityJson)) {
427         return false;
428     }
429     return true;
430 }
431 
ParseSystemAbility(SaProfile & saProfile,nlohmann::json & systemAbilityJson)432 bool ParseUtil::ParseSystemAbility(SaProfile& saProfile, nlohmann::json& systemAbilityJson)
433 {
434     HILOGD("ParseSystemAbility begin");
435     if (!ParseSystemAbilityGetSaBaseInfo(saProfile, systemAbilityJson)) {
436         return false;
437     }
438     if (!ParseSystemAbilityGetSaExtInfo(saProfile, systemAbilityJson)) {
439         return false;
440     }
441     HILOGD("ParseSystemAbility end");
442     return true;
443 }
444 
CheckRecycleStrategy(const std::string & recycleStrategyStr,int32_t & recycleStrategy)445 bool ParseUtil::CheckRecycleStrategy(const std::string& recycleStrategyStr, int32_t& recycleStrategy)
446 {
447     if (recycleStrategyStr == "" || recycleStrategyStr == "immediately") {
448         recycleStrategy = IMMEDIATELY;
449         return true;
450     } else if (recycleStrategyStr == "low-memory") {
451         recycleStrategy = LOW_MEMORY;
452         return true;
453     }
454     return false;
455 }
456 
ParseJsonTag(const nlohmann::json & systemAbilityJson,const std::string & jsonTag,nlohmann::json & onDemandJson)457 bool ParseUtil::ParseJsonTag(const nlohmann::json& systemAbilityJson, const std::string& jsonTag,
458     nlohmann::json& onDemandJson)
459 {
460     if (systemAbilityJson.find(jsonTag) == systemAbilityJson.end()) {
461         return false;
462     }
463     onDemandJson = systemAbilityJson.at(jsonTag);
464     if (!onDemandJson.is_object()) {
465         HILOGE("parse ondemand tag error");
466         return false;
467     }
468     return true;
469 }
470 
ParseOndemandTag(const nlohmann::json & onDemandJson,std::vector<OnDemandEvent> & onDemandEvents)471 void ParseUtil::ParseOndemandTag(const nlohmann::json& onDemandJson, std::vector<OnDemandEvent>& onDemandEvents)
472 {
473     GetOnDemandArrayFromJson(DEVICE_ONLINE, onDemandJson, SA_TAG_DEVICE_ON_LINE, onDemandEvents);
474     GetOnDemandArrayFromJson(SETTING_SWITCH, onDemandJson, SA_TAG_SETTING_SWITCH, onDemandEvents);
475     GetOnDemandArrayFromJson(COMMON_EVENT, onDemandJson, SA_TAG_COMMON_EVENT, onDemandEvents);
476     GetOnDemandArrayFromJson(PARAM, onDemandJson, SA_TAG_PARAM, onDemandEvents);
477     GetOnDemandArrayFromJson(TIMED_EVENT, onDemandJson, SA_TAG_TIEMD_EVENT, onDemandEvents);
478 }
479 
ParseStartOndemandTag(const nlohmann::json & systemAbilityJson,const std::string & jsonTag,StartOnDemand & startOnDemand)480 void ParseUtil::ParseStartOndemandTag(const nlohmann::json& systemAbilityJson,
481     const std::string& jsonTag, StartOnDemand& startOnDemand)
482 {
483     nlohmann::json onDemandJson;
484     if (!ParseJsonTag(systemAbilityJson, jsonTag, onDemandJson)) {
485         return;
486     }
487     ParseOndemandTag(onDemandJson, startOnDemand.onDemandEvents);
488     GetBoolFromJson(onDemandJson, SA_TAG_ALLOW_UPDATE, startOnDemand.allowUpdate);
489 }
490 
ParseStopOndemandTag(const nlohmann::json & systemAbilityJson,const std::string & jsonTag,StopOnDemand & stopOnDemand)491 void ParseUtil::ParseStopOndemandTag(const nlohmann::json& systemAbilityJson,
492     const std::string& jsonTag, StopOnDemand& stopOnDemand)
493 {
494     nlohmann::json onDemandJson;
495     if (!ParseJsonTag(systemAbilityJson, jsonTag, onDemandJson)) {
496         return;
497     }
498     ParseOndemandTag(onDemandJson, stopOnDemand.onDemandEvents);
499     GetBoolFromJson(onDemandJson, SA_TAG_ALLOW_UPDATE, stopOnDemand.allowUpdate);
500     GetBoolFromJson(onDemandJson, SA_TAG_UNREF_UNLOAD, stopOnDemand.unrefUnload);
501     GetInt32FromJson(onDemandJson, SA_TAG_RECYCLE_DELAYTIME, stopOnDemand.delayTime);
502     GetInt32FromJson(onDemandJson, SA_TAG_LONGTIMEUNUSED_UNLOAD, stopOnDemand.unusedTimeout);
503 }
504 
GetOnDemandArrayFromJson(int32_t eventId,const nlohmann::json & obj,const std::string & key,std::vector<OnDemandEvent> & out)505 void ParseUtil::GetOnDemandArrayFromJson(int32_t eventId, const nlohmann::json& obj,
506     const std::string& key, std::vector<OnDemandEvent>& out)
507 {
508     if (obj.find(key.c_str()) != obj.end() && obj[key.c_str()].is_array()) {
509         for (auto& item : obj[key.c_str()]) {
510             std::string name;
511             GetStringFromJson(item, "name", name);
512             std::string value;
513             GetStringFromJson(item, "value", value);
514             bool persistence = false;
515             GetBoolFromJson(item, "persistence", persistence);
516             std::vector<OnDemandCondition> conditions;
517             GetOnDemandConditionsFromJson(item, "conditions", conditions);
518             HILOGD("conditions size: %{public}zu", conditions.size());
519             bool enableOnce = false;
520             GetBoolFromJson(item, "enable-once", enableOnce);
521             std::string priority;
522             GetStringFromJson(item, "load-priority", priority);
523             uint32_t loadPriority = GetOndemandPriorityPara(priority);
524             std::map<std::string, std::string> extraMessages;
525             GetOnDemandExtraMessagesFromJson(item, "extra-messages", extraMessages);
526             HILOGD("extraMessages size: %{public}zu", extraMessages.size());
527             if (!name.empty() && name.length() <= MAX_JSON_STRING_LENGTH &&
528                 value.length() <= MAX_JSON_STRING_LENGTH) {
529                 OnDemandEvent event = {eventId, name, value, -1, persistence,
530                     conditions, enableOnce, loadPriority, extraMessages};
531                 out.emplace_back(event);
532             }
533         }
534     }
535 }
536 
GetOnDemandExtraMessagesFromJson(const nlohmann::json & obj,const std::string & key,std::map<std::string,std::string> & out)537 void ParseUtil::GetOnDemandExtraMessagesFromJson(const nlohmann::json& obj,
538     const std::string& key, std::map<std::string, std::string>& out)
539 {
540     if (obj.find(key.c_str()) == obj.end() || !obj[key.c_str()].is_object()) {
541         return;
542     }
543     for (auto &it: obj[key.c_str()].items()) {
544         if (it.value().is_string()) {
545             out[it.key()] = it.value();
546         } else {
547             HILOGW("extra-mesasge: not string type");
548         }
549     }
550 }
551 
GetOnDemandConditionsFromJson(const nlohmann::json & obj,const std::string & key,std::vector<OnDemandCondition> & out)552 void ParseUtil::GetOnDemandConditionsFromJson(const nlohmann::json& obj,
553     const std::string& key, std::vector<OnDemandCondition>& out)
554 {
555     nlohmann::json conditionsJson;
556     if (obj.find(key.c_str()) == obj.end() || !obj[key.c_str()].is_array()) {
557         return;
558     }
559     conditionsJson = obj.at(key.c_str());
560     for (auto& condition : conditionsJson) {
561         std::string type;
562         GetStringFromJson(condition, "eventId", type);
563         std::string name;
564         GetStringFromJson(condition, "name", name);
565         std::string value;
566         GetStringFromJson(condition, "value", value);
567         int32_t eventId = 0;
568         if (type == SA_TAG_DEVICE_ON_LINE) {
569             eventId = DEVICE_ONLINE;
570         } else if (type == SA_TAG_SETTING_SWITCH) {
571             eventId = SETTING_SWITCH;
572         } else if (type == SA_TAG_COMMON_EVENT) {
573             eventId = COMMON_EVENT;
574         } else if (type == SA_TAG_PARAM) {
575             eventId = PARAM;
576         } else if (type == SA_TAG_TIEMD_EVENT) {
577             eventId = TIMED_EVENT;
578         } else {
579             HILOGW("invalid condition eventId: %{public}s", type.c_str());
580             continue;
581         }
582         std::map<std::string, std::string> extraMessages;
583         GetOnDemandExtraMessagesFromJson(condition, "extra-messages", extraMessages);
584         OnDemandCondition conditionEvent = {eventId, name, value, extraMessages};
585         out.emplace_back(conditionEvent);
586     }
587 }
588 
GetProcessName() const589 std::u16string ParseUtil::GetProcessName() const
590 {
591     return procName_;
592 }
593 
GetRealPath(const string & profilePath) const594 string ParseUtil::GetRealPath(const string& profilePath) const
595 {
596     char path[PATH_MAX] = {'\0'};
597     if (realpath(profilePath.c_str(), path) == nullptr) {
598         HILOGD("get real path fail");
599         return "";
600     }
601     string realPath(path);
602     return realPath;
603 }
604 
CheckPathExist(const string & profilePath)605 bool ParseUtil::CheckPathExist(const string& profilePath)
606 {
607     std::ifstream profileStream(profilePath.c_str());
608     return profileStream.good();
609 }
610 
ParseTrustConfig(const string & profilePath,std::map<std::u16string,std::set<int32_t>> & values)611 bool ParseUtil::ParseTrustConfig(const string& profilePath,
612     std::map<std::u16string, std::set<int32_t>>& values)
613 {
614     HILOGD("config path:%{private}s", profilePath.c_str());
615     string realPath = GetRealPath(profilePath);
616     if (!CheckPathExist(realPath.c_str())) {
617         HILOGE("bad profile path!");
618         return false;
619     }
620     nlohmann::json trustSaIdJson;
621     bool result = ParseJsonObj(trustSaIdJson, realPath);
622     if (!result) {
623         HILOGE("trust json file parse error!");
624         return false;
625     }
626     string process;
627     GetStringFromJson(trustSaIdJson, SA_TAG_PROCESS, process);
628     if (process.empty()) {
629         HILOGE("trust profile format error: no process tag");
630         return false;
631     }
632     if (process.length() > MAX_JSON_STRING_LENGTH) {
633         HILOGE("trust profile format error: process is too long");
634         return false;
635     }
636     auto& saIds = values[Str8ToStr16(process)];
637     GetIntArrayFromJson(trustSaIdJson, SA_TAG_SAID, saIds);
638     HILOGI("ParseTrustConfig realPath:%{public}s, saIds size = %{public}zu", realPath.c_str(), saIds.size());
639     return true;
640 }
641 
ParseJsonObj(nlohmann::json & jsonObj,const string & jsonPath)642 bool ParseUtil::ParseJsonObj(nlohmann::json& jsonObj, const string& jsonPath)
643 {
644     std::ifstream jsonFileStream;
645     jsonFileStream.open(jsonPath.c_str(), std::ios::in);
646     if (!jsonFileStream.is_open()) {
647         HILOGE("open json file error!!");
648         return false;
649     }
650     std::ostringstream buffer;
651     char ch;
652     int32_t readSize = 0;
653     while (buffer && jsonFileStream.get(ch)) {
654         readSize++;
655         if (readSize < MAX_JSON_OBJECT_SIZE) {
656             buffer.put(ch);
657         } else {
658             jsonFileStream.close();
659             HILOGE("too big json file error!!");
660             return false;
661         }
662     }
663     jsonFileStream.close();
664     string jsonStr = buffer.str();
665     jsonObj = nlohmann::json::parse(jsonStr, nullptr, false);
666     if (jsonObj.is_discarded()) {
667         HILOGE("parse json obj error!!");
668         return false;
669     }
670     return true;
671 }
672 
CheckLogicRelationship(const std::string & state,const std::string & profile)673 bool ParseUtil::CheckLogicRelationship(const std::string& state, const std::string& profile)
674 {
675     HILOGD("CheckLogicRelationship State:%{public}s || Profile:%{public}s", state.c_str(), profile.c_str());
676     if (profile.empty() || state == profile) {
677         return true;
678     }
679     if (state.empty()) {
680         return false;
681     }
682     int32_t logicRelationship = EQ;
683     int32_t valueStartPosition = 0;
684     if (profile[0] == '>') {
685         valueStartPosition ++;
686         if (profile[1] == '=') {
687             valueStartPosition ++;
688             logicRelationship = GREATER_EQ;
689         } else {
690             logicRelationship = GREATER;
691         }
692     } else if (profile[0] == '<') {
693         valueStartPosition ++;
694         if (profile[1] == '=') {
695             valueStartPosition ++;
696             logicRelationship = LESS_EQ;
697         } else {
698             logicRelationship = LESS;
699         }
700     }
701     int32_t stateInt, profileInt;
702     if (!StrToInt(profile.substr(valueStartPosition, profile.length() - 1), profileInt)) {
703         return false;
704     }
705     if (!StrToInt(state, stateInt)) {
706         return false;
707     }
708     if (logicRelationship == EQ) {
709         return stateInt == profileInt;
710     } else if (logicRelationship == GREATER_EQ) {
711         return stateInt >= profileInt;
712     } else if (logicRelationship == GREATER) {
713         return stateInt > profileInt;
714     } else if (logicRelationship == LESS_EQ) {
715         return stateInt <= profileInt;
716     } else if (logicRelationship == LESS) {
717         return stateInt < profileInt;
718     }
719     return false;
720 }
721 } // namespace OHOS
722