• 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 "battery_log.h"
19 #include <climits>
20 #include "string_ex.h"
21 #include "config_policy_utils.h"
22 #include "hdf_battery_json_utils.h"
23 
24 namespace OHOS {
25 namespace HDI {
26 namespace Battery {
27 namespace V2_0 {
28 namespace {
29 constexpr const char* BATTERY_CONFIG_PATH = "etc/battery/battery_config.json";
30 constexpr const char* SYSTEM_BATTERY_CONFIG_PATH = "/system/etc/battery/battery_config.json";
31 constexpr const char* VENDOR_BATTERY_CONFIG_PATH = "/vendor/etc/battery/battery_config.json";
32 constexpr const char* VENDOR_BATTERY_SPLIT_CONFIG_PATH = "/vendor/etc/battery/charge_config.json";
33 constexpr const char* BATTERY_CONFIG_EXCEPTION_PATH = "";
34 constexpr int32_t MAP_KEY_INDEX = 0;
35 constexpr int32_t BEGIN_SOC_INDEX = 0;
36 constexpr int32_t END_SOC_INDEX = 1;
37 constexpr int32_t MAX_SOC_RANGE = 2;
38 constexpr int32_t RED_INDEX = 0;
39 constexpr int32_t GREEN_INDEX = 1;
40 constexpr int32_t BLUE_INDEX = 2;
41 constexpr int32_t MAX_RGB_RANGE = 3;
42 constexpr int32_t MAX_DEPTH = 5;
43 constexpr int32_t MIN_DEPTH = 1;
44 constexpr uint32_t MOVE_LEFT_16 = 16;
45 constexpr uint32_t MOVE_LEFT_8 = 8;
46 constexpr uint32_t SYSTEM_PATH_CHECK = 4;
47 constexpr uint32_t DATA_PATH_CHECK = 5;
48 }
49 std::shared_ptr<BatteryConfig> BatteryConfig::instance_ = nullptr;
50 std::mutex BatteryConfig::mutex_;
51 
GetInstance()52 BatteryConfig& BatteryConfig::GetInstance()
53 {
54     std::lock_guard<std::mutex> lock(mutex_);
55     if (instance_ == nullptr) {
56         instance_ = std::make_shared<BatteryConfig>();
57     }
58     return *(instance_.get());
59 }
60 
ParseJsonStream(std::istream & ifsConf)61 cJSON* BatteryConfig::ParseJsonStream(std::istream& ifsConf)
62 {
63     std::string content((std::istreambuf_iterator<char>(ifsConf)), std::istreambuf_iterator<char>());
64     cJSON* config = cJSON_Parse(content.c_str());
65     if (config == nullptr) {
66         const char* errorPtr = cJSON_GetErrorPtr();
67         BATTERY_HILOGE(COMP_HDI, "cJSON parse error: in %{public}s",
68             (errorPtr != nullptr) ? errorPtr : "unknown error");
69         return nullptr;
70     }
71     if (HdfBatteryJsonUtils::IsEmptyJsonParse(config)) {
72         cJSON_Delete(config);
73         BATTERY_HILOGW(COMP_HDI, "cJSON parse result is empty, battery config is %{public}s", content.c_str());
74         return nullptr;
75     }
76     return config;
77 }
78 
ParseConfig()79 bool BatteryConfig::ParseConfig()
80 {
81     char buf[MAX_PATH_LEN];
82     char* path = GetOneCfgFile(BATTERY_CONFIG_PATH, buf, MAX_PATH_LEN);
83     if (path == nullptr || *path == '\0') {
84         BATTERY_HILOGW(COMP_HDI, "GetOneCfgFile battery_config.json is NULL");
85         path = const_cast<char*>(BATTERY_CONFIG_EXCEPTION_PATH);
86     }
87     BATTERY_HILOGD(COMP_HDI, "GetOneCfgFile battery_config.json");
88 
89     cJSON* config = nullptr;
90     std::ifstream ifsConf;
91     ifsConf.open(VENDOR_BATTERY_SPLIT_CONFIG_PATH);
92     bool isOpen = ifsConf.is_open();
93     if (isOpen) {
94         config = ParseJsonStream(ifsConf);
95         if (config) {
96             ParseConfSplit(config);
97             cJSON_Delete(config);
98         }
99         ifsConf.close();
100         config = nullptr;
101 
102         if (!OpenFile(ifsConf, path)) {
103             return false;
104         }
105         config = ParseJsonStream(ifsConf);
106         if (config) {
107             ParseConfInner(config);
108             cJSON_Delete(config);
109         }
110     } else {
111         if (!OpenFile(ifsConf, path)) {
112             return false;
113         }
114         config = ParseJsonStream(ifsConf);
115         if (config) {
116             ParseConfInner(config);
117             ParseConfSplit(config);
118             cJSON_Delete(config);
119         }
120     }
121     ifsConf.close();
122     config = nullptr;
123     return true;
124 }
125 
GetLightConfig() const126 const std::vector<BatteryConfig::LightConfig>& BatteryConfig::GetLightConfig() const
127 {
128     return lightConfig_;
129 }
130 
GetChargerConfig() const131 const BatteryConfig::ChargerConfig& BatteryConfig::GetChargerConfig() const
132 {
133     return chargerConfig_;
134 }
135 
GetChargeSceneConfigMap() const136 const std::map<std::string, BatteryConfig::ChargeSceneConfig>& BatteryConfig::GetChargeSceneConfigMap() const
137 {
138     return chargeSceneConfigMap_;
139 }
140 
GetUeventList() const141 const UeventMap& BatteryConfig::GetUeventList() const
142 {
143     return ueventMap_;
144 }
145 
DestroyInstance()146 void BatteryConfig::DestroyInstance()
147 {
148     std::lock_guard<std::mutex> lock(mutex_);
149     instance_ = nullptr;
150 }
151 
OpenFile(std::ifstream & ifsConf,const std::string & configPath)152 bool BatteryConfig::OpenFile(std::ifstream& ifsConf, const std::string& configPath)
153 {
154     bool isOpen = false;
155     if (!configPath.empty()) {
156         ifsConf.open(configPath);
157         isOpen = ifsConf.is_open();
158         BATTERY_HILOGD(COMP_HDI, "open file is %{public}d", isOpen);
159     }
160     if (isOpen) {
161         return true;
162     }
163 
164     ifsConf.open(VENDOR_BATTERY_CONFIG_PATH);
165     isOpen = ifsConf.is_open();
166     BATTERY_HILOGI(COMP_HDI, "open then vendor battery_config.json is %{public}d", isOpen);
167 
168     if (isOpen) {
169         return true;
170     }
171 
172     ifsConf.open(SYSTEM_BATTERY_CONFIG_PATH);
173     isOpen = ifsConf.is_open();
174     BATTERY_HILOGI(FEATURE_CHARGING, "open then system battery_config.json is %{public}d", isOpen);
175     return isOpen;
176 }
177 
ParseConfInner(const cJSON * config)178 void BatteryConfig::ParseConfInner(const cJSON* config)
179 {
180     BATTERY_HILOGI(COMP_HDI, "start parse battery config inner");
181     ParseLightConfig(GetValue(config, "light"));
182     ParseChargerConfig(GetValue(config, "charger"));
183 }
184 
ParseConfSplit(const cJSON * config)185 void BatteryConfig::ParseConfSplit(const cJSON* config)
186 {
187     BATTERY_HILOGI(COMP_HDI, "start parse split config inner");
188     ParseChargeSceneConfig(GetValue(config, "charge_scene"));
189     ParseUeventConfig(GetValue(config, "uevent"));
190 }
191 
ParseChargerConfig(const cJSON * chargerConfig)192 void BatteryConfig::ParseChargerConfig(const cJSON* chargerConfig)
193 {
194     if (!HdfBatteryJsonUtils::IsValidJsonObject(chargerConfig)) {
195         BATTERY_HILOGW(COMP_HDI, "chargerConfig is invalid");
196         return;
197     }
198 
199     cJSON* currentPath = GetValue(chargerConfig, "current_limit.path");
200     if (HdfBatteryJsonUtils::IsValidJsonString(currentPath)) {
201         chargerConfig_.currentPath = currentPath->valuestring;
202     }
203 
204     cJSON* voltagePath = GetValue(chargerConfig, "voltage_limit.path");
205     if (HdfBatteryJsonUtils::IsValidJsonString(voltagePath)) {
206         chargerConfig_.voltagePath = voltagePath->valuestring;
207     }
208 
209     cJSON* chargeTypePath = GetValue(chargerConfig, "type.path");
210     if (HdfBatteryJsonUtils::IsValidJsonString(chargeTypePath)) {
211         chargerConfig_.chargeTypePath = chargeTypePath->valuestring;
212     }
213     BATTERY_HILOGI(COMP_HDI, "The battery charger configuration parse succeed");
214 }
215 
ParseLightConfig(const cJSON * lightConfig)216 void BatteryConfig::ParseLightConfig(const cJSON* lightConfig)
217 {
218     if (!HdfBatteryJsonUtils::IsValidJsonObject(lightConfig)) {
219         BATTERY_HILOGW(COMP_HDI, "lightConf is invalid");
220         return;
221     }
222     lightConfig_.clear();
223     SaveJsonResult(lightConfig);
224     BATTERY_HILOGI(COMP_HDI, "The battery light configuration size %{public}d",
225         static_cast<int32_t>(lightConfig_.size()));
226 }
227 
SaveJsonResult(const cJSON * lightConfig)228 void BatteryConfig::SaveJsonResult(const cJSON* lightConfig)
229 {
230     cJSON* valueObj = nullptr;
231     cJSON_ArrayForEach(valueObj, lightConfig) {
232         if (valueObj->string == nullptr) {
233             BATTERY_HILOGW(COMP_HDI, "Found null key in light config");
234             continue;
235         }
236         const std::string key = valueObj->string;
237         if (cJSON_IsNull(valueObj) || !cJSON_IsObject(valueObj)) {
238             BATTERY_HILOGW(COMP_HDI, "The light conf is invalid, key=%{public}s", key.c_str());
239             continue;
240         }
241         cJSON* soc = GetValue(valueObj, "soc");
242         cJSON* rgb = GetValue(valueObj, "rgb");
243         if (!HdfBatteryJsonUtils::IsValidJsonArray(soc) || !HdfBatteryJsonUtils::IsValidJsonArray(rgb)) {
244             BATTERY_HILOGW(COMP_HDI, "The battery light %{public}s configuration is invalid.", key.c_str());
245             continue;
246         }
247         if (cJSON_GetArraySize(soc) != MAX_SOC_RANGE) {
248             BATTERY_HILOGW(COMP_HDI, "The battery light %{public}s soc data length error.", key.c_str());
249             continue;
250         }
251         cJSON* beginSocItem = cJSON_GetArrayItem(soc, BEGIN_SOC_INDEX);
252         cJSON* endSocItem = cJSON_GetArrayItem(soc, END_SOC_INDEX);
253         if (!HdfBatteryJsonUtils::IsValidJsonNumber(beginSocItem) ||
254             !HdfBatteryJsonUtils::IsValidJsonNumber(endSocItem)) {
255             BATTERY_HILOGW(COMP_HDI, "The battery light %{public}s soc data type error.", key.c_str());
256             continue;
257         }
258         if (cJSON_GetArraySize(rgb) != MAX_RGB_RANGE) {
259             BATTERY_HILOGW(COMP_HDI, "The battery light %{public}s rgb data length error.", key.c_str());
260             continue;
261         }
262         cJSON* redItem = cJSON_GetArrayItem(rgb, RED_INDEX);
263         cJSON* greenItem = cJSON_GetArrayItem(rgb, GREEN_INDEX);
264         cJSON* blueItem = cJSON_GetArrayItem(rgb, BLUE_INDEX);
265         if (!HdfBatteryJsonUtils::IsValidJsonNumber(redItem) || !HdfBatteryJsonUtils::IsValidJsonNumber(greenItem) ||
266             !HdfBatteryJsonUtils::IsValidJsonNumber(blueItem)) {
267             BATTERY_HILOGW(COMP_HDI, "The battery light %{public}s rgb data type error.", key.c_str());
268             continue;
269         }
270         BatteryConfig::LightConfig tempLightConfig = {
271             .beginSoc = static_cast<int32_t>(beginSocItem->valueint),
272             .endSoc = static_cast<int32_t>(endSocItem->valueint),
273             .rgb = (static_cast<uint32_t>(redItem->valueint) << MOVE_LEFT_16) |
274                 (static_cast<uint32_t>(greenItem->valueint) << MOVE_LEFT_8) | static_cast<uint32_t>(blueItem->valueint)
275         };
276         lightConfig_.push_back(tempLightConfig);
277     }
278 }
279 
ParseChargeSceneConfig(const cJSON * chargeSceneConfig)280 void BatteryConfig::ParseChargeSceneConfig(const cJSON* chargeSceneConfig)
281 {
282     if (!HdfBatteryJsonUtils::IsValidJsonObject(chargeSceneConfig)) {
283         BATTERY_HILOGW(COMP_HDI, "chargeSceneConfig is invalid");
284         return;
285     }
286 
287     chargeSceneConfigMap_.clear();
288     cJSON* valueObj = nullptr;
289     cJSON_ArrayForEach(valueObj, chargeSceneConfig) {
290         if (valueObj->string == nullptr) {
291             BATTERY_HILOGW(COMP_HDI, "Found null key in charge scene config");
292             continue;
293         }
294         const std::string key = valueObj->string;
295         if (!IsValidChargeSceneConfig(key, valueObj)) {
296             continue;
297         }
298 
299         BatteryConfig::ChargeSceneConfig tempChargeSceneConfig;
300         bool parseSupportPathResult = ParseChargeSceneSupport(valueObj, tempChargeSceneConfig);
301         bool parseSetPathResult = ParseChargeSceneSet(valueObj, tempChargeSceneConfig);
302         bool parseGetPathResult = ParseChargeSceneGet(valueObj, tempChargeSceneConfig);
303         if (parseSupportPathResult || parseSetPathResult || parseGetPathResult) {
304             chargeSceneConfigMap_.insert(std::make_pair(key, tempChargeSceneConfig));
305         }
306     }
307 
308     BATTERY_HILOGI(COMP_HDI, "The charge scene config size: %{public}d",
309         static_cast<int32_t>(chargeSceneConfigMap_.size()));
310 }
311 
IsValidChargeSceneConfig(const std::string & key,const cJSON * valueObj)312 bool BatteryConfig::IsValidChargeSceneConfig(const std::string& key, const cJSON* valueObj)
313 {
314     if (key.empty() || !HdfBatteryJsonUtils::IsValidJsonObject(valueObj)) {
315         BATTERY_HILOGW(COMP_HDI, "The charge scene config is invalid, key=%{public}s", key.c_str());
316         return false;
317     }
318 
319     cJSON* supportPath = GetValue(valueObj, "support.path");
320     cJSON* setPath = GetValue(valueObj, "set.path");
321     cJSON* getPath = GetValue(valueObj, "get.path");
322     if (!HdfBatteryJsonUtils::IsValidJsonString(supportPath) && !HdfBatteryJsonUtils::IsValidJsonString(setPath) &&
323         !HdfBatteryJsonUtils::IsValidJsonString(getPath)) {
324         BATTERY_HILOGW(COMP_HDI, "The charge scene config path is invalid, key=%{public}s", key.c_str());
325         return false;
326     }
327 
328     return true;
329 }
330 
ParseChargeSceneSupport(const cJSON * valueObj,BatteryConfig::ChargeSceneConfig & config)331 bool BatteryConfig::ParseChargeSceneSupport(const cJSON* valueObj, BatteryConfig::ChargeSceneConfig& config)
332 {
333     cJSON* supportPath = GetValue(valueObj, "support.path");
334     cJSON* type = GetValue(valueObj, "support.type");
335     cJSON* expectValue = GetValue(valueObj, "support.expect_value");
336     if (HdfBatteryJsonUtils::IsValidJsonString(supportPath)) {
337         std::string path = supportPath->valuestring;
338         if (IsValidSysPath(path)) {
339             config.supportPath = path;
340             config.type = HdfBatteryJsonUtils::IsValidJsonString(type) ? type->valuestring : "";
341             config.expectValue = HdfBatteryJsonUtils::IsValidJsonString(expectValue) ? expectValue->valuestring : "";
342             return true;
343         }
344     }
345     return false;
346 }
347 
ParseChargeSceneSet(const cJSON * valueObj,BatteryConfig::ChargeSceneConfig & config)348 bool BatteryConfig::ParseChargeSceneSet(const cJSON* valueObj, BatteryConfig::ChargeSceneConfig& config)
349 {
350     cJSON* setPath = GetValue(valueObj, "set.path");
351     if (HdfBatteryJsonUtils::IsValidJsonString(setPath)) {
352         std::string path = setPath->valuestring;
353         if (IsValidSysPath(path)) {
354             config.setPath = path;
355             return true;
356         }
357     }
358     return false;
359 }
360 
ParseChargeSceneGet(const cJSON * valueObj,BatteryConfig::ChargeSceneConfig & config)361 bool BatteryConfig::ParseChargeSceneGet(const cJSON* valueObj, BatteryConfig::ChargeSceneConfig& config)
362 {
363     cJSON* getPath = GetValue(valueObj, "get.path");
364     if (HdfBatteryJsonUtils::IsValidJsonString(getPath)) {
365         std::string path = getPath->valuestring;
366         if (IsValidSysPath(path)) {
367             config.getPath = path;
368             return true;
369         }
370     }
371     return false;
372 }
373 
IsValidSysPath(const std::string & path)374 bool BatteryConfig::IsValidSysPath(const std::string& path)
375 {
376     char resolvedPath[PATH_MAX] = {};
377     if ((realpath(path.c_str(), resolvedPath) == nullptr) ||
378         ((strncmp(resolvedPath, "/sys", SYSTEM_PATH_CHECK) != 0) &&
379         (strncmp(resolvedPath, "/data", DATA_PATH_CHECK) != 0))) {
380         return false;
381     }
382     return true;
383 }
384 
ParseUeventConfig(const cJSON * ueventConfig)385 void BatteryConfig::ParseUeventConfig(const cJSON* ueventConfig)
386 {
387     if (!HdfBatteryJsonUtils::IsValidJsonObject(ueventConfig)) {
388         BATTERY_HILOGW(COMP_HDI, "ueventConfig is invalid");
389         return;
390     }
391     ueventMap_.clear();
392     cJSON* valueObj = nullptr;
393     cJSON_ArrayForEach(valueObj, ueventConfig) {
394         if (valueObj->string == nullptr) {
395             BATTERY_HILOGW(COMP_HDI, "Found null key in uevent config");
396             continue;
397         }
398         const std::string key = valueObj->string;
399         if (cJSON_IsNull(valueObj) || !cJSON_IsObject(valueObj)) {
400             BATTERY_HILOGW(COMP_HDI, "The uevent conf is invalid, key=%{public}s", key.c_str());
401             continue;
402         }
403 
404         std::vector<std::pair<std::string, std::string>> ueventList;
405         cJSON* subChild = nullptr;
406         cJSON_ArrayForEach(subChild, valueObj) {
407             if (subChild->string == nullptr) {
408                 BATTERY_HILOGW(COMP_SVC, "Found null key in uevent conf");
409                 continue;
410             }
411             const std::string event = subChild->string;
412             if (!HdfBatteryJsonUtils::IsValidJsonString(subChild)) {
413                 BATTERY_HILOGW(COMP_SVC, "The uevent conf is invalid, key=%{public}s", key.c_str());
414                 continue;
415             }
416             std::string act = subChild->valuestring;
417             ueventList.emplace_back(std::make_pair(event, act));
418         }
419 
420         ueventMap_.emplace(key, ueventList);
421         BATTERY_HILOGI(COMP_HDI, "%{public}s size: %{public}d", key.c_str(), static_cast<int32_t>(ueventList.size()));
422     }
423     BATTERY_HILOGI(COMP_HDI, "The uevent config size: %{public}d", static_cast<int32_t>(ueventMap_.size()));
424 }
425 
SplitKey(const std::string & key,std::vector<std::string> & keys) const426 bool BatteryConfig::SplitKey(const std::string& key, std::vector<std::string>& keys) const
427 {
428     SplitStr(TrimStr(key), ".", keys);
429     return (keys.size() < MIN_DEPTH || keys.size() > MAX_DEPTH) ? false : true;
430 }
431 
GetValue(const cJSON * config,std::string key) const432 cJSON* BatteryConfig::GetValue(const cJSON* config, std::string key) const
433 {
434     std::vector<std::string> keys;
435     if (!SplitKey(key, keys)) {
436         BATTERY_HILOGW(COMP_HDI, "The key does not meet the. key=%{public}s", key.c_str());
437         return nullptr;
438     }
439 
440     std::string firstKey = keys[MAP_KEY_INDEX];
441     cJSON* value = (config && cJSON_IsObject(config) && cJSON_HasObjectItem(config, firstKey.c_str())) ?
442         cJSON_GetObjectItemCaseSensitive(config, firstKey.c_str()) : nullptr;
443     if (!value || cJSON_IsNull(value)) {
444         BATTERY_HILOGD(COMP_HDI, "Value is empty. key=%{public}s", key.c_str());
445         return value;
446     }
447 
448     for (size_t i = 1; i < keys.size(); ++i) {
449         if (!cJSON_IsObject(value) || !cJSON_HasObjectItem(value, keys[i].c_str())) {
450             BATTERY_HILOGW(COMP_HDI, "The key is not configured. key=%{public}s", keys[i].c_str());
451             break;
452         }
453         value = cJSON_GetObjectItemCaseSensitive(value, keys[i].c_str());
454     }
455     return value;
456 }
457 }  // namespace V2_0
458 }  // namespace Battery
459 }  // namespace HDI
460 }  // namespace OHOS
461