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 #include "suspend_source_parser.h"
16
17 #include <fstream>
18 #include <securec.h>
19 #include <unistd.h>
20
21 #include <cJSON.h>
22
23 #include "config_policy_utils.h"
24 #include "power_cjson_utils.h"
25 #include "power_log.h"
26 #include "setting_helper.h"
27 #ifdef POWER_MANAGER_ENABLE_CHARGING_TYPE_SETTING
28 #include "power_mgr_service.h"
29 #endif
30
31 namespace OHOS {
32 namespace PowerMgr {
33
34 namespace {
35 static const std::string POWER_SUSPEND_CONFIG_FILE = "etc/power_config/power_suspend.json";
36 static const std::string VENDOR_POWER_SUSPEND_CONFIG_FILE = "/vendor/etc/power_config/power_suspend.json";
37 static const std::string SYSTEM_POWER_SUSPEND_CONFIG_FILE = "/system/etc/power_config/power_suspend.json";
38 static const uint32_t ILLEGAL_ACTION = static_cast<uint32_t>(SuspendAction::ACTION_INVALID);
39 } // namespace
40
41 #ifdef POWER_MANAGER_ENABLE_CHARGING_TYPE_SETTING
ParseSources()42 std::shared_ptr<SuspendSources> SuspendSourceParser::ParseSources()
43 {
44 std::shared_ptr<SuspendSources> parseSources{nullptr};
45 auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
46 if (pms == nullptr) {
47 POWER_HILOGE(FEATURE_SUSPEND, "get PowerMgrService fail");
48 return parseSources;
49 }
50 bool isPowerConnected = pms->IsPowerConnected();
51 bool isSettingAcValid = SettingHelper::IsSettingAcSuspendSourcesValid();
52 bool isSettingDcValid = SettingHelper::IsSettingDcSuspendSourcesValid();
53 std::string configJsonStr;
54
55 if (!isSettingAcValid || !isSettingDcValid) {
56 std::string fileStringStr = GetSuspendSourcesByConfig();
57
58 if (!isSettingAcValid) {
59 SettingHelper::SetSettingAcSuspendSources(fileStringStr);
60 }
61 if (!isSettingDcValid) {
62 SettingHelper::SetSettingDcSuspendSources(fileStringStr);
63 }
64 configJsonStr = fileStringStr;
65 }
66
67 if (isPowerConnected && isSettingAcValid) {
68 configJsonStr = SettingHelper::GetSettingAcSuspendSources();
69 } else if (!isPowerConnected && isSettingDcValid) {
70 configJsonStr = SettingHelper::GetSettingDcSuspendSources();
71 }
72
73 parseSources = ParseSources(configJsonStr);
74 if (parseSources->GetParseErrorFlag()) {
75 POWER_HILOGI(FEATURE_SUSPEND, "call GetSuspendSourcesByConfig again");
76 configJsonStr = GetSuspendSourcesByConfig();
77 parseSources = ParseSources(configJsonStr);
78 }
79 return parseSources;
80 }
81 #else
ParseSources()82 std::shared_ptr<SuspendSources> SuspendSourceParser::ParseSources()
83 {
84 std::shared_ptr<SuspendSources> parseSources{nullptr};
85 bool isSettingUpdated = SettingHelper::IsSuspendSourcesSettingValid();
86 POWER_HILOGI(FEATURE_SUSPEND, "ParseSources setting=%{public}d", isSettingUpdated);
87 std::string configJsonStr;
88 if (isSettingUpdated) {
89 std::string sourcesSettingStr = SettingHelper::GetSettingSuspendSources();
90 configJsonStr = sourcesSettingStr;
91 #ifdef POWER_MANAGER_ENABLE_WATCH_UPDATE_ADAPT
92 // this branch means use config file for update scene in watch
93 if (sourcesSettingStr.find(SuspendSources::TP_COVER_KEY) == std::string::npos) {
94 configJsonStr = GetSuspendSourcesByConfig();
95 POWER_HILOGW(FEATURE_SUSPEND, "update scene need use (config file)");
96 }
97 #endif
98 } else {
99 configJsonStr = GetSuspendSourcesByConfig();
100 }
101 parseSources = ParseSources(configJsonStr);
102 if (parseSources->GetParseErrorFlag()) {
103 POWER_HILOGI(FEATURE_SUSPEND, "call GetSuspendSourcesByConfig again");
104 configJsonStr = GetSuspendSourcesByConfig();
105 parseSources = ParseSources(configJsonStr);
106 }
107 if (parseSources != nullptr) {
108 SettingHelper::SetSettingSuspendSources(configJsonStr);
109 }
110 return parseSources;
111 }
112 #endif
113
GetSuspendSourcesByConfig()114 const std::string SuspendSourceParser::GetSuspendSourcesByConfig()
115 {
116 std::string targetPath;
117 bool ret = GetTargetPath(targetPath);
118 if (ret == false) {
119 POWER_HILOGE(FEATURE_SUSPEND, "GetTargetPath fail");
120 return "";
121 }
122 POWER_HILOGI(FEATURE_SUSPEND, "use targetPath=%{public}s", targetPath.c_str());
123 std::ifstream inputStream(targetPath.c_str(), std::ios::in | std::ios::binary);
124 return std::string(std::istreambuf_iterator<char> {inputStream}, std::istreambuf_iterator<char> {});
125 }
126
GetTargetPath(std::string & targetPath)127 bool SuspendSourceParser::GetTargetPath(std::string& targetPath)
128 {
129 targetPath.clear();
130 bool ret = true;
131 char buf[MAX_PATH_LEN];
132 char* path = GetOneCfgFile(POWER_SUSPEND_CONFIG_FILE.c_str(), buf, MAX_PATH_LEN);
133 if (path != nullptr && *path != '\0') {
134 POWER_HILOGI(FEATURE_SUSPEND, "use policy path=%{public}s", path);
135 targetPath = path;
136 return true;
137 }
138
139 if (access(VENDOR_POWER_SUSPEND_CONFIG_FILE.c_str(), F_OK | R_OK) == -1) {
140 POWER_HILOGE(FEATURE_SUSPEND, "vendor suspend config is not exist or permission denied");
141 if (access(SYSTEM_POWER_SUSPEND_CONFIG_FILE.c_str(), F_OK | R_OK) == -1) {
142 POWER_HILOGE(FEATURE_SUSPEND, "system suspend config is not exist or permission denied");
143 ret = false;
144 } else {
145 targetPath = SYSTEM_POWER_SUSPEND_CONFIG_FILE;
146 }
147 } else {
148 targetPath = VENDOR_POWER_SUSPEND_CONFIG_FILE;
149 }
150 return ret;
151 }
152
ParseSources(const std::string & jsonStr)153 std::shared_ptr<SuspendSources> SuspendSourceParser::ParseSources(const std::string& jsonStr)
154 {
155 std::shared_ptr<SuspendSources> parseSources = std::make_shared<SuspendSources>();
156 cJSON* root = cJSON_Parse(jsonStr.c_str());
157 if (!root) {
158 POWER_HILOGE(FEATURE_SUSPEND, "json parse error");
159 parseSources->SetParseErrorFlag(true);
160 return parseSources;
161 }
162 if (!PowerMgrJsonUtils::IsValidJsonObjectOrJsonArray(root)) {
163 POWER_HILOGE(FEATURE_SUSPEND, "json root invalid[%{public}s]", jsonStr.c_str());
164 parseSources->SetParseErrorFlag(true);
165 cJSON_Delete(root);
166 return parseSources;
167 }
168
169 cJSON* item = nullptr;
170 cJSON_ArrayForEach(item, root) {
171 const char* key = item->string;
172 if (!key) {
173 POWER_HILOGI(FEATURE_SUSPEND, "invalid key in json object");
174 continue;
175 }
176 std::string keyStr = std::string(key);
177 bool ret = ParseSourcesProc(parseSources, item, keyStr);
178 if (ret == false) {
179 POWER_HILOGI(FEATURE_SUSPEND, "lost map config key");
180 continue;
181 }
182 }
183
184 cJSON_Delete(root);
185 return parseSources;
186 }
187
ParseSourcesProc(std::shared_ptr<SuspendSources> & parseSources,cJSON * valueObj,std::string & key)188 bool SuspendSourceParser::ParseSourcesProc(
189 std::shared_ptr<SuspendSources>& parseSources, cJSON* valueObj, std::string& key)
190 {
191 if (parseSources == nullptr) {
192 POWER_HILOGE(FEATURE_SUSPEND, "parseSources is nullptr");
193 return false;
194 }
195
196 SuspendDeviceType suspendDeviceType = SuspendSources::mapSuspendDeviceType(key);
197 if (suspendDeviceType == SuspendDeviceType::SUSPEND_DEVICE_REASON_MIN) {
198 return false;
199 }
200
201 uint32_t action = 0;
202 uint32_t delayMs = 0;
203 if (PowerMgrJsonUtils::IsValidJsonObject(valueObj)) {
204 cJSON* actionValue = cJSON_GetObjectItemCaseSensitive(valueObj, SuspendSource::ACTION_KEY);
205 cJSON* delayValue = cJSON_GetObjectItemCaseSensitive(valueObj, SuspendSource::DELAY_KEY);
206 if (PowerMgrJsonUtils::IsValidJsonNumber(actionValue) && PowerMgrJsonUtils::IsValidJsonNumber(delayValue)) {
207 action = static_cast<uint32_t>(actionValue->valueint);
208 delayMs = static_cast<uint32_t>(delayValue->valueint);
209 if (action >= ILLEGAL_ACTION) {
210 action = 0;
211 }
212 }
213 }
214
215 POWER_HILOGI(FEATURE_SUSPEND,
216 "ParseSourcesProc key=%{public}s, type=%{public}u, action=%{public}u, delayMs=%{public}u",
217 key.c_str(), suspendDeviceType, action, delayMs);
218 SuspendSource suspendSource = SuspendSource(suspendDeviceType, action, delayMs);
219 parseSources->PutSource(suspendSource);
220 return true;
221 }
222
223 } // namespace PowerMgr
224 } // namespace OHOS