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