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 }
42 namespace OHOS {
43 namespace PowerMgr {
44 std::shared_ptr<BatteryConfig> BatteryConfig::instance_ = nullptr;
45 std::mutex BatteryConfig::mutex_;
46 
GetInstance()47 BatteryConfig& BatteryConfig::GetInstance()
48 {
49     std::lock_guard<std::mutex> lock(mutex_);
50     if (instance_ == nullptr) {
51         instance_ = std::make_shared<BatteryConfig>();
52     }
53     return *(instance_.get());
54 }
55 
ParseConfig()56 bool BatteryConfig::ParseConfig()
57 {
58     char buf[MAX_PATH_LEN];
59     char* path = GetOneCfgFile(BATTERY_CONFIG_PATH, buf, MAX_PATH_LEN);
60     if (path == nullptr || *path == '\0') {
61         BATTERY_HILOGW(COMP_SVC, "GetOneCfgFile battery_config.json is NULL");
62         path = const_cast<char*>(BATTERY_CONFIG_EXCEPTION_PATH);
63     }
64     BATTERY_HILOGD(COMP_SVC, "GetOneCfgFile battery_config.json");
65 
66     Json::CharReaderBuilder readerBuilder;
67     std::ifstream ifsConf;
68 
69     RETURN_IF_WITH_RET(!OpenFile(ifsConf, path), false);
70 
71     config_.clear();
72     readerBuilder["collectComments"] = false;
73     JSONCPP_STRING errs;
74 
75     if (parseFromStream(readerBuilder, ifsConf, &config_, &errs) && !config_.empty()) {
76         ParseConfInner();
77     }
78     ifsConf.close();
79     return true;
80 }
81 
IsExist(std::string key) const82 bool BatteryConfig::IsExist(std::string key) const
83 {
84     return !GetValue(key).isNull();
85 }
86 
GetInt(std::string key,int32_t defVal) const87 int32_t BatteryConfig::GetInt(std::string key, int32_t defVal) const
88 {
89     Json::Value value = GetValue(key);
90     return (value.isNull() || !value.isInt()) ? defVal : value.asInt();
91 }
92 
GetLightConf() const93 const std::vector<BatteryConfig::LightConf>& BatteryConfig::GetLightConf() const
94 {
95     return lightConf_;
96 }
97 
OpenFile(std::ifstream & ifsConf,const std::string & configPath)98 bool BatteryConfig::OpenFile(std::ifstream& ifsConf, const std::string& configPath)
99 {
100     bool isOpen = false;
101     if (!configPath.empty()) {
102         ifsConf.open(configPath);
103         isOpen = ifsConf.is_open();
104         BATTERY_HILOGD(COMP_SVC, "open configPath file is %{public}d", isOpen);
105     }
106     RETURN_IF_WITH_RET(isOpen, true);
107 
108     ifsConf.open(VENDOR_BATTERY_CONFIG_PATH);
109     isOpen = ifsConf.is_open();
110     BATTERY_HILOGI(COMP_SVC, "open then vendor battery_config.json is %{public}d", isOpen);
111     RETURN_IF_WITH_RET(isOpen, true);
112 
113     ifsConf.open(SYSTEM_BATTERY_CONFIG_PATH);
114     isOpen = ifsConf.is_open();
115     BATTERY_HILOGI(COMP_SVC, "open then system battery_config.json is %{public}d", isOpen);
116     return isOpen;
117 }
118 
ParseConfInner()119 void BatteryConfig::ParseConfInner()
120 {
121     lightConf_.clear();
122     ParseLightConf("low");
123     ParseLightConf("normal");
124     ParseLightConf("high");
125     BATTERY_HILOGD(COMP_SVC, "The battery light configuration size %{public}d",
126         static_cast<int32_t>(lightConf_.size()));
127 }
128 
ParseLightConf(std::string level)129 void BatteryConfig::ParseLightConf(std::string level)
130 {
131     Json::Value soc = GetValue("light." + level + ".soc");
132     Json::Value rgb = GetValue("light." + level + ".rgb");
133     if (!soc.isArray() || !rgb.isArray()) {
134         BATTERY_HILOGW(COMP_SVC, "The battery light %{public}s configuration is invalid.", level.c_str());
135         return;
136     }
137 
138     if (soc.size() != MAX_SOC_RANGE || !soc[BEGIN_SOC_INDEX].isInt() || !soc[END_SOC_INDEX].isInt()) {
139         BATTERY_HILOGW(COMP_SVC, "The battery light %{public}s soc data type error.", level.c_str());
140         return;
141     }
142     if (rgb.size() != MAX_RGB_RANGE || !rgb[RED_INDEX].isUInt() || !rgb[GREEN_INDEX].isUInt() ||
143         !rgb[BLUE_INDEX].isUInt()) {
144         BATTERY_HILOGW(COMP_SVC, "The battery light %{public}s rgb data type error.", level.c_str());
145         return;
146     }
147     BatteryConfig::LightConf lightConf = {
148         .beginSoc = soc[BEGIN_SOC_INDEX].asInt(),
149         .endSoc = soc[END_SOC_INDEX].asInt(),
150         .rgb = (rgb[RED_INDEX].asUInt() << MOVE_LEFT_16) |
151                (rgb[GREEN_INDEX].asUInt() << MOVE_LEFT_8) |
152                rgb[BLUE_INDEX].asUInt()
153     };
154     lightConf_.push_back(lightConf);
155 }
156 
FindConf(const std::string & key) const157 Json::Value BatteryConfig::FindConf(const std::string& key) const
158 {
159     return (config_.isObject() && config_.isMember(key)) ? config_[key] : Json::Value();
160 }
161 
SplitKey(const std::string & key,std::vector<std::string> & keys) const162 bool BatteryConfig::SplitKey(const std::string& key, std::vector<std::string>& keys) const
163 {
164     SplitStr(TrimStr(key), ".", keys);
165     return (keys.size() < MIN_DEPTH || keys.size() > MAX_DEPTH) ? false : true;
166 }
167 
GetValue(std::string key) const168 Json::Value BatteryConfig::GetValue(std::string key) const
169 {
170     std::vector<std::string> keys;
171     if (!SplitKey(key, keys)) {
172         BATTERY_HILOGW(COMP_SVC, "The key does not meet the. key=%{public}s", key.c_str());
173         return Json::Value();
174     }
175 
176     Json::Value value = FindConf(keys[MAP_KEY_INDEX]);
177     if (value.isNull()) {
178         BATTERY_HILOGD(COMP_SVC, "Value is empty. key=%{public}s", key.c_str());
179         return value;
180     }
181 
182     for (size_t i = 1; i < keys.size(); ++i) {
183         if (!value.isObject() || !value.isMember(keys[i])) {
184             BATTERY_HILOGW(COMP_SVC, "The key is not configured. key=%{public}s", keys[i].c_str());
185             break;
186         }
187         value = value[keys[i]];
188     }
189     return value;
190 }
191 } // namespace PowerMgr
192 } // namespace OHOS
193