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