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 #ifdef HAS_BATTERY_CONFIG_POLICY_PART
20 #include "config_policy_utils.h"
21 #endif
22 #include "charger_log.h"
23 
24 namespace OHOS {
25 namespace PowerMgr {
26 namespace {
27 #ifdef HAS_BATTERY_CONFIG_POLICY_PART
28 constexpr const char* BATTERY_CONFIG_EXCEPTION_PATH = "";
29 constexpr const char* BATTERY_CONFIG_PATH = "etc/battery/battery_config.json";
30 #endif
31 constexpr const char* SYSTEM_BATTERY_CONFIG_PATH = "/system/etc/battery/battery_config.json";
32 constexpr const char* VENDOR_BATTERY_CONFIG_PATH = "/vendor/etc/battery/battery_config.json";
33 constexpr int32_t MAP_KEY_INDEX = 0;
34 constexpr int32_t BEGIN_SOC_INDEX = 0;
35 constexpr int32_t END_SOC_INDEX = 1;
36 constexpr int32_t MAX_SOC_RANGE = 2;
37 constexpr int32_t RED_INDEX = 0;
38 constexpr int32_t GREEN_INDEX = 1;
39 constexpr int32_t BLUE_INDEX = 2;
40 constexpr int32_t MAX_RGB_RANGE = 3;
41 constexpr int32_t MAX_DEPTH = 5;
42 constexpr int32_t MIN_DEPTH = 1;
43 constexpr uint32_t MOVE_LEFT_16 = 16;
44 constexpr uint32_t MOVE_LEFT_8 = 8;
45 } // namespace
46 std::shared_ptr<BatteryConfig> BatteryConfig::instance_ = nullptr;
47 std::mutex BatteryConfig::mutex_;
48 
GetInstance()49 BatteryConfig& BatteryConfig::GetInstance()
50 {
51     std::lock_guard<std::mutex> lock(mutex_);
52     if (instance_ == nullptr) {
53         instance_ = std::make_shared<BatteryConfig>();
54     }
55     return *(instance_.get());
56 }
57 
58 #ifdef HAS_BATTERY_CONFIG_POLICY_PART
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(FEATURE_CHARGING, "GetOneCfgFile battery_config.json is NULL");
65         path = const_cast<char*>(BATTERY_CONFIG_EXCEPTION_PATH);
66     }
67     BATTERY_HILOGD(FEATURE_CHARGING, "GetOneCfgFile battery_config.json");
68 
69     Json::CharReaderBuilder readerBuilder;
70     std::ifstream ifsConf;
71     if (!OpenFile(ifsConf, path)) {
72         return false;
73     }
74 
75     config_.clear();
76     readerBuilder["collectComments"] = false;
77     JSONCPP_STRING errs;
78 
79     if (parseFromStream(readerBuilder, ifsConf, &config_, &errs) && !config_.empty()) {
80         ParseConfInner();
81     }
82     ifsConf.close();
83     return true;
84 }
85 #endif
86 
IsExist(std::string key) const87 bool BatteryConfig::IsExist(std::string key) const
88 {
89     return !GetValue(key).isNull();
90 }
91 
GetInt(std::string key, int32_t defVal) const92 int32_t BatteryConfig::GetInt(std::string key, int32_t defVal) const
93 {
94     Json::Value value = GetValue(key);
95     return (value.isNull() || !value.isInt()) ? defVal : value.asInt();
96 }
97 
GetString(std::string key, std::string defVal) const98 std::string BatteryConfig::GetString(std::string key, std::string defVal) const
99 {
100     Json::Value value = GetValue(key);
101     return (value.isNull() || !value.isString()) ? defVal : value.asString();
102 }
103 
GetLightConf() const104 const std::vector<BatteryConfig::LightConf>& BatteryConfig::GetLightConf() const
105 {
106     return lightConf_;
107 }
108 
DestroyInstance()109 void BatteryConfig::DestroyInstance()
110 {
111     std::lock_guard<std::mutex> lock(mutex_);
112     instance_ = nullptr;
113 }
114 
OpenFile(std::ifstream& ifsConf, const std::string& configPath)115 bool BatteryConfig::OpenFile(std::ifstream& ifsConf, const std::string& configPath)
116 {
117     bool isOpen = false;
118     if (!configPath.empty()) {
119         ifsConf.open(configPath);
120         isOpen = ifsConf.is_open();
121         BATTERY_HILOGD(FEATURE_CHARGING, "open configPath file is %{public}d", isOpen);
122     }
123     if (isOpen) {
124         return true;
125     }
126 
127     ifsConf.open(VENDOR_BATTERY_CONFIG_PATH);
128     isOpen = ifsConf.is_open();
129     BATTERY_HILOGI(FEATURE_CHARGING, "open then vendor battery_config.json is %{public}d", isOpen);
130 
131     if (isOpen) {
132         return true;
133     }
134 
135     ifsConf.open(SYSTEM_BATTERY_CONFIG_PATH);
136     isOpen = ifsConf.is_open();
137     BATTERY_HILOGI(FEATURE_CHARGING, "open then system battery_config.json is %{public}d", isOpen);
138     return isOpen;
139 }
140 
ParseConfInner()141 void BatteryConfig::ParseConfInner()
142 {
143     lightConf_.clear();
144     ParseLightConf("low");
145     ParseLightConf("normal");
146     ParseLightConf("high");
147     BATTERY_HILOGD(FEATURE_CHARGING, "The battery light configuration size %{public}d",
148         static_cast<int32_t>(lightConf_.size()));
149 }
150 
ParseLightConf(std::string level)151 void BatteryConfig::ParseLightConf(std::string level)
152 {
153     Json::Value soc = GetValue("light." + level + ".soc");
154     Json::Value rgb = GetValue("light." + level + ".rgb");
155     if (!soc.isArray() || !rgb.isArray()) {
156         BATTERY_HILOGW(FEATURE_CHARGING, "The battery light %{public}s configuration is invalid.", level.c_str());
157         return;
158     }
159 
160     if (soc.size() != MAX_SOC_RANGE || !soc[BEGIN_SOC_INDEX].isInt() || !soc[END_SOC_INDEX].isInt()) {
161         BATTERY_HILOGW(FEATURE_CHARGING, "The battery light %{public}s soc data type error.", level.c_str());
162         return;
163     }
164     if (rgb.size() != MAX_RGB_RANGE || !rgb[RED_INDEX].isUInt() || !rgb[GREEN_INDEX].isUInt() ||
165         !rgb[BLUE_INDEX].isUInt()) {
166         BATTERY_HILOGW(FEATURE_CHARGING, "The battery light %{public}s rgb data type error.", level.c_str());
167         return;
168     }
169     BatteryConfig::LightConf lightConf = {
170         .beginSoc = soc[BEGIN_SOC_INDEX].asInt(),
171         .endSoc = soc[END_SOC_INDEX].asInt(),
172         .rgb = (rgb[RED_INDEX].asUInt() << MOVE_LEFT_16) |
173                (rgb[GREEN_INDEX].asUInt() << MOVE_LEFT_8) |
174                rgb[BLUE_INDEX].asUInt()
175     };
176     lightConf_.push_back(lightConf);
177 }
178 
FindConf(const std::string& key) const179 Json::Value BatteryConfig::FindConf(const std::string& key) const
180 {
181     return (config_.isObject() && config_.isMember(key)) ? config_[key] : Json::Value();
182 }
183 
SplitKey(const std::string& key, std::vector<std::string>& keys) const184 bool BatteryConfig::SplitKey(const std::string& key, std::vector<std::string>& keys) const
185 {
186     SplitStr(TrimStr(key), ".", keys);
187     return (keys.size() < MIN_DEPTH || keys.size() > MAX_DEPTH) ? false : true;
188 }
189 
GetValue(std::string key) const190 Json::Value BatteryConfig::GetValue(std::string key) const
191 {
192     std::vector<std::string> keys;
193     if (!SplitKey(key, keys)) {
194         BATTERY_HILOGW(FEATURE_CHARGING, "The key does not meet the. key=%{public}s", key.c_str());
195         return Json::Value();
196     }
197 
198     Json::Value value = FindConf(keys[MAP_KEY_INDEX]);
199     if (value.isNull()) {
200         BATTERY_HILOGD(FEATURE_CHARGING, "Value is empty. key=%{public}s", key.c_str());
201         return value;
202     }
203 
204     for (size_t i = 1; i < keys.size(); ++i) {
205         if (!value.isObject() || !value.isMember(keys[i])) {
206             BATTERY_HILOGW(FEATURE_CHARGING, "The key is not configured. key=%{public}s", keys[i].c_str());
207             break;
208         }
209         value = value[keys[i]];
210     }
211     return value;
212 }
213 } // namespace PowerMgr
214 } // namespace OHOS
215