1 /*
2  * Copyright (c) 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 "standby_config_manager.h"
17 
18 #include <functional>
19 #include <string>
20 #include <sstream>
21 #include <unistd.h>
22 #include <dlfcn.h>
23 
24 #ifdef STANDBY_CONFIG_POLICY_ENABLE
25 #include "config_policy_utils.h"
26 #endif
27 #include "json_utils.h"
28 #include "standby_service_log.h"
29 
30 namespace OHOS {
31 namespace DevStandbyMgr {
32 namespace {
33     const std::string DEFAULT_CONFIG_ROOT_DIR = "/system";
34     const std::string STANDBY_CONFIG_PATH = "/etc/standby_service/device_standby_config.json";
35     const int32_t STANDBY_CONFIG_INDEX = 5;
36     const std::string STRATEGY_CONFIG_PATH = "/etc/standby_service/standby_strategy_config.json";
37     const int32_t STRATEGY_CONFIG_INDEX = 6;
38     const int32_t CLOUD_CONFIG_INDEX = 7;
39     const char* EXT_CONFIG_LIB = "libsuspend_manager_service.z.so";
40     const std::string TAG_PLUGIN_NAME = "plugin_name";
41     const std::string TAG_STANDBY = "standby";
42     const std::string TAG_MAINTENANCE_LIST = "maintenance_list";
43     const std::string TAG_DETECT_LIST = "detect_list";
44     const std::string TAG_STRATEGY_LIST = "strategy_list";
45     const std::string TAG_HALFHOUR_SWITCH_SETTING = "halfhour_switch_setting";
46     const std::string TAG_LADDER_BATTERY_LIST = "ladder_battery_threshold_list";
47 
48     const std::string TAG_SETTING_LIST = "setting_list";
49     const std::string TAG_VER = "version";
50     const int VERSION_LEN = 4;
51     const int DEC = 10;
52     const char VERSION_DELIM = '.';
53     const std::string TAG_CONDITION = "condition";
54     const std::string TAG_ACTION = "action";
55     const std::string TAG_ALLOW = "allow";
56     const std::string TAG_PROCESSES = "processes";
57     const std::string TAG_APPS = "apps";
58     const std::string TAG_PROCESSES_LIMIT = "processes_limit";
59     const std::string TAG_TIME_CLOCK_APPS = "time_clock_apps";
60     const std::string TAG_APPS_LIMIT = "apps_limit";
61     const std::string TAG_NAME = "name";
62     const std::string TAG_MAX_DURATION_LIM = "duration";
63 
64     const std::string TAG_TIMER = "TIMER";
65     const std::string TAG_TIMER_CLOCK = "timer_clock";
66     const std::string TAG_TIMER_PERIOD = "timer_period";
67 
68     const char TAG_CONDITION_DELIM = '&';
69     const std::string TAG_DAY_STANDBY = "day_standby";
70     const std::string TAG_NIGHT_STANDBY = "night_standby";
71     const std::string TAG_SCREENOFF = "screenoff";
72     const std::string TAG_SCREENOFF_HALFHOUR = "screenoff_halfhour";
73     const std::unordered_map<std::string, ConditionType::Type> conditionMap = {
74         {TAG_DAY_STANDBY, ConditionType::DAY_STANDBY},
75         {TAG_NIGHT_STANDBY, ConditionType::NIGHT_STANDBY},
76     };
77 }
78 
StandbyConfigManager()79 StandbyConfigManager::StandbyConfigManager() {}
80 
~StandbyConfigManager()81 StandbyConfigManager::~StandbyConfigManager() {}
82 
GetInstance()83 std::shared_ptr<StandbyConfigManager> StandbyConfigManager::GetInstance()
84 {
85     return DelayedSingleton<StandbyConfigManager>::GetInstance();
86 }
87 
Init()88 ErrCode StandbyConfigManager::Init()
89 {
90     STANDBYSERVICE_LOGI("start to read config");
91     LoadGetExtConfigFunc();
92     GetAndParseStandbyConfig();
93     GetAndParseStrategyConfig();
94     if (NeedsToReadCloudConfig()) {
95         GetCloudConfig();
96     }
97     return ERR_OK;
98 }
99 
GetAndParseStandbyConfig()100 void StandbyConfigManager::GetAndParseStandbyConfig()
101 {
102     std::vector<std::string> configContentList;
103     if (getExtConfigFunc_ != nullptr && getExtConfigFunc_(STANDBY_CONFIG_INDEX, configContentList) == ERR_OK) {
104         for (const auto& content : configContentList) {
105             nlohmann::json devStandbyConfigRoot;
106             if (!JsonUtils::LoadJsonValueFromContent(devStandbyConfigRoot, content)) {
107                 STANDBYSERVICE_LOGE("load config failed");
108                 continue;
109             }
110             if (!ParseDeviceStanbyConfig(devStandbyConfigRoot)) {
111                 STANDBYSERVICE_LOGE("parse config failed");
112             }
113         }
114     } else {
115         std::vector<std::string> configFileList = GetConfigFileList(STANDBY_CONFIG_PATH);
116         for (const auto& configFile : configFileList) {
117             nlohmann::json devStandbyConfigRoot;
118             // if failed to load one json file, read next config file
119             if (!JsonUtils::LoadJsonValueFromFile(devStandbyConfigRoot, configFile)) {
120                 STANDBYSERVICE_LOGE("load config file %{public}s failed", configFile.c_str());
121                 continue;
122             }
123             if (!ParseDeviceStanbyConfig(devStandbyConfigRoot)) {
124                 STANDBYSERVICE_LOGE("parse config file %{public}s failed", configFile.c_str());
125             }
126         }
127     }
128     UpdateStrategyList();
129 }
130 
GetAndParseStrategyConfig()131 void StandbyConfigManager::GetAndParseStrategyConfig()
132 {
133     std::vector<std::string> configContentList;
134     if (getExtConfigFunc_ != nullptr && getExtConfigFunc_(STRATEGY_CONFIG_INDEX, configContentList) == ERR_OK) {
135         for (const auto& content : configContentList) {
136             nlohmann::json resCtrlConfigRoot;
137             if (!JsonUtils::LoadJsonValueFromContent(resCtrlConfigRoot, content)) {
138                 STANDBYSERVICE_LOGE("load config failed");
139                 continue;
140             }
141             if (!ParseResCtrlConfig(resCtrlConfigRoot)) {
142                 STANDBYSERVICE_LOGE("parse config failed");
143             }
144         }
145     } else {
146         std::vector<std::string> configFileList = GetConfigFileList(STRATEGY_CONFIG_PATH);
147         for (const auto& configFile : configFileList) {
148             nlohmann::json resCtrlConfigRoot;
149             if (!JsonUtils::LoadJsonValueFromFile(resCtrlConfigRoot, configFile)) {
150                 STANDBYSERVICE_LOGE("load config file %{public}s failed", configFile.c_str());
151                 continue;
152             }
153             if (!ParseResCtrlConfig(resCtrlConfigRoot)) {
154                 STANDBYSERVICE_LOGE("parse config file %{public}s failed", configFile.c_str());
155             }
156         }
157     }
158 }
159 
GetCloudConfig()160 void StandbyConfigManager::GetCloudConfig()
161 {
162     if (getSingleExtConfigFunc_ == nullptr) {
163         return;
164     }
165     std::string configCloud;
166     int32_t returnCode = getSingleExtConfigFunc_(CLOUD_CONFIG_INDEX, configCloud);
167     if (returnCode == ERR_OK) {
168         nlohmann::json ConfigRoot;
169         JsonUtils::LoadJsonValueFromContent(ConfigRoot, configCloud);
170         ParseCloudConfig(ConfigRoot);
171     } else {
172         STANDBYSERVICE_LOGE("Decrypt errcode: %{public}d.", returnCode);
173     }
174     UpdateStrategyList();
175 }
176 
ParseCloudConfig(const nlohmann::json& devConfigRoot)177 void StandbyConfigManager::ParseCloudConfig(const nlohmann::json& devConfigRoot)
178 {
179     nlohmann::json settingConfig;
180     nlohmann::json listConfig;
181 
182     if (JsonUtils::GetObjFromJsonValue(devConfigRoot, TAG_SETTING_LIST, settingConfig) &&
183         !ParseStandbyConfig(settingConfig)) {
184         STANDBYSERVICE_LOGW("Failed to parse cloud config in %{public}s", TAG_SETTING_LIST.c_str());
185     }
186     if (JsonUtils::GetObjFromJsonValue(devConfigRoot, TAG_STRATEGY_LIST, listConfig) &&
187         !ParseStrategyListConfig(listConfig)) {
188         STANDBYSERVICE_LOGW("Failed to parse cloud config in %{public}s", TAG_STRATEGY_LIST.c_str());
189     }
190     if (!ParseResCtrlConfig(devConfigRoot)) {
191         STANDBYSERVICE_LOGW("Failed to parse cloud config in standby strategy.");
192     }
193 }
194 
LoadGetExtConfigFunc()195 void StandbyConfigManager::LoadGetExtConfigFunc()
196 {
197     auto handle = dlopen(EXT_CONFIG_LIB, RTLD_NOW);
198     if (!handle) {
199         STANDBYSERVICE_LOGE("not find lib");
200         return;
201     }
202     getExtConfigFunc_ = reinterpret_cast<GetExtConfigFunc>(dlsym(handle, "GetExtMultiConfig"));
203     getSingleExtConfigFunc_ = reinterpret_cast<GetSingleExtConfigFunc>(dlsym(handle, "GetExtConfig"));
204     if (!getSingleExtConfigFunc_) {
205         STANDBYSERVICE_LOGE("Failed to load GetExtConfig.");
206     }
207     if (!getExtConfigFunc_) {
208         STANDBYSERVICE_LOGE("get func failed");
209         dlclose(handle);
210     }
211 }
212 
NeedsToReadCloudConfig()213 bool StandbyConfigManager::NeedsToReadCloudConfig()
214 {
215     std::string cloudConfigVer;
216     std::string deviceConfigVer;
217     std::string strategyConfigVer;
218     if (!GetParamVersion(STANDBY_CONFIG_INDEX, deviceConfigVer)) {
219         STANDBYSERVICE_LOGE("failed to get the version of fileIndex: %{public}d", STANDBY_CONFIG_INDEX);
220     }
221     if (!GetParamVersion(STRATEGY_CONFIG_INDEX, strategyConfigVer)) {
222         STANDBYSERVICE_LOGE("failed to get the version of fileIndex: %{public}d", STRATEGY_CONFIG_INDEX);
223     }
224     if (!GetCloudVersion(CLOUD_CONFIG_INDEX, cloudConfigVer)) {
225         STANDBYSERVICE_LOGE("failed to get the version of fileIndex: %{public}d", CLOUD_CONFIG_INDEX);
226     }
227     std::string temp;
228     int result = CompareVersion(deviceConfigVer, strategyConfigVer);
229     if (result < 0) {
230         STANDBYSERVICE_LOGI("do not need to read cloud config.");
231         return false;
232     } else {
233         temp = (result > 0)? deviceConfigVer : strategyConfigVer;
234     }
235     bool ret = CompareVersion(cloudConfigVer, temp) > 0;
236     STANDBYSERVICE_LOGI("cloud config:%{public}d, cloud:%{public}s, device:%{public}s, strategy:%{public}s",
237         ret, cloudConfigVer.c_str(), deviceConfigVer.c_str(), strategyConfigVer.c_str());
238     return ret;
239 }
240 
CompareVersion(const std::string& configVerA, const std::string& configVerB)241 int StandbyConfigManager::CompareVersion(const std::string& configVerA, const std::string& configVerB)
242 {
243     if (!configVerA.empty() && configVerB.empty()) {
244         return 1;
245     }
246     if (configVerA.empty() && !configVerB.empty()) {
247         return 0;
248     }
249     if (configVerA.empty() && configVerB.empty()) {
250         return -1;
251     }
252     std::vector<std::string> segA = JsonUtils::SplitVersion(configVerA, VERSION_DELIM);
253     if (segA.size() != VERSION_LEN) {
254         STANDBYSERVICE_LOGE("segment size error: %{public}s", configVerA.c_str());
255         return -1;
256     }
257     std::vector<std::string> segB = JsonUtils::SplitVersion(configVerB, VERSION_DELIM);
258     if (segB.size() != VERSION_LEN) {
259         STANDBYSERVICE_LOGE("segment size error: %{public}s", configVerB.c_str());
260         return -1;
261     }
262     for (int i = 0; i < VERSION_LEN; i++) {
263         if (!isdigit(segA[i][0]) || !isdigit(segB[i][0])) {
264             STANDBYSERVICE_LOGE("segment not digit");
265             return -1;
266         }
267         if (segB[i] != segA[i]) {
268             int ret = (strtol(segB[i].c_str(), nullptr, DEC) < strtol(segA[i].c_str(), nullptr, DEC)) ? 1 : 0;
269             return ret;
270         }
271     }
272     return 1;
273 }
274 
GetParamVersion(const int32_t& fileIndex, std::string& version)275 bool StandbyConfigManager::GetParamVersion(const int32_t& fileIndex, std::string& version)
276 {
277     if (getExtConfigFunc_ == nullptr) {
278         return true;
279     }
280     if (fileIndex != STANDBY_CONFIG_INDEX && fileIndex != STRATEGY_CONFIG_INDEX) {
281         STANDBYSERVICE_LOGE("invalid input when getting version.");
282         return false;
283     }
284     std::vector<std::string> configContentList;
285     int32_t returnCode = getExtConfigFunc_(fileIndex, configContentList);
286     if (returnCode != ERR_OK) {
287         STANDBYSERVICE_LOGE("Decrypt fail.");
288         return false;
289     }
290     std::string tempVersion;
291     for (const auto& content : configContentList) {
292         nlohmann::json devStandbyConfigRoot;
293         if (!JsonUtils::LoadJsonValueFromContent(devStandbyConfigRoot, content)) {
294             continue;
295         }
296         if (!JsonUtils::GetStringFromJsonValue(devStandbyConfigRoot, TAG_VER, tempVersion)) {
297             STANDBYSERVICE_LOGE("failed to get version");
298             continue;
299         }
300         if (CompareVersion(tempVersion, version)) {
301             version = tempVersion;
302         }
303     }
304     return true;
305 }
306 
GetCloudVersion(const int32_t& fileIndex, std::string& version)307 bool StandbyConfigManager::GetCloudVersion(const int32_t& fileIndex, std::string& version)
308 {
309     if (getSingleExtConfigFunc_ == nullptr) {
310         return true;
311     }
312     if (fileIndex != CLOUD_CONFIG_INDEX) {
313         STANDBYSERVICE_LOGE("invalid input when getting version.");
314         return false;
315     }
316     std::string configCloud;
317     int32_t returnCode = getSingleExtConfigFunc_(fileIndex, configCloud);
318     if (returnCode != ERR_OK) {
319         STANDBYSERVICE_LOGE("Decrypt fail.");
320         return false;
321     }
322     nlohmann::json devStandbyConfigRoot;
323     JsonUtils::LoadJsonValueFromContent(devStandbyConfigRoot, configCloud);
324     if (!JsonUtils::GetStringFromJsonValue(devStandbyConfigRoot, TAG_VER, version)) {
325         STANDBYSERVICE_LOGE("failed to get version");
326     }
327     return true;
328 }
329 
GetConfigFileList(const std::string& relativeConfigPath)330 std::vector<std::string> StandbyConfigManager::GetConfigFileList(const std::string& relativeConfigPath)
331 {
332     std::list<std::string> rootDirList;
333 #ifdef STANDBY_CONFIG_POLICY_ENABLE
334         auto cfgDirList = GetCfgDirList();
335         if (cfgDirList != nullptr) {
336             for (const auto &cfgDir : cfgDirList->paths) {
337                 if (cfgDir == nullptr) {
338                     continue;
339                 }
340                 STANDBYSERVICE_LOGD("cfgDir: %{public}s ", cfgDir);
341                 rootDirList.emplace_back(cfgDir);
342             }
343             FreeCfgDirList(cfgDirList);
344         }
345 #endif
346     if (std::find(rootDirList.begin(), rootDirList.end(), DEFAULT_CONFIG_ROOT_DIR)
347         == rootDirList.end()) {
348         rootDirList.emplace_front(DEFAULT_CONFIG_ROOT_DIR);
349     }
350     std::string baseRealPath;
351     std::vector<std::string> configFilesList;
352     for (auto configDir : rootDirList) {
353         if (JsonUtils::GetRealPath(configDir + relativeConfigPath, baseRealPath)
354             && access(baseRealPath.c_str(), F_OK) == ERR_OK) {
355             STANDBYSERVICE_LOGD("Get valid base config file: %{public}s", baseRealPath.c_str());
356             configFilesList.emplace_back(baseRealPath);
357         }
358     }
359     return configFilesList;
360 }
361 
GetPluginName()362 const std::string& StandbyConfigManager::GetPluginName()
363 {
364     return pluginName_;
365 }
366 
GetDefaultConfig(const std::string& configName)367 nlohmann::json StandbyConfigManager::GetDefaultConfig(const std::string& configName)
368 {
369     return GetConfigWithName(configName, standbyStrategyConfigMap_);
370 }
371 
GetStandbySwitch(const std::string& switchName)372 bool StandbyConfigManager::GetStandbySwitch(const std::string& switchName)
373 {
374     return GetConfigWithName(switchName, standbySwitchMap_);
375 }
376 
GetStandbyParam(const std::string& paramName)377 int32_t StandbyConfigManager::GetStandbyParam(const std::string& paramName)
378 {
379     return GetConfigWithName(paramName, standbyParaMap_);
380 }
381 
GetStrategySwitch(const std::string& switchName)382 bool StandbyConfigManager::GetStrategySwitch(const std::string& switchName)
383 {
384     return GetConfigWithName(switchName, strategySwitchMap_);
385 }
386 
GetHalfHourSwitch(const std::string& switchName)387 bool StandbyConfigManager::GetHalfHourSwitch(const std::string& switchName)
388 {
389     return GetConfigWithName(switchName, halfhourSwitchMap_);
390 }
391 
GetResCtrlConfig(const std::string& switchName)392 std::shared_ptr<std::vector<DefaultResourceConfig>> StandbyConfigManager::GetResCtrlConfig(const
393     std::string& switchName)
394 {
395     return GetConfigWithName(switchName, defaultResourceConfigMap_);
396 }
397 
398 template<typename T>
GetConfigWithName(const std::string& switchName, std::unordered_map<std::string, T>& configMap)399 T StandbyConfigManager::GetConfigWithName(const std::string& switchName,
400     std::unordered_map<std::string, T>& configMap)
401 {
402     std::lock_guard<std::mutex> lock(configMutex_);
403     auto iter = configMap.find(switchName);
404     if (iter == configMap.end()) {
405         STANDBYSERVICE_LOGW("failed to find config %{public}s", switchName.c_str());
406         return T{};
407     }
408     return iter->second;
409 }
410 
GetTimerResConfig()411 const std::vector<TimerResourceConfig>& StandbyConfigManager::GetTimerResConfig()
412 {
413     return timerResConfigList_;
414 }
415 
GetStrategyConfigList(const std::string& switchName)416 bool StandbyConfigManager::GetStrategyConfigList(const std::string& switchName)
417 {
418     return GetConfigWithName(switchName, strategyListMap_);
419 }
420 
GetStrategyConfigList()421 const std::vector<std::string>& StandbyConfigManager::GetStrategyConfigList()
422 {
423     return strategyList_;
424 }
425 
GetStandbyDurationList(const std::string& switchName)426 std::vector<int32_t> StandbyConfigManager::GetStandbyDurationList(const std::string& switchName)
427 {
428     return GetConfigWithName(switchName, intervalListMap_);
429 }
430 
GetMaxDuration(const std::string& name, const std::string& paramName, uint32_t condition, bool isApp)431 int32_t StandbyConfigManager::GetMaxDuration(const std::string& name, const std::string& paramName,
432     uint32_t condition, bool isApp)
433 {
434     auto eligibleAllowTimeList = GetEligibleAllowTimeConfig(paramName, condition, true, isApp);
435     auto findConfigTask = [&name](const auto& it) { return it.name_ == name; };
436     auto it = std::find_if(eligibleAllowTimeList.begin(), eligibleAllowTimeList.end(), findConfigTask);
437     if (it == eligibleAllowTimeList.end()) {
438         return 0;
439     } else {
440         return it->maxDurationLim_;
441     }
442 }
443 
GetStandbyLadderBatteryList(const std::string& switchName)444 std::vector<int32_t> StandbyConfigManager::GetStandbyLadderBatteryList(const std::string& switchName)
445 {
446     return GetConfigWithName(switchName, ladderBatteryListMap_);
447 }
448 
GetEligibleAllowConfig(const std::string& paramName, uint32_t condition, bool isAllow, bool isApp, const std::function<void(bool, std::set<T>&, const DefaultResourceConfig&)>& func)449 template<typename T> std::set<T> StandbyConfigManager::GetEligibleAllowConfig(const std::string& paramName,
450     uint32_t condition, bool isAllow, bool isApp, const std::function<void(bool, std::set<T>&,
451     const DefaultResourceConfig&)>& func)
452 {
453     if (defaultResourceConfigMap_.find(paramName) == defaultResourceConfigMap_.end()) {
454         return {};
455     }
456     std::set<T> eligibleResCtrlConfig;
457     const auto& resCtrlConfig = *(defaultResourceConfigMap_.find(paramName)->second);
458     STANDBYSERVICE_LOGD("find duration from %{public}s, size is %{public}d",
459         paramName.c_str(), static_cast<int32_t>(resCtrlConfig.size()));
460     for (const auto& config : resCtrlConfig) {
461         if (config.isAllow_ != isAllow) {
462             continue;
463         }
464         bool isEligiable {false};
465         for (const auto configCondition : config.conditions_) {
466             if ((condition & configCondition) == configCondition) {
467                 isEligiable = true;
468                 break;
469             }
470         }
471         if (!isEligiable) {
472             continue;
473         }
474         func(isApp, eligibleResCtrlConfig, config);
475     }
476     STANDBYSERVICE_LOGD("eligibleResCtrlConfig size is %{public}d",
477         static_cast<int32_t>(eligibleResCtrlConfig.size()));
478     return eligibleResCtrlConfig;
479 }
480 
GetEligibleAllowTimeConfig(const std::string& paramName, uint32_t condition, bool isAllow, bool isApp)481 std::set<TimeLtdProcess> StandbyConfigManager::GetEligibleAllowTimeConfig(const std::string& paramName,
482     uint32_t condition, bool isAllow, bool isApp)
483 {
484     auto func = [](bool isApp, std::set<TimeLtdProcess>& eligibleResCtrlConfig,
485         const DefaultResourceConfig& config) {
486         if (isApp) {
487             eligibleResCtrlConfig.insert(config.timeLtdApps_.begin(), config.timeLtdApps_.end());
488         } else {
489             eligibleResCtrlConfig.insert(config.timeLtdProcesses_.begin(), config.timeLtdProcesses_.end());
490         }
491         STANDBYSERVICE_LOGD("after calculate, eligible size is %{public}d",
492             static_cast<int32_t>(eligibleResCtrlConfig.size()));
493     };
494     return GetEligibleAllowConfig<TimeLtdProcess>(paramName, condition, isAllow, isApp, func);
495 }
496 
GetEligiblePersistAllowConfig(const std::string& paramName, uint32_t condition, bool isAllow, bool isApp)497 std::set<std::string> StandbyConfigManager::GetEligiblePersistAllowConfig(const std::string& paramName,
498     uint32_t condition, bool isAllow, bool isApp)
499 {
500     auto func = [](bool isApp, std::set<std::string>& eligibleResCtrlConfig,
501         const DefaultResourceConfig& config) {
502         if (isApp) {
503             eligibleResCtrlConfig.insert(config.apps_.begin(), config.apps_.end());
504         } else {
505             eligibleResCtrlConfig.insert(config.processes_.begin(), config.processes_.end());
506         }
507     };
508     return GetEligibleAllowConfig<std::string>(paramName, condition, isAllow, isApp, func);
509 }
510 
ParseDeviceStanbyConfig(const nlohmann::json& devStandbyConfigRoot)511 bool StandbyConfigManager::ParseDeviceStanbyConfig(const nlohmann::json& devStandbyConfigRoot)
512 {
513     nlohmann::json standbyConfig;
514     nlohmann::json detectlist;
515     nlohmann::json standbySwitchConfig;
516     nlohmann::json standbyListConfig;
517     nlohmann::json standbyIntervalList;
518     nlohmann::json standbyBatteryList;
519 
520     JsonUtils::GetStringFromJsonValue(devStandbyConfigRoot, TAG_PLUGIN_NAME, pluginName_);
521     if (JsonUtils::GetObjFromJsonValue(devStandbyConfigRoot, TAG_STANDBY, standbyConfig) &&
522         !ParseStandbyConfig(standbyConfig)) {
523         STANDBYSERVICE_LOGW("failed to parse standby config in %{public}s", STANDBY_CONFIG_PATH.c_str());
524         return false;
525     }
526     if (JsonUtils::GetObjFromJsonValue(devStandbyConfigRoot, TAG_DETECT_LIST, detectlist) &&
527         !ParseStandbyConfig(detectlist)) {
528         STANDBYSERVICE_LOGW("failed to parse detect list in %{public}s", STANDBY_CONFIG_PATH.c_str());
529         return false;
530     }
531     if (JsonUtils::GetObjFromJsonValue(devStandbyConfigRoot, TAG_MAINTENANCE_LIST, standbyIntervalList) &&
532         !ParseIntervalList(standbyIntervalList)) {
533         STANDBYSERVICE_LOGW("failed to parse standby interval list in %{public}s", STANDBY_CONFIG_PATH.c_str());
534         return false;
535     }
536     if (JsonUtils::GetObjFromJsonValue(devStandbyConfigRoot, TAG_STRATEGY_LIST, standbyListConfig) &&
537         !ParseStrategyListConfig(standbyListConfig)) {
538         STANDBYSERVICE_LOGW("failed to parse strategy list config in %{public}s", STANDBY_CONFIG_PATH.c_str());
539         return false;
540     }
541 
542     if (JsonUtils::GetObjFromJsonValue(devStandbyConfigRoot, TAG_HALFHOUR_SWITCH_SETTING, standbyConfig)) {
543         if (!ParseHalfHourSwitchConfig(standbyConfig)) {
544             STANDBYSERVICE_LOGW("failed to parse halfhour config");
545             return false;
546         }
547     }
548 
549     if (JsonUtils::GetObjFromJsonValue(devStandbyConfigRoot, TAG_LADDER_BATTERY_LIST, standbyBatteryList) &&
550         !ParseBatteryList(standbyBatteryList)) {
551         STANDBYSERVICE_LOGW("failed to parse standby battery list in %{public}s", STANDBY_CONFIG_PATH.c_str());
552         return false;
553     }
554     return true;
555 }
556 
ParseStandbyConfig(const nlohmann::json& standbyConfig)557 bool StandbyConfigManager::ParseStandbyConfig(const nlohmann::json& standbyConfig)
558 {
559     bool ret = true;
560     for (const auto& element : standbyConfig.items()) {
561         if (!element.value().is_primitive()) {
562             STANDBYSERVICE_LOGW("there is unexpected type of key in standby config %{public}s", element.key().c_str());
563             ret = false;
564             continue;
565         }
566         if (element.value().is_boolean()) {
567             standbySwitchMap_[element.key()] = element.value().get<bool>();
568         } else if (element.value().is_number_integer()) {
569             if (element.value().get<int32_t>() < 0) {
570                 STANDBYSERVICE_LOGW("there is negative value in standby config %{public}s", element.key().c_str());
571                 ret = false;
572                 continue;
573             }
574             standbyParaMap_[element.key()] = element.value().get<int32_t>();
575         }
576     }
577     return ret;
578 }
579 
ParseIntervalList(const nlohmann::json& standbyIntervalList)580 bool StandbyConfigManager::ParseIntervalList(const nlohmann::json& standbyIntervalList)
581 {
582     bool ret = true;
583     for (const auto& element : standbyIntervalList.items()) {
584         if (!element.value().is_array()) {
585             STANDBYSERVICE_LOGW("there is unexpected value of %{public}s in standby interval list",
586                 element.key().c_str());
587             ret = false;
588             continue;
589         }
590         std::vector<int32_t> intervalList;
591         for (const int32_t interval : element.value()) {
592             intervalList.emplace_back(interval);
593         }
594         intervalListMap_.emplace(element.key(), std::move(intervalList));
595     }
596     return ret;
597 }
598 
ParseStrategyListConfig(const nlohmann::json& standbyListConfig)599 bool StandbyConfigManager::ParseStrategyListConfig(const nlohmann::json& standbyListConfig)
600 {
601     bool ret = true;
602     for (const auto& element : standbyListConfig.items()) {
603         if (!element.value().is_boolean()) {
604             STANDBYSERVICE_LOGW("there is unexpected type of value in half hour standby switch config %{public}s",
605                 element.key().c_str());
606             ret = false;
607             continue;
608         }
609         strategyListMap_[element.key()] = element.value().get<bool>();
610     }
611     return ret;
612 }
613 
UpdateStrategyList()614 void StandbyConfigManager::UpdateStrategyList()
615 {
616     strategyList_.clear();
617     for (const auto& it : strategyListMap_) {
618         if (it.second) {
619             strategyList_.emplace_back(it.first);
620         }
621     }
622     if (strategyList_.empty()) {
623         STANDBYSERVICE_LOGI("No strategy is set to true.");
624     }
625 }
626 
ParseHalfHourSwitchConfig(const nlohmann::json& halfHourSwitchConfig)627 bool StandbyConfigManager::ParseHalfHourSwitchConfig(const nlohmann::json& halfHourSwitchConfig)
628 {
629     bool ret = true;
630     for (const auto& element : halfHourSwitchConfig.items()) {
631         if (!element.value().is_boolean()) {
632             STANDBYSERVICE_LOGW("there is unexpected type of value in half hour standby switch config %{public}s",
633                 element.key().c_str());
634             ret = false;
635             return ret;
636         }
637         halfhourSwitchMap_[element.key()] = element.value().get<bool>();
638     }
639     return ret;
640 }
641 
ParseResCtrlConfig(const nlohmann::json& resCtrlConfigRoot)642 bool StandbyConfigManager::ParseResCtrlConfig(const nlohmann::json& resCtrlConfigRoot)
643 {
644     bool ret = true;
645     for (const auto& element : resCtrlConfigRoot.items()) {
646         standbyStrategyConfigMap_[element.key()] = element.value();
647         if (!element.value().is_array()) {
648             STANDBYSERVICE_LOGW("there is unexpected type of value in resource control config %{public}s",
649                 element.key().c_str());
650             ret = false;
651             continue;
652         }
653         std::string resCtrlKey = element.key();
654         if (!ParseDefaultResCtrlConfig(resCtrlKey, element.value())) {
655             STANDBYSERVICE_LOGW("there is error in config of %{public}s", resCtrlKey.c_str());
656             ret = false;
657             continue;
658         }
659         // parse exemption config of timer resource
660         if (resCtrlKey == TAG_TIMER && !ParseTimerResCtrlConfig(element.value())) {
661             STANDBYSERVICE_LOGW("there is error in config of %{public}s", resCtrlKey.c_str());
662             ret = false;
663             continue;
664         }
665     }
666     return ret;
667 }
668 
ParseTimerResCtrlConfig(const nlohmann::json& resConfigArray)669 bool StandbyConfigManager::ParseTimerResCtrlConfig(const nlohmann::json& resConfigArray)
670 {
671     if (!resConfigArray.is_array()) {
672         STANDBYSERVICE_LOGW("the value of timer config should be an array");
673         return false;
674     }
675     timerResConfigList_.clear();
676     for (const auto &singleConfigItem : resConfigArray) {
677         TimerResourceConfig timerResourceConfig;
678         if (!singleConfigItem.contains(TAG_TIME_CLOCK_APPS) || !singleConfigItem.at(TAG_TIME_CLOCK_APPS).is_array()) {
679             timerResConfigList_.emplace_back(std::move(timerResourceConfig));
680             continue;
681         }
682         const nlohmann::json& limitedAppItems = singleConfigItem.at(TAG_TIME_CLOCK_APPS);
683         for (const auto &singleLtdAppItem : limitedAppItems) {
684             TimerClockApp timerClockApp;
685             if (!JsonUtils::GetStringFromJsonValue(singleLtdAppItem, TAG_NAME, timerClockApp.name_) ||
686                 (!JsonUtils::GetBoolFromJsonValue(singleLtdAppItem, TAG_TIMER_CLOCK, timerClockApp.isTimerClock_) &&
687                 !JsonUtils::GetInt32FromJsonValue(singleLtdAppItem, TAG_TIMER_PERIOD, timerClockApp.timerPeriod_))) {
688                 STANDBYSERVICE_LOGW("there is error in timer clock config");
689                 return false;
690             }
691             timerResourceConfig.timerClockApps_.emplace_back(std::move(timerClockApp));
692         }
693         timerResConfigList_.emplace_back(std::move(timerResourceConfig));
694     }
695     return true;
696 }
697 
ParseDefaultResCtrlConfig(const std::string& resCtrlKey, const nlohmann::json& resConfigArray)698 bool StandbyConfigManager::ParseDefaultResCtrlConfig(const std::string& resCtrlKey,
699     const nlohmann::json& resConfigArray)
700 {
701     if (!resConfigArray.is_array()) {
702         STANDBYSERVICE_LOGW("the value of %{public}s should be an array", resCtrlKey.c_str());
703         return false;
704     }
705     auto defaultResConfigPtr = std::make_shared<std::vector<DefaultResourceConfig>>();
706     for (const auto &singleConfigItem : resConfigArray) {
707         DefaultResourceConfig defaultResourceConfig;
708         if (!ParseCommonResCtrlConfig(singleConfigItem, defaultResourceConfig)) {
709             STANDBYSERVICE_LOGW("the value of %{public}s can not be parsed", resCtrlKey.c_str());
710             return false;
711         }
712         defaultResConfigPtr->emplace_back(std::move(defaultResourceConfig));
713     }
714     defaultResourceConfigMap_[resCtrlKey] = defaultResConfigPtr;
715     STANDBYSERVICE_LOGI("succeed to parse the config of %{public}s", resCtrlKey.c_str());
716     return true;
717 }
718 
ParseCommonResCtrlConfig(const nlohmann::json& singleConfigItem, DefaultResourceConfig& resCtrlConfig)719 bool StandbyConfigManager::ParseCommonResCtrlConfig(const nlohmann::json& singleConfigItem,
720     DefaultResourceConfig& resCtrlConfig)
721 {
722     if (!singleConfigItem.contains(TAG_ACTION) || !singleConfigItem.contains(TAG_CONDITION)) {
723         STANDBYSERVICE_LOGW("there is no necessary field %{public}s or %{public}s",
724             TAG_ACTION.c_str(), TAG_CONDITION.c_str());
725         return false;
726     }
727     std::string resCtrlAction;
728     std::vector<std::string> conditionItemArray {};
729     if (!JsonUtils::GetStringFromJsonValue(singleConfigItem, TAG_ACTION, resCtrlAction) ||
730         !JsonUtils::GetStrArrFromJsonValue(singleConfigItem, TAG_CONDITION, conditionItemArray)) {
731         STANDBYSERVICE_LOGW("get necessary field %{public}s or %{public}s config failed",
732             TAG_ACTION.c_str(), TAG_CONDITION.c_str());
733         return false;
734     }
735     resCtrlConfig.isAllow_ = resCtrlAction == TAG_ALLOW;
736 
737     for (const auto &singleConditionItem : conditionItemArray) {
738         uint32_t conditionValue = ParseCondition(singleConditionItem);
739         if (conditionValue > 0) {
740             resCtrlConfig.conditions_.emplace_back(conditionValue);
741         }
742     }
743 
744     JsonUtils::GetStrArrFromJsonValue(singleConfigItem, TAG_PROCESSES, resCtrlConfig.processes_);
745     JsonUtils::GetStrArrFromJsonValue(singleConfigItem, TAG_APPS, resCtrlConfig.apps_);
746     ParseTimeLimitedConfig(singleConfigItem, TAG_PROCESSES_LIMIT, resCtrlConfig.timeLtdProcesses_);
747     ParseTimeLimitedConfig(singleConfigItem, TAG_APPS_LIMIT, resCtrlConfig.timeLtdApps_);
748     return true;
749 }
750 
ParseTimeLimitedConfig(const nlohmann::json& singleConfigItem, const std::string& key, std::vector<TimeLtdProcess>& timeLimitedConfig)751 void StandbyConfigManager::ParseTimeLimitedConfig(const nlohmann::json& singleConfigItem,
752     const std::string& key, std::vector<TimeLtdProcess>& timeLimitedConfig)
753 {
754     nlohmann::json timeLimitedItems;
755     if (!JsonUtils::GetArrayFromJsonValue(singleConfigItem, key, timeLimitedItems)) {
756         return;
757     }
758     for (const auto &singleLtdItem : timeLimitedItems) {
759         std::string name {};
760         int32_t duration {0};
761         if (!JsonUtils::GetStringFromJsonValue(singleLtdItem, TAG_NAME, name) ||
762             !JsonUtils::GetInt32FromJsonValue(singleLtdItem, TAG_MAX_DURATION_LIM, duration)) {
763             STANDBYSERVICE_LOGW("there is error in %{public}s config", key.c_str());
764             continue;
765         }
766         timeLimitedConfig.emplace_back(TimeLtdProcess{name, duration});
767     }
768 }
769 
ParseCondition(const std::string& conditionStr)770 uint32_t StandbyConfigManager::ParseCondition(const std::string& conditionStr)
771 {
772     uint32_t conditionValue = 0;
773     std::stringstream ss(conditionStr);
774     std::string conditionSubstr;
775     while (std::getline(ss, conditionSubstr, TAG_CONDITION_DELIM)) {
776         auto iter = conditionMap.find(conditionSubstr);
777         if (iter == conditionMap.end()) {
778             continue;
779         }
780         conditionValue |= iter->second;
781     }
782     return conditionValue;
783 }
784 
ParseBatteryList(const nlohmann::json& standbyBatteryList)785 bool StandbyConfigManager::ParseBatteryList(const nlohmann::json& standbyBatteryList)
786 {
787     bool ret = true;
788     for (const auto& element : standbyBatteryList.items()) {
789         if (!element.value().is_array()) {
790             STANDBYSERVICE_LOGW("there is unexpected value of %{public}s in standby battery list",
791                 element.key().c_str());
792             ret = false;
793             continue;
794         }
795         std::vector<int32_t> batterylList;
796         for (const int32_t battery : element.value()) {
797             batterylList.emplace_back(battery);
798         }
799         ladderBatteryListMap_.emplace(element.key(), std::move(batterylList));
800     }
801     return ret;
802 }
803 
DumpSetDebugMode(bool debugMode)804 void StandbyConfigManager::DumpSetDebugMode(bool debugMode)
805 {
806     std::lock_guard<std::mutex> lock(configMutex_);
807     if (debugMode) {
808         backStandbySwitchMap_ = standbySwitchMap_;
809         backStandbyParaMap_ = standbyParaMap_;
810     } else {
811         standbySwitchMap_ = backStandbySwitchMap_;
812         standbyParaMap_ = backStandbyParaMap_;
813         backStandbySwitchMap_.clear();
814         backStandbyParaMap_.clear();
815     }
816 }
817 
DumpSetSwitch(const std::string& switchName, bool switchStatus, std::string& result)818 void StandbyConfigManager::DumpSetSwitch(const std::string& switchName, bool switchStatus, std::string& result)
819 {
820     std::lock_guard<std::mutex> lock(configMutex_);
821     auto iter = standbySwitchMap_.find(switchName);
822     if (iter == standbySwitchMap_.end()) {
823         result += switchName + " not exist\n";
824         return;
825     }
826     iter->second = switchStatus;
827 }
828 
DumpSetParameter(const std::string& paramName, int32_t paramValue, std::string& result)829 void StandbyConfigManager::DumpSetParameter(const std::string& paramName, int32_t paramValue, std::string& result)
830 {
831     std::lock_guard<std::mutex> lock(configMutex_);
832     auto iter = standbyParaMap_.find(paramName);
833     if (iter == standbyParaMap_.end()) {
834         result += paramName + " not exist\n";
835         return;
836     }
837     iter->second = paramValue;
838 }
839 
DumpStandbyConfigInfo(std::string& result)840 void StandbyConfigManager::DumpStandbyConfigInfo(std::string& result)
841 {
842     std::lock_guard<std::mutex> lock(configMutex_);
843     std::stringstream stream;
844     for (const auto& [switchName, switchVal] : standbySwitchMap_) {
845         stream << switchName << ": " << (switchVal ? "true" : "false") << "\n";
846     }
847     for (const auto& [paraName, paraVal] : standbyParaMap_) {
848         stream << paraName << ": " << paraVal << "\n";
849     }
850     for (const auto& [strategyName, strategyVal] : strategySwitchMap_) {
851         stream << strategyName << ": " << (strategyVal ? "true" : "false") << "\n";
852     }
853     for (const auto& [strategyListName, strategyListVal] : strategyListMap_) {
854         stream << strategyListName << ": " << (strategyListVal ? "true" : "false") << "\n";
855     }
856     stream << "\n";
857     auto printConditions = [&stream](const int32_t& condition) { stream << "\t\t" << condition << " "; };
858     auto printProceses = [&stream](const std::string& process) { stream << "\t\t" << process << "\n"; };
859     auto printLtdProceses = [&stream](const TimeLtdProcess& timeLtdProcess) {
860         stream << "\t\t" << timeLtdProcess.name_ << " " << timeLtdProcess.maxDurationLim_ << "\n";
861         };
862     for (const auto& [resCtrlKey, resConfigVec] : defaultResourceConfigMap_) {
863         for (const auto& resConfig : *resConfigVec) {
864             stream << resCtrlKey << ": \n";
865             stream << "\tisAllow: " << resConfig.isAllow_ << "\n";
866             DumpResCtrlConfig<uint32_t>("conditions", resConfig.conditions_, stream, printConditions);
867             stream << "\n";
868             DumpResCtrlConfig<std::string>("processes", resConfig.processes_, stream, printProceses);
869             DumpResCtrlConfig<std::string>("apps", resConfig.apps_, stream, printProceses);
870             DumpResCtrlConfig<TimeLtdProcess>("timeLtdProcesses", resConfig.timeLtdProcesses_,
871                 stream, printLtdProceses);
872             DumpResCtrlConfig<TimeLtdProcess>("timeLtdApps", resConfig.timeLtdApps_, stream, printLtdProceses);
873         }
874     }
875     result += stream.str();
876     stream.str("");
877     stream.clear();
878 }
879 
DumpResCtrlConfig(const char* name, const std::vector<T>& configArray, std::stringstream& stream, const std::function<void(const T&)>& func)880 template<typename T> void StandbyConfigManager::DumpResCtrlConfig(const char* name, const std::vector<T>& configArray,
881     std::stringstream& stream, const std::function<void(const T&)>& func)
882 {
883     if (configArray.empty()) {
884         return;
885     }
886     stream << "\t" << name << ":\n";
887     for_each(configArray.begin(), configArray.end(), func);
888 }
889 }  // namespace DevStandbyMgr
890 }  // namespace OHOS