• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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