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