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