1 /*
2 * Copyright (c) 2022-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 "battery_config.h"
17
18 #include "string_ex.h"
19 #include "config_policy_utils.h"
20
21 #include "battery_log.h"
22 #include "battery_mgr_cjson_utils.h"
23 #include "power_common.h"
24
25 namespace {
26 constexpr const char* BATTERY_CONFIG_PATH = "etc/battery/battery_config.json";
27 constexpr const char* SYSTEM_BATTERY_CONFIG_PATH = "/system/etc/battery/battery_config.json";
28 constexpr const char* VENDOR_BATTERY_CONFIG_PATH = "/vendor/etc/battery/battery_config.json";
29 constexpr const char* BATTERY_CONFIG_EXCEPTION_PATH = "";
30 constexpr int32_t MAP_KEY_INDEX = 0;
31 constexpr int32_t BEGIN_SOC_INDEX = 0;
32 constexpr int32_t END_SOC_INDEX = 1;
33 constexpr int32_t MAX_SOC_RANGE = 2;
34 constexpr int32_t RED_INDEX = 0;
35 constexpr int32_t GREEN_INDEX = 1;
36 constexpr int32_t BLUE_INDEX = 2;
37 constexpr int32_t MAX_RGB_RANGE = 3;
38 constexpr int32_t MAX_DEPTH = 5;
39 constexpr int32_t MIN_DEPTH = 1;
40 constexpr uint32_t MOVE_LEFT_16 = 16;
41 constexpr uint32_t MOVE_LEFT_8 = 8;
42 constexpr int32_t FIRST_BUTTON_INDEX = 0;
43 constexpr int32_t SECOND_BUTTON_INDEX = 1;
44 constexpr int32_t MAX_BUTTON_RANGE = 2;
45 }
46 namespace OHOS {
47 namespace PowerMgr {
48 std::shared_ptr<BatteryConfig> BatteryConfig::instance_ = nullptr;
49 std::mutex BatteryConfig::mutex_;
50
GetInstance()51 BatteryConfig& BatteryConfig::GetInstance()
52 {
53 std::lock_guard<std::mutex> lock(mutex_);
54 if (instance_ == nullptr) {
55 instance_ = std::make_shared<BatteryConfig>();
56 }
57 return *(instance_.get());
58 }
59
ParseConfig()60 bool BatteryConfig::ParseConfig()
61 {
62 char buf[MAX_PATH_LEN];
63 char* path = GetOneCfgFile(BATTERY_CONFIG_PATH, buf, MAX_PATH_LEN);
64 if (path == nullptr || *path == '\0') {
65 BATTERY_HILOGW(COMP_SVC, "GetOneCfgFile battery_config.json is NULL");
66 path = const_cast<char*>(BATTERY_CONFIG_EXCEPTION_PATH);
67 }
68 BATTERY_HILOGD(COMP_SVC, "GetOneCfgFile battery_config.json");
69
70 std::ifstream ifsConf;
71
72 RETURN_IF_WITH_RET(!OpenFile(ifsConf, path), false);
73
74 if (config_) {
75 cJSON_Delete(config_);
76 config_ = nullptr;
77 }
78
79 std::string content((std::istreambuf_iterator<char>(ifsConf)), std::istreambuf_iterator<char>());
80 config_ = cJSON_Parse(content.c_str());
81 ifsConf.close();
82 if (config_ == nullptr) {
83 const char* errorPtr = cJSON_GetErrorPtr();
84 BATTERY_HILOGW(FEATURE_CHARGING, "cJSON parse error: in %{public}s",
85 (errorPtr != nullptr) ? errorPtr : "unknown error");
86 return false;
87 }
88
89 if (BatteryMgrJsonUtils::IsEmptyJsonParse(config_)) {
90 cJSON_Delete(config_);
91 config_ = nullptr;
92 BATTERY_HILOGW(FEATURE_CHARGING, "cJSON parse result is empty, battery config is %{public}s", content.c_str());
93 return false;
94 } else {
95 ParseConfInner();
96 }
97 return true;
98 }
99
IsExist(std::string key) const100 bool BatteryConfig::IsExist(std::string key) const
101 {
102 cJSON* value = GetValue(key);
103 return (value && !cJSON_IsNull(value));
104 }
105
GetInt(std::string key,int32_t defVal) const106 int32_t BatteryConfig::GetInt(std::string key, int32_t defVal) const
107 {
108 cJSON* value = GetValue(key);
109 return (!BatteryMgrJsonUtils::IsValidJsonNumber(value)) ? defVal : static_cast<int32_t>(value->valueint);
110 }
111
GetLightConf() const112 const std::vector<BatteryConfig::LightConf>& BatteryConfig::GetLightConf() const
113 {
114 return lightConf_;
115 }
116
GetWirelessChargerConf() const117 bool BatteryConfig::GetWirelessChargerConf() const
118 {
119 return wirelessChargerEnable_;
120 }
121
GetCommonEventConf() const122 const std::vector<BatteryConfig::CommonEventConf>& BatteryConfig::GetCommonEventConf() const
123 {
124 return commonEventConf_;
125 }
126
OpenFile(std::ifstream & ifsConf,const std::string & configPath)127 bool BatteryConfig::OpenFile(std::ifstream& ifsConf, const std::string& configPath)
128 {
129 bool isOpen = false;
130 if (!configPath.empty()) {
131 ifsConf.open(configPath);
132 isOpen = ifsConf.is_open();
133 BATTERY_HILOGD(COMP_SVC, "open configPath file is %{public}d", isOpen);
134 }
135 RETURN_IF_WITH_RET(isOpen, true);
136
137 ifsConf.open(VENDOR_BATTERY_CONFIG_PATH);
138 isOpen = ifsConf.is_open();
139 BATTERY_HILOGI(COMP_SVC, "open then vendor battery_config.json is %{public}d", isOpen);
140 RETURN_IF_WITH_RET(isOpen, true);
141
142 ifsConf.open(SYSTEM_BATTERY_CONFIG_PATH);
143 isOpen = ifsConf.is_open();
144 BATTERY_HILOGI(COMP_SVC, "open then system battery_config.json is %{public}d", isOpen);
145 return isOpen;
146 }
147
ParseConfInner()148 void BatteryConfig::ParseConfInner()
149 {
150 lightConf_.clear();
151 ParseLightConf("low");
152 ParseLightConf("normal");
153 ParseLightConf("high");
154 BATTERY_HILOGD(COMP_SVC, "The battery light configuration size %{public}d",
155 static_cast<int32_t>(lightConf_.size()));
156 ParseWirelessChargerConf();
157 ParseBootActionsConf();
158 ParsePopupConf();
159 ParseNotificationConf();
160 }
161
ParseLightConf(std::string level)162 void BatteryConfig::ParseLightConf(std::string level)
163 {
164 cJSON* soc = GetValue("light." + level + ".soc");
165 cJSON* rgb = GetValue("light." + level + ".rgb");
166 if (!BatteryMgrJsonUtils::IsValidJsonArray(soc) || !BatteryMgrJsonUtils::IsValidJsonArray(rgb)) {
167 BATTERY_HILOGW(COMP_SVC, "The battery light %{public}s configuration is invalid.", level.c_str());
168 return;
169 }
170 if (cJSON_GetArraySize(soc) != MAX_SOC_RANGE) {
171 BATTERY_HILOGW(COMP_SVC, "The battery light %{public}s soc data length error.", level.c_str());
172 return;
173 }
174 cJSON* beginSocItem = cJSON_GetArrayItem(soc, BEGIN_SOC_INDEX);
175 cJSON* endSocItem = cJSON_GetArrayItem(soc, END_SOC_INDEX);
176 if (!BatteryMgrJsonUtils::IsValidJsonNumber(beginSocItem) || !BatteryMgrJsonUtils::IsValidJsonNumber(endSocItem)) {
177 BATTERY_HILOGW(COMP_SVC, "The battery light %{public}s soc data type error.", level.c_str());
178 return;
179 }
180 if (cJSON_GetArraySize(rgb) != MAX_RGB_RANGE) {
181 BATTERY_HILOGW(COMP_SVC, "The battery light %{public}s rgb data length error.", level.c_str());
182 return;
183 }
184 cJSON* redItem = cJSON_GetArrayItem(rgb, RED_INDEX);
185 cJSON* greenItem = cJSON_GetArrayItem(rgb, GREEN_INDEX);
186 cJSON* blueItem = cJSON_GetArrayItem(rgb, BLUE_INDEX);
187 if (!BatteryMgrJsonUtils::IsValidJsonNumber(redItem) || !BatteryMgrJsonUtils::IsValidJsonNumber(greenItem) ||
188 !BatteryMgrJsonUtils::IsValidJsonNumber(blueItem)) {
189 BATTERY_HILOGW(COMP_SVC, "The battery light %{public}s rgb data type error.", level.c_str());
190 return;
191 }
192 BatteryConfig::LightConf lightConf = {
193 .beginSoc = static_cast<int32_t>(beginSocItem->valueint),
194 .endSoc = static_cast<int32_t>(endSocItem->valueint),
195 .rgb = (static_cast<uint32_t>(redItem->valueint) << MOVE_LEFT_16) |
196 (static_cast<uint32_t>(greenItem->valueint) << MOVE_LEFT_8) |
197 static_cast<uint32_t>(blueItem->valueint)
198 };
199 lightConf_.push_back(lightConf);
200 }
201
ParseWirelessChargerConf()202 void BatteryConfig::ParseWirelessChargerConf()
203 {
204 cJSON* wirelessCharger = GetValue("wirelesscharger");
205 if (!BatteryMgrJsonUtils::IsValidJsonNumber(wirelessCharger)) {
206 BATTERY_HILOGW(COMP_SVC, "wirelesscharger is invalid");
207 return;
208 }
209 wirelessChargerEnable_ = static_cast<bool>(wirelessCharger->valueint);
210 }
211
ParseBootActionsConf()212 void BatteryConfig::ParseBootActionsConf()
213 {
214 cJSON* bootActionsConfig = GetValue("boot_actions");
215 if (!BatteryMgrJsonUtils::IsValidJsonObject(bootActionsConfig)) {
216 BATTERY_HILOGW(COMP_SVC, "boot_actions is invalid");
217 return;
218 }
219 ParseCommonEventConf(bootActionsConfig);
220 }
221
ParseCommonEventConf(const cJSON * bootActionsConfig)222 void BatteryConfig::ParseCommonEventConf(const cJSON* bootActionsConfig)
223 {
224 cJSON* commonEventConfs = cJSON_GetObjectItemCaseSensitive(bootActionsConfig, "sendcommonevent");
225 if (!BatteryMgrJsonUtils::IsValidJsonArray(commonEventConfs)) {
226 BATTERY_HILOGW(COMP_SVC, "The common event config is invalid");
227 return;
228 }
229 commonEventConf_.clear();
230 cJSON* commonEventConf = nullptr;
231 cJSON_ArrayForEach(commonEventConf, commonEventConfs) {
232 BatteryConfig::CommonEventConf tempCommonEventConf;
233 cJSON* eventName = cJSON_GetObjectItemCaseSensitive(commonEventConf, "event_name");
234 cJSON* sceneConfig = cJSON_GetObjectItemCaseSensitive(commonEventConf, "scene_config");
235 cJSON* sceneConfigName = sceneConfig ? cJSON_GetObjectItemCaseSensitive(sceneConfig, "name") : nullptr;
236 cJSON* sceneConfigEqual = sceneConfig ? cJSON_GetObjectItemCaseSensitive(sceneConfig, "equal") : nullptr;
237 cJSON* sceneConfigNotEqual = sceneConfig ?
238 cJSON_GetObjectItemCaseSensitive(sceneConfig, "not_equal") : nullptr;
239 cJSON* uevent = cJSON_GetObjectItemCaseSensitive(commonEventConf, "uevent");
240 if (!BatteryMgrJsonUtils::IsValidJsonString(eventName) ||
241 !BatteryMgrJsonUtils::IsValidJsonString(sceneConfigName) ||
242 !BatteryMgrJsonUtils::IsValidJsonString(uevent)) {
243 BATTERY_HILOGW(COMP_SVC, "parse common event config failed");
244 continue;
245 }
246 if (BatteryMgrJsonUtils::IsValidJsonString(sceneConfigEqual)) {
247 tempCommonEventConf.sceneConfigEqual = true;
248 tempCommonEventConf.sceneConfigValue = sceneConfigEqual->valuestring;
249 } else if (BatteryMgrJsonUtils::IsValidJsonString(sceneConfigNotEqual)) {
250 tempCommonEventConf.sceneConfigEqual = false;
251 tempCommonEventConf.sceneConfigValue = sceneConfigNotEqual->valuestring;
252 } else {
253 BATTERY_HILOGW(COMP_SVC, "parse expect value failed");
254 continue;
255 }
256 tempCommonEventConf.eventName = eventName->valuestring;
257 tempCommonEventConf.sceneConfigName = sceneConfigName->valuestring;
258 tempCommonEventConf.uevent = uevent->valuestring;
259 commonEventConf_.emplace_back(tempCommonEventConf);
260 }
261 BATTERY_HILOGI(COMP_SVC, "The battery commonevent configuration size %{public}d",
262 static_cast<int32_t>(commonEventConf_.size()));
263 }
264
GetPopupConf() const265 const std::unordered_map<std::string, std::vector<BatteryConfig::PopupConf>>& BatteryConfig::GetPopupConf() const
266 {
267 BATTERY_HILOGI(COMP_SVC, "GetPopupConf");
268 return popupConfig_;
269 }
270
ParsePopupConf()271 void BatteryConfig::ParsePopupConf()
272 {
273 cJSON* popupConfig = GetValue("popup");
274 if (!BatteryMgrJsonUtils::IsValidJsonObject(popupConfig)) {
275 BATTERY_HILOGW(COMP_SVC, "popupConfig invalid");
276 return;
277 }
278 popupConfig_.clear();
279 cJSON* valueObj = nullptr;
280 cJSON_ArrayForEach(valueObj, popupConfig) {
281 if (valueObj->string == nullptr) {
282 BATTERY_HILOGW(COMP_HDI, "Found null key in popup config");
283 continue;
284 }
285 std::string uevent = valueObj->string;
286 if (!BatteryMgrJsonUtils::IsValidJsonArray(valueObj)) {
287 BATTERY_HILOGW(COMP_SVC, "ueventConf invalid, key=%{public}s", uevent.c_str());
288 continue;
289 }
290 std::vector<BatteryConfig::PopupConf> popupConfVec;
291 cJSON* popupObj = nullptr;
292 cJSON_ArrayForEach(popupObj, valueObj) {
293 cJSON* popupName = cJSON_GetObjectItemCaseSensitive(popupObj, "name");
294 cJSON* popupAction = cJSON_GetObjectItemCaseSensitive(popupObj, "action");
295 if (!BatteryMgrJsonUtils::IsValidJsonString(popupName) ||
296 !BatteryMgrJsonUtils::IsValidJsonNumber(popupAction)) {
297 BATTERY_HILOGW(COMP_SVC, "popupObj invalid, key=%{public}s", uevent.c_str());
298 continue;
299 }
300 BatteryConfig::PopupConf popupCfg = {
301 .name = popupName->valuestring,
302 .action = static_cast<uint32_t>(popupAction->valueint)
303 };
304 BATTERY_HILOGI(COMP_SVC, "add popupConf %{public}s, %{public}d", popupCfg.name.c_str(), popupCfg.action);
305 popupConfVec.emplace_back(popupCfg);
306 }
307 BATTERY_HILOGI(COMP_SVC, "popupConfVec size: %{public}d", static_cast<int32_t>(popupConfVec.size()));
308 popupConfig_.emplace(uevent, popupConfVec);
309 }
310 BATTERY_HILOGI(COMP_SVC, "popupConfVec size: %{public}d", static_cast<int32_t>(popupConfig_.size()));
311 }
312
GetNotificationConf() const313 const std::unordered_map<std::string, BatteryConfig::NotificationConf>& BatteryConfig::GetNotificationConf() const
314 {
315 return notificationConfMap_;
316 }
317
ParseNotificationConf()318 void BatteryConfig::ParseNotificationConf()
319 {
320 cJSON* nConf = GetValue("notification");
321 if (!BatteryMgrJsonUtils::IsValidJsonArray(nConf)) {
322 BATTERY_HILOGW(COMP_SVC, "nConf is invalid");
323 return;
324 }
325 SaveNotificationConfToMap(nConf);
326 }
327
SaveNotificationConfToMap(cJSON * nConf)328 void BatteryConfig::SaveNotificationConfToMap(cJSON* nConf)
329 {
330 cJSON* conf = nullptr;
331 cJSON_ArrayForEach(conf, nConf) {
332 cJSON* nameObj = cJSON_GetObjectItemCaseSensitive(conf, "name");
333 cJSON* iconObj = cJSON_GetObjectItemCaseSensitive(conf, "icon");
334 cJSON* titleObj = cJSON_GetObjectItemCaseSensitive(conf, "title");
335 cJSON* textObj = cJSON_GetObjectItemCaseSensitive(conf, "text");
336 cJSON* buttonObj = cJSON_GetObjectItemCaseSensitive(conf, "button");
337 if (!BatteryMgrJsonUtils::IsValidJsonString(nameObj) || !BatteryMgrJsonUtils::IsValidJsonString(iconObj) ||
338 !BatteryMgrJsonUtils::IsValidJsonString(titleObj) || !BatteryMgrJsonUtils::IsValidJsonString(textObj) ||
339 !BatteryMgrJsonUtils::IsValidJsonArray(buttonObj)) {
340 BATTERY_HILOGW(COMP_SVC, "stringConf Parse failed");
341 continue;
342 }
343 if (cJSON_GetArraySize(buttonObj) != MAX_BUTTON_RANGE) {
344 BATTERY_HILOGW(COMP_SVC, "notificationConf button data length error");
345 continue;
346 }
347 cJSON* firstButton = cJSON_GetArrayItem(buttonObj, FIRST_BUTTON_INDEX);
348 cJSON* secondButton = cJSON_GetArrayItem(buttonObj, SECOND_BUTTON_INDEX);
349 if (!BatteryMgrJsonUtils::IsValidJsonObject(firstButton) ||
350 !BatteryMgrJsonUtils::IsValidJsonObject(secondButton)) {
351 BATTERY_HILOGW(COMP_SVC, "buttonConf is invalid");
352 continue;
353 }
354 cJSON* firstButtonNameObj = cJSON_GetObjectItemCaseSensitive(firstButton, "name");
355 cJSON* firstButtonActionObj = cJSON_GetObjectItemCaseSensitive(firstButton, "action");
356 cJSON* secondButtonNameObj = cJSON_GetObjectItemCaseSensitive(secondButton, "name");
357 cJSON* secondButtonActionObj = cJSON_GetObjectItemCaseSensitive(secondButton, "action");
358 if (!BatteryMgrJsonUtils::IsValidJsonString(firstButtonNameObj) ||
359 !BatteryMgrJsonUtils::IsValidJsonString(firstButtonActionObj) ||
360 !BatteryMgrJsonUtils::IsValidJsonString(secondButtonNameObj) ||
361 !BatteryMgrJsonUtils::IsValidJsonString(secondButtonActionObj)) {
362 BATTERY_HILOGW(COMP_SVC, "buttonConf Parse failed");
363 return;
364 }
365 std::string name = nameObj->valuestring;
366 BatteryConfig::NotificationConf notificationConf = {
367 .name = name,
368 .icon = iconObj->valuestring,
369 .title = titleObj->valuestring,
370 .text = textObj->valuestring,
371 .firstButton = std::make_pair(firstButtonNameObj->valuestring, firstButtonActionObj->valuestring),
372 .secondButton = std::make_pair(secondButtonNameObj->valuestring, secondButtonActionObj->valuestring)
373 };
374 BATTERY_HILOGI(COMP_SVC, "notificationConf name: %{public}s", name.c_str());
375 notificationConfMap_.emplace(name, notificationConf);
376 }
377 BATTERY_HILOGI(COMP_SVC, "notificationConf size: %{public}d", static_cast<int32_t>(notificationConfMap_.size()));
378 }
379
FindConf(const std::string & key) const380 cJSON* BatteryConfig::FindConf(const std::string& key) const
381 {
382 return (config_ && cJSON_IsObject(config_) && cJSON_HasObjectItem(config_, key.c_str())) ?
383 cJSON_GetObjectItemCaseSensitive(config_, key.c_str()) : nullptr;
384 }
385
SplitKey(const std::string & key,std::vector<std::string> & keys) const386 bool BatteryConfig::SplitKey(const std::string& key, std::vector<std::string>& keys) const
387 {
388 SplitStr(TrimStr(key), ".", keys);
389 return (keys.size() < MIN_DEPTH || keys.size() > MAX_DEPTH) ? false : true;
390 }
391
GetValue(std::string key) const392 cJSON* BatteryConfig::GetValue(std::string key) const
393 {
394 std::vector<std::string> keys;
395 if (!SplitKey(key, keys)) {
396 BATTERY_HILOGW(COMP_SVC, "The key does not meet the. key=%{public}s", key.c_str());
397 return nullptr;
398 }
399
400 cJSON* value = FindConf(keys[MAP_KEY_INDEX]);
401 if (!value || cJSON_IsNull(value)) {
402 BATTERY_HILOGD(COMP_SVC, "Value is empty. key=%{public}s", key.c_str());
403 return value;
404 }
405
406 for (size_t i = 1; i < keys.size(); ++i) {
407 if (!cJSON_IsObject(value) || !cJSON_HasObjectItem(value, keys[i].c_str())) {
408 BATTERY_HILOGW(COMP_SVC, "The key is not configured. key=%{public}s", keys[i].c_str());
409 break;
410 }
411 value = cJSON_GetObjectItemCaseSensitive(value, keys[i].c_str());
412 }
413 return value;
414 }
415 } // namespace PowerMgr
416 } // namespace OHOS
417