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 "power_common.h"
23
24 namespace {
25 constexpr const char* BATTERY_CONFIG_PATH = "etc/battery/battery_config.json";
26 constexpr const char* SYSTEM_BATTERY_CONFIG_PATH = "/system/etc/battery/battery_config.json";
27 constexpr const char* VENDOR_BATTERY_CONFIG_PATH = "/vendor/etc/battery/battery_config.json";
28 constexpr const char* BATTERY_CONFIG_EXCEPTION_PATH = "";
29 constexpr int32_t MAP_KEY_INDEX = 0;
30 constexpr int32_t BEGIN_SOC_INDEX = 0;
31 constexpr int32_t END_SOC_INDEX = 1;
32 constexpr int32_t MAX_SOC_RANGE = 2;
33 constexpr int32_t RED_INDEX = 0;
34 constexpr int32_t GREEN_INDEX = 1;
35 constexpr int32_t BLUE_INDEX = 2;
36 constexpr int32_t MAX_RGB_RANGE = 3;
37 constexpr int32_t MAX_DEPTH = 5;
38 constexpr int32_t MIN_DEPTH = 1;
39 constexpr uint32_t MOVE_LEFT_16 = 16;
40 constexpr uint32_t MOVE_LEFT_8 = 8;
41 constexpr int32_t FIRST_BUTTON_INDEX = 0;
42 constexpr int32_t SECOND_BUTTON_INDEX = 1;
43 constexpr int32_t MAX_BUTTON_RANGE = 2;
44 }
45 namespace OHOS {
46 namespace PowerMgr {
47 std::shared_ptr<BatteryConfig> BatteryConfig::instance_ = nullptr;
48 std::mutex BatteryConfig::mutex_;
49
GetInstance()50 BatteryConfig& BatteryConfig::GetInstance()
51 {
52 std::lock_guard<std::mutex> lock(mutex_);
53 if (instance_ == nullptr) {
54 instance_ = std::make_shared<BatteryConfig>();
55 }
56 return *(instance_.get());
57 }
58
ParseConfig()59 bool BatteryConfig::ParseConfig()
60 {
61 char buf[MAX_PATH_LEN];
62 char* path = GetOneCfgFile(BATTERY_CONFIG_PATH, buf, MAX_PATH_LEN);
63 if (path == nullptr || *path == '\0') {
64 BATTERY_HILOGW(COMP_SVC, "GetOneCfgFile battery_config.json is NULL");
65 path = const_cast<char*>(BATTERY_CONFIG_EXCEPTION_PATH);
66 }
67 BATTERY_HILOGD(COMP_SVC, "GetOneCfgFile battery_config.json");
68
69 Json::CharReaderBuilder readerBuilder;
70 std::ifstream ifsConf;
71
72 RETURN_IF_WITH_RET(!OpenFile(ifsConf, path), false);
73
74 config_.clear();
75 readerBuilder["collectComments"] = false;
76 JSONCPP_STRING errs;
77
78 if (parseFromStream(readerBuilder, ifsConf, &config_, &errs) && !config_.empty()) {
79 ParseConfInner();
80 }
81 ifsConf.close();
82 return true;
83 }
84
IsExist(std::string key) const85 bool BatteryConfig::IsExist(std::string key) const
86 {
87 return !GetValue(key).isNull();
88 }
89
GetInt(std::string key,int32_t defVal) const90 int32_t BatteryConfig::GetInt(std::string key, int32_t defVal) const
91 {
92 Json::Value value = GetValue(key);
93 return (value.isNull() || !value.isInt()) ? defVal : value.asInt();
94 }
95
GetLightConf() const96 const std::vector<BatteryConfig::LightConf>& BatteryConfig::GetLightConf() const
97 {
98 return lightConf_;
99 }
100
GetWirelessChargerConf() const101 bool BatteryConfig::GetWirelessChargerConf() const
102 {
103 return wirelessChargerEnable_;
104 }
105
GetCommonEventConf() const106 const std::vector<BatteryConfig::CommonEventConf>& BatteryConfig::GetCommonEventConf() const
107 {
108 return commonEventConf_;
109 }
110
OpenFile(std::ifstream & ifsConf,const std::string & configPath)111 bool BatteryConfig::OpenFile(std::ifstream& ifsConf, const std::string& configPath)
112 {
113 bool isOpen = false;
114 if (!configPath.empty()) {
115 ifsConf.open(configPath);
116 isOpen = ifsConf.is_open();
117 BATTERY_HILOGD(COMP_SVC, "open configPath file is %{public}d", isOpen);
118 }
119 RETURN_IF_WITH_RET(isOpen, true);
120
121 ifsConf.open(VENDOR_BATTERY_CONFIG_PATH);
122 isOpen = ifsConf.is_open();
123 BATTERY_HILOGI(COMP_SVC, "open then vendor battery_config.json is %{public}d", isOpen);
124 RETURN_IF_WITH_RET(isOpen, true);
125
126 ifsConf.open(SYSTEM_BATTERY_CONFIG_PATH);
127 isOpen = ifsConf.is_open();
128 BATTERY_HILOGI(COMP_SVC, "open then system battery_config.json is %{public}d", isOpen);
129 return isOpen;
130 }
131
ParseConfInner()132 void BatteryConfig::ParseConfInner()
133 {
134 lightConf_.clear();
135 ParseLightConf("low");
136 ParseLightConf("normal");
137 ParseLightConf("high");
138 BATTERY_HILOGD(COMP_SVC, "The battery light configuration size %{public}d",
139 static_cast<int32_t>(lightConf_.size()));
140 ParseWirelessChargerConf();
141 ParseBootActionsConf();
142 ParsePopupConf();
143 ParseNotificationConf();
144 }
145
ParseLightConf(std::string level)146 void BatteryConfig::ParseLightConf(std::string level)
147 {
148 Json::Value soc = GetValue("light." + level + ".soc");
149 Json::Value rgb = GetValue("light." + level + ".rgb");
150 if (!soc.isArray() || !rgb.isArray()) {
151 BATTERY_HILOGW(COMP_SVC, "The battery light %{public}s configuration is invalid.", level.c_str());
152 return;
153 }
154
155 if (soc.size() != MAX_SOC_RANGE || !soc[BEGIN_SOC_INDEX].isInt() || !soc[END_SOC_INDEX].isInt()) {
156 BATTERY_HILOGW(COMP_SVC, "The battery light %{public}s soc data type error.", level.c_str());
157 return;
158 }
159 if (rgb.size() != MAX_RGB_RANGE || !rgb[RED_INDEX].isUInt() || !rgb[GREEN_INDEX].isUInt() ||
160 !rgb[BLUE_INDEX].isUInt()) {
161 BATTERY_HILOGW(COMP_SVC, "The battery light %{public}s rgb data type error.", level.c_str());
162 return;
163 }
164 BatteryConfig::LightConf lightConf = {
165 .beginSoc = soc[BEGIN_SOC_INDEX].asInt(),
166 .endSoc = soc[END_SOC_INDEX].asInt(),
167 .rgb = (rgb[RED_INDEX].asUInt() << MOVE_LEFT_16) |
168 (rgb[GREEN_INDEX].asUInt() << MOVE_LEFT_8) |
169 rgb[BLUE_INDEX].asUInt()
170 };
171 lightConf_.push_back(lightConf);
172 }
173
ParseWirelessChargerConf()174 void BatteryConfig::ParseWirelessChargerConf()
175 {
176 Json::Value wirelessCharger = GetValue("wirelesscharger");
177 if (wirelessCharger.isNull() || !wirelessCharger.isInt()) {
178 BATTERY_HILOGW(COMP_SVC, "wirelesscharger is invalid");
179 return;
180 }
181 wirelessChargerEnable_ = static_cast<bool>(wirelessCharger.asInt());
182 }
183
ParseBootActionsConf()184 void BatteryConfig::ParseBootActionsConf()
185 {
186 Json::Value bootActionsConfig = GetValue("boot_actions");
187 if (bootActionsConfig.isNull() || !bootActionsConfig.isObject()) {
188 BATTERY_HILOGW(COMP_SVC, "boot_actions is invalid");
189 return;
190 }
191 ParseCommonEventConf(bootActionsConfig);
192 }
193
ParseCommonEventConf(const Json::Value & bootActionsConfig)194 void BatteryConfig::ParseCommonEventConf(const Json::Value& bootActionsConfig)
195 {
196 Json::Value commonEventConfs = bootActionsConfig["sendcommonevent"];
197 if (commonEventConfs.isNull() || !commonEventConfs.isArray()) {
198 BATTERY_HILOGW(COMP_SVC, "The common event config is invalid");
199 return;
200 }
201 commonEventConf_.clear();
202 for (const auto& commonEventConf : commonEventConfs) {
203 BatteryConfig::CommonEventConf tempCommonEventConf;
204 Json::Value eventName = commonEventConf["event_name"];
205 Json::Value sceneConfigName = commonEventConf["scene_config"]["name"];
206 Json::Value sceneConfigEqual = commonEventConf["scene_config"]["equal"];
207 Json::Value sceneConfigNotEqual = commonEventConf["scene_config"]["not_equal"];
208 Json::Value uevent = commonEventConf["uevent"];
209 if (!eventName.isString() || !sceneConfigName.isString() || !uevent.isString()) {
210 BATTERY_HILOGW(COMP_SVC, "parse common event config failed");
211 continue;
212 }
213 if (!sceneConfigEqual.isNull() && sceneConfigEqual.isString()) {
214 tempCommonEventConf.sceneConfigEqual = true;
215 tempCommonEventConf.sceneConfigValue = sceneConfigEqual.asString();
216 } else if (!sceneConfigNotEqual.isNull() && sceneConfigNotEqual.isString()) {
217 tempCommonEventConf.sceneConfigEqual = false;
218 tempCommonEventConf.sceneConfigValue = sceneConfigNotEqual.asString();
219 } else {
220 BATTERY_HILOGW(COMP_SVC, "parse expect value failed");
221 continue;
222 }
223 tempCommonEventConf.eventName = eventName.asString();
224 tempCommonEventConf.sceneConfigName = sceneConfigName.asString();
225 tempCommonEventConf.uevent = uevent.asString();
226 commonEventConf_.push_back(tempCommonEventConf);
227 }
228 BATTERY_HILOGI(COMP_SVC, "The battery commonevent configuration size %{public}d",
229 static_cast<int32_t>(commonEventConf_.size()));
230 }
231
GetPopupConf() const232 const std::unordered_map<std::string, std::vector<BatteryConfig::PopupConf>>& BatteryConfig::GetPopupConf() const
233 {
234 BATTERY_HILOGI(COMP_SVC, "GetPopupConf");
235 return popupConfig_;
236 }
237
ParsePopupConf()238 void BatteryConfig::ParsePopupConf()
239 {
240 Json::Value popupConfig = GetValue("popup");
241 if (popupConfig.isNull() || !popupConfig.isObject()) {
242 BATTERY_HILOGW(COMP_SVC, "popupConfig invalid");
243 return;
244 }
245 popupConfig_.clear();
246 Json::Value::Members members = popupConfig.getMemberNames();
247 for (auto iter = members.begin(); iter != members.end(); iter++) {
248 std::string uevent = *iter;
249 Json::Value valueObj = popupConfig[uevent];
250 if (valueObj.isNull() || !valueObj.isArray()) {
251 BATTERY_HILOGW(COMP_SVC, "ueventConf invalid, key=%{public}s", uevent.c_str());
252 continue;
253 }
254 std::vector<BatteryConfig::PopupConf> popupConfVec;
255 for (const auto& popupObj : valueObj) {
256 Json::Value popupName = popupObj["name"];
257 Json::Value popupAction = popupObj["action"];
258 if (!popupName.isString() || !popupAction.isUInt()) {
259 BATTERY_HILOGW(COMP_SVC, "popupObj invalid, key=%{public}s", uevent.c_str());
260 continue;
261 }
262 BatteryConfig::PopupConf popupCfg = {
263 .name = popupName.asString(),
264 .action = popupAction.asUInt()
265 };
266 BATTERY_HILOGI(COMP_SVC, "add popupConf %{public}s, %{public}d", popupCfg.name.c_str(), popupCfg.action);
267 popupConfVec.emplace_back(popupCfg);
268 }
269 BATTERY_HILOGI(COMP_SVC, "popupConfVec size: %{public}d", static_cast<int32_t>(popupConfVec.size()));
270 popupConfig_.emplace(uevent, popupConfVec);
271 }
272 BATTERY_HILOGI(COMP_SVC, "popupConfVec size: %{public}d", static_cast<int32_t>(popupConfig_.size()));
273 }
274
GetNotificationConf() const275 const std::unordered_map<std::string, BatteryConfig::NotificationConf>& BatteryConfig::GetNotificationConf() const
276 {
277 return notificationConfMap_;
278 }
279
ParseNotificationConf()280 void BatteryConfig::ParseNotificationConf()
281 {
282 Json::Value nConf = GetValue("notification");
283 if (nConf.isNull() || !nConf.isArray()) {
284 BATTERY_HILOGW(COMP_SVC, "nConf is invalid");
285 return;
286 }
287 for (const auto& conf : nConf) {
288 Json::Value nameObj = conf["name"];
289 Json::Value iconObj = conf["icon"];
290 Json::Value titleObj = conf["title"];
291 Json::Value textObj = conf["text"];
292 Json::Value buttonObj = conf["button"];
293 if (!nameObj.isString() || !iconObj.isString() || !titleObj.isString()
294 || !textObj.isString() || !buttonObj.isArray()) {
295 BATTERY_HILOGW(COMP_SVC, "stringConf Parse failed");
296 continue;
297 }
298 if (buttonObj.size() != MAX_BUTTON_RANGE || !buttonObj[FIRST_BUTTON_INDEX].isObject() ||
299 !buttonObj[SECOND_BUTTON_INDEX].isObject()) {
300 BATTERY_HILOGW(COMP_SVC, "buttonConf is invalid");
301 continue;
302 }
303 Json::Value firstButtonNameObj = buttonObj[FIRST_BUTTON_INDEX]["name"];
304 Json::Value firstButtonActionObj = buttonObj[FIRST_BUTTON_INDEX]["action"];
305 Json::Value secondButtonNameObj = buttonObj[SECOND_BUTTON_INDEX]["name"];
306 Json::Value secondButtonActionObj = buttonObj[SECOND_BUTTON_INDEX]["action"];
307 if (!firstButtonNameObj.isString() || !firstButtonActionObj.isString()
308 || !secondButtonNameObj.isString() || !secondButtonActionObj.isString()) {
309 BATTERY_HILOGW(COMP_SVC, "buttonConf Parse failed");
310 return;
311 }
312 std::string name = nameObj.asString();
313 BatteryConfig::NotificationConf notificationConf = {
314 .name = name,
315 .icon = iconObj.asString(),
316 .title = titleObj.asString(),
317 .text = textObj.asString(),
318 .firstButton = std::make_pair(firstButtonNameObj.asString(), firstButtonActionObj.asString()),
319 .secondButton = std::make_pair(secondButtonNameObj.asString(), secondButtonActionObj.asString())
320 };
321 BATTERY_HILOGI(COMP_SVC, "notificationConf name: %{public}s", name.c_str());
322 notificationConfMap_.emplace(name, notificationConf);
323 }
324 BATTERY_HILOGI(COMP_SVC, "notificationConf size: %{public}d", static_cast<int32_t>(notificationConfMap_.size()));
325 }
326
FindConf(const std::string & key) const327 Json::Value BatteryConfig::FindConf(const std::string& key) const
328 {
329 return (config_.isObject() && config_.isMember(key)) ? config_[key] : Json::Value();
330 }
331
SplitKey(const std::string & key,std::vector<std::string> & keys) const332 bool BatteryConfig::SplitKey(const std::string& key, std::vector<std::string>& keys) const
333 {
334 SplitStr(TrimStr(key), ".", keys);
335 return (keys.size() < MIN_DEPTH || keys.size() > MAX_DEPTH) ? false : true;
336 }
337
GetValue(std::string key) const338 Json::Value BatteryConfig::GetValue(std::string key) const
339 {
340 std::vector<std::string> keys;
341 if (!SplitKey(key, keys)) {
342 BATTERY_HILOGW(COMP_SVC, "The key does not meet the. key=%{public}s", key.c_str());
343 return Json::Value();
344 }
345
346 Json::Value value = FindConf(keys[MAP_KEY_INDEX]);
347 if (value.isNull()) {
348 BATTERY_HILOGD(COMP_SVC, "Value is empty. key=%{public}s", key.c_str());
349 return value;
350 }
351
352 for (size_t i = 1; i < keys.size(); ++i) {
353 if (!value.isObject() || !value.isMember(keys[i])) {
354 BATTERY_HILOGW(COMP_SVC, "The key is not configured. key=%{public}s", keys[i].c_str());
355 break;
356 }
357 value = value[keys[i]];
358 }
359 return value;
360 }
361 } // namespace PowerMgr
362 } // namespace OHOS
363