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
20 #include "string_ex.h"
21 #include "config_policy_utils.h"
22
23 namespace OHOS {
24 namespace HDI {
25 namespace Battery {
26 namespace V2_0 {
27 namespace {
28 constexpr const char* BATTERY_CONFIG_PATH = "etc/battery/battery_config.json";
29 constexpr const char* SYSTEM_BATTERY_CONFIG_PATH = "/system/etc/battery/battery_config.json";
30 constexpr const char* VENDOR_BATTERY_CONFIG_PATH = "/vendor/etc/battery/battery_config.json";
31 constexpr const char* BATTERY_CONFIG_EXCEPTION_PATH = "";
32 constexpr int32_t MAP_KEY_INDEX = 0;
33 constexpr int32_t BEGIN_SOC_INDEX = 0;
34 constexpr int32_t END_SOC_INDEX = 1;
35 constexpr int32_t MAX_SOC_RANGE = 2;
36 constexpr int32_t RED_INDEX = 0;
37 constexpr int32_t GREEN_INDEX = 1;
38 constexpr int32_t BLUE_INDEX = 2;
39 constexpr int32_t MAX_RGB_RANGE = 3;
40 constexpr int32_t MAX_DEPTH = 5;
41 constexpr int32_t MIN_DEPTH = 1;
42 constexpr uint32_t MOVE_LEFT_16 = 16;
43 constexpr uint32_t MOVE_LEFT_8 = 8;
44 }
45 std::shared_ptr<BatteryConfig> BatteryConfig::instance_ = nullptr;
46 std::mutex BatteryConfig::mutex_;
47
GetInstance()48 BatteryConfig& BatteryConfig::GetInstance()
49 {
50 std::lock_guard<std::mutex> lock(mutex_);
51 if (instance_ == nullptr) {
52 instance_ = std::make_shared<BatteryConfig>();
53 }
54 return *(instance_.get());
55 }
56
ParseConfig()57 bool BatteryConfig::ParseConfig()
58 {
59 char buf[MAX_PATH_LEN];
60 char* path = GetOneCfgFile(BATTERY_CONFIG_PATH, buf, MAX_PATH_LEN);
61 if (path == nullptr || *path == '\0') {
62 BATTERY_HILOGW(COMP_HDI, "GetOneCfgFile battery_config.json is NULL");
63 path = const_cast<char*>(BATTERY_CONFIG_EXCEPTION_PATH);
64 }
65 BATTERY_HILOGD(COMP_HDI, "GetOneCfgFile battery_config.json");
66
67 Json::CharReaderBuilder readerBuilder;
68 std::ifstream ifsConf;
69
70 if (!OpenFile(ifsConf, path)) {
71 return false;
72 }
73
74 Json::Value config;
75 readerBuilder["collectComments"] = false;
76 JSONCPP_STRING errs;
77
78 if (parseFromStream(readerBuilder, ifsConf, &config, &errs) && !config.empty()) {
79 ParseConfInner(config);
80 }
81 ifsConf.close();
82 return true;
83 }
84
GetLightConfig() const85 const std::vector<BatteryConfig::LightConfig>& BatteryConfig::GetLightConfig() const
86 {
87 return lightConfig_;
88 }
89
GetChargerConfig() const90 const BatteryConfig::ChargerConfig& BatteryConfig::GetChargerConfig() const
91 {
92 return chargerConfig_;
93 }
94
GetChargeSceneConfigMap() const95 const std::map<std::string, BatteryConfig::ChargeSceneConfig>& BatteryConfig::GetChargeSceneConfigMap() const
96 {
97 return chargeSceneConfigMap_;
98 }
99
GetUeventList() const100 const std::map<std::string, std::vector<std::string>>& BatteryConfig::GetUeventList() const
101 {
102 return ueventMap_;
103 }
104
DestroyInstance()105 void BatteryConfig::DestroyInstance()
106 {
107 std::lock_guard<std::mutex> lock(mutex_);
108 instance_ = nullptr;
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_HDI, "open file is %{public}d", isOpen);
118 }
119 if (isOpen) {
120 return true;
121 }
122
123 ifsConf.open(VENDOR_BATTERY_CONFIG_PATH);
124 isOpen = ifsConf.is_open();
125 BATTERY_HILOGI(COMP_HDI, "open then vendor battery_config.json is %{public}d", isOpen);
126
127 if (isOpen) {
128 return true;
129 }
130
131 ifsConf.open(SYSTEM_BATTERY_CONFIG_PATH);
132 isOpen = ifsConf.is_open();
133 BATTERY_HILOGI(FEATURE_CHARGING, "open then system battery_config.json is %{public}d", isOpen);
134 return isOpen;
135 }
136
ParseConfInner(const Json::Value & config)137 void BatteryConfig::ParseConfInner(const Json::Value& config)
138 {
139 BATTERY_HILOGI(COMP_HDI, "start parse battery config inner");
140 ParseLightConfig(GetValue(config, "light"));
141 ParseChargerConfig(GetValue(config, "charger"));
142 ParseChargeSceneConfig(GetValue(config, "charge_scene"));
143 ParseUeventConfig(GetValue(config, "uevent"));
144 }
145
ParseChargerConfig(const Json::Value & chargerConfig)146 void BatteryConfig::ParseChargerConfig(const Json::Value& chargerConfig)
147 {
148 if (chargerConfig.isNull() || !chargerConfig.isObject()) {
149 BATTERY_HILOGW(COMP_HDI, "chargerConfig is invalid");
150 return;
151 }
152
153 Json::Value currentPath = GetValue(chargerConfig, "current_limit.path");
154 if (isValidJsonString(currentPath)) {
155 chargerConfig_.currentPath = currentPath.asString();
156 }
157
158 Json::Value voltagePath = GetValue(chargerConfig, "voltage_limit.path");
159 if (isValidJsonString(voltagePath)) {
160 chargerConfig_.voltagePath = voltagePath.asString();
161 }
162
163 Json::Value chargeTypePath = GetValue(chargerConfig, "type.path");
164 if (isValidJsonString(chargeTypePath)) {
165 chargerConfig_.chargeTypePath = chargeTypePath.asString();
166 }
167 BATTERY_HILOGI(COMP_HDI, "The battery charger configuration parse succeed");
168 }
169
ParseLightConfig(const Json::Value & lightConfig)170 void BatteryConfig::ParseLightConfig(const Json::Value& lightConfig)
171 {
172 if (lightConfig.isNull() || !lightConfig.isObject()) {
173 BATTERY_HILOGW(COMP_HDI, "lightConf is invalid");
174 return;
175 }
176 lightConfig_.clear();
177 Json::Value::Members members = lightConfig.getMemberNames();
178 for (auto iter = members.begin(); iter != members.end(); iter++) {
179 std::string key = *iter;
180 Json::Value valueObj = lightConfig[key];
181 if (valueObj.isNull() || !valueObj.isObject()) {
182 BATTERY_HILOGW(COMP_HDI, "The light conf is invalid, key=%{public}s", key.c_str());
183 continue;
184 }
185
186 Json::Value soc = GetValue(valueObj, "soc");
187 Json::Value rgb = GetValue(valueObj, "rgb");
188 if (!soc.isArray() || !rgb.isArray()) {
189 BATTERY_HILOGW(COMP_HDI, "The battery light %{public}s configuration is invalid.", key.c_str());
190 continue;
191 }
192 if (soc.size() != MAX_SOC_RANGE || !soc[BEGIN_SOC_INDEX].isInt() || !soc[END_SOC_INDEX].isInt()) {
193 BATTERY_HILOGW(COMP_HDI, "The battery light %{public}s soc data type error.", key.c_str());
194 continue;
195 }
196 if (rgb.size() != MAX_RGB_RANGE || !rgb[RED_INDEX].isUInt() || !rgb[GREEN_INDEX].isUInt() ||
197 !rgb[BLUE_INDEX].isUInt()) {
198 BATTERY_HILOGW(COMP_HDI, "The battery light %{public}s rgb data type error.", key.c_str());
199 continue;
200 }
201
202 BatteryConfig::LightConfig tempLightConfig = {
203 .beginSoc = soc[BEGIN_SOC_INDEX].asInt(),
204 .endSoc = soc[END_SOC_INDEX].asInt(),
205 .rgb = (rgb[RED_INDEX].asUInt() << MOVE_LEFT_16) |
206 (rgb[GREEN_INDEX].asUInt() << MOVE_LEFT_8) |
207 rgb[BLUE_INDEX].asUInt()
208 };
209 lightConfig_.push_back(tempLightConfig);
210 }
211 BATTERY_HILOGI(COMP_HDI, "The battery light configuration size %{public}d",
212 static_cast<int32_t>(lightConfig_.size()));
213 }
214
ParseChargeSceneConfig(const Json::Value & chargeSceneConfig)215 void BatteryConfig::ParseChargeSceneConfig(const Json::Value& chargeSceneConfig)
216 {
217 if (chargeSceneConfig.isNull() || !chargeSceneConfig.isObject()) {
218 BATTERY_HILOGW(COMP_HDI, "chargeSceneConfig is invalid");
219 return;
220 }
221
222 chargeSceneConfigMap_.clear();
223 Json::Value::Members members = chargeSceneConfig.getMemberNames();
224 for (auto iter = members.begin(); iter != members.end(); iter++) {
225 std::string key = *iter;
226 Json::Value valueObj = chargeSceneConfig[key];
227 if (key.empty() || valueObj.isNull() || !valueObj.isObject()) {
228 BATTERY_HILOGW(COMP_HDI, "The charge scene config is invalid, key=%{public}s", key.c_str());
229 continue;
230 }
231
232 Json::Value supportPath = GetValue(valueObj, "support.path");
233 Json::Value type = GetValue(valueObj, "support.type");
234 Json::Value expectValue = GetValue(valueObj, "support.expect_value");
235 Json::Value setPath = GetValue(valueObj, "set.path");
236 Json::Value getPath = GetValue(valueObj, "get.path");
237 if (!isValidJsonString(supportPath) && !isValidJsonString(setPath) && !isValidJsonString(getPath)) {
238 BATTERY_HILOGW(COMP_HDI, "The charge scene config path is invalid, key=%{public}s", key.c_str());
239 continue;
240 }
241
242 BatteryConfig::ChargeSceneConfig tempChargeSceneConfig;
243 if (isValidJsonString(supportPath)) {
244 tempChargeSceneConfig.supportPath = supportPath.asString();
245 tempChargeSceneConfig.type = isValidJsonString(type) ? type.asString() : "";
246 tempChargeSceneConfig.expectValue = isValidJsonString(expectValue) ? expectValue.asString() : "";
247 }
248
249 if (isValidJsonString(setPath)) {
250 tempChargeSceneConfig.setPath = setPath.asString();
251 }
252
253 if (isValidJsonString(getPath)) {
254 tempChargeSceneConfig.getPath = getPath.asString();
255 }
256 chargeSceneConfigMap_.insert(std::make_pair(key, tempChargeSceneConfig));
257 }
258 BATTERY_HILOGI(COMP_HDI, "The charge scene config size: %{public}d",
259 static_cast<int32_t>(chargeSceneConfigMap_.size()));
260 }
261
ParseUeventConfig(const Json::Value & ueventConfig)262 void BatteryConfig::ParseUeventConfig(const Json::Value& ueventConfig)
263 {
264 if (ueventConfig.isNull() || !ueventConfig.isObject()) {
265 BATTERY_HILOGW(COMP_HDI, "ueventConfig is invalid");
266 return;
267 }
268 ueventMap_.clear();
269 Json::Value::Members members = ueventConfig.getMemberNames();
270 for (auto iter = members.begin(); iter != members.end(); iter++) {
271 std::string key = *iter;
272 Json::Value valueObj = ueventConfig[key];
273 if (valueObj.isNull() || !valueObj.isObject()) {
274 BATTERY_HILOGW(COMP_HDI, "The uevent conf is invalid, key=%{public}s", key.c_str());
275 continue;
276 }
277 std::vector<std::string> ueventList;
278 Json::Value::Members ObjMembers = valueObj.getMemberNames();
279 for (auto it = ObjMembers.begin(); it != ObjMembers.end(); it++) {
280 ueventList.push_back(*it);
281 }
282 ueventMap_.emplace(*iter, ueventList);
283 BATTERY_HILOGI(COMP_HDI, "%{public}s size: %{public}d", key.c_str(),
284 static_cast<int32_t>(ueventList.size()));
285 }
286 BATTERY_HILOGI(COMP_HDI, "The uevent config size: %{public}d", static_cast<int32_t>(ueventMap_.size()));
287 }
288
SplitKey(const std::string & key,std::vector<std::string> & keys) const289 bool BatteryConfig::SplitKey(const std::string& key, std::vector<std::string>& keys) const
290 {
291 SplitStr(TrimStr(key), ".", keys);
292 return (keys.size() < MIN_DEPTH || keys.size() > MAX_DEPTH) ? false : true;
293 }
294
GetValue(const Json::Value & config,std::string key) const295 Json::Value BatteryConfig::GetValue(const Json::Value& config, std::string key) const
296 {
297 std::vector<std::string> keys;
298 if (!SplitKey(key, keys)) {
299 BATTERY_HILOGW(COMP_HDI, "The key does not meet the. key=%{public}s", key.c_str());
300 return Json::Value();
301 }
302
303 std::string firstKey = keys[MAP_KEY_INDEX];
304 Json::Value value = (config.isObject() && config.isMember(firstKey)) ? config[firstKey] : Json::Value();
305 if (value.isNull()) {
306 BATTERY_HILOGW(COMP_HDI, "Value is empty. key=%{public}s", keys[MAP_KEY_INDEX].c_str());
307 return value;
308 }
309
310 for (size_t i = 1; i < keys.size(); ++i) {
311 if (!value.isObject() || !value.isMember(keys[i])) {
312 BATTERY_HILOGW(COMP_HDI, "The key is not configured. key=%{public}s", keys[i].c_str());
313 break;
314 }
315 value = value[keys[i]];
316 }
317 return value;
318 }
319
isValidJsonString(const Json::Value & config) const320 bool BatteryConfig::isValidJsonString(const Json::Value& config) const
321 {
322 return !config.isNull() && config.isString();
323 }
324 } // namespace V2_0
325 } // namespace Battery
326 } // namespace HDI
327 } // namespace OHOS
328