1 /*
2 * Copyright (c) 2022-2025 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 "power_config.h"
17 #include "string_ex.h"
18 #include "config_policy_utils.h"
19 #include "power_hdf_log.h"
20
21 namespace OHOS {
22 namespace HDI {
23 namespace Power {
24 namespace V1_2 {
25 namespace {
26 constexpr const char* POWER_CONFIG_PATH = "etc/power_config/power_config.json";
27 constexpr const char* SYSTEM_POWER_CONFIG_PATH = "/system/etc/power_config/power_config.json";
28 constexpr const char* VENDOR_POWER_CONFIG_PATH = "/vendor/etc/power_config/power_config.json";
29 constexpr const char* POWER_CONFIG_EXCEPTION_PATH = "";
30 constexpr int32_t MAP_KEY_INDEX = 0;
31 constexpr int32_t MAX_DEPTH = 5;
32 constexpr int32_t MIN_DEPTH = 1;
33 }
34
35 std::shared_ptr<PowerConfig> PowerConfig::instance_ = nullptr;
36 std::mutex PowerConfig::mutex_;
37
GetInstance()38 PowerConfig& PowerConfig::GetInstance()
39 {
40 std::lock_guard<std::mutex> lock(mutex_);
41 if (instance_ == nullptr) {
42 instance_ = std::make_shared<PowerConfig>();
43 }
44 return *(instance_.get());
45 }
46
DestroyInstance()47 void PowerConfig::DestroyInstance()
48 {
49 std::lock_guard<std::mutex> lock(mutex_);
50 instance_ = nullptr;
51 }
52
GetPowerSceneConfigMap() const53 const std::map<std::string, PowerConfig::PowerSceneConfig>& PowerConfig::GetPowerSceneConfigMap() const
54 {
55 return sceneConfigMap_;
56 }
57
ParseJsonStream(std::istream & ifsConf)58 cJSON* PowerConfig::ParseJsonStream(std::istream& ifsConf)
59 {
60 std::string content((std::istreambuf_iterator<char>(ifsConf)), std::istreambuf_iterator<char>());
61 cJSON* config = cJSON_Parse(content.c_str());
62 if (config == nullptr) {
63 const char *errorPtr = cJSON_GetErrorPtr();
64 HDF_LOGW("cJSON parse error: in %{public}s", (errorPtr != nullptr) ? errorPtr : "unknown error");
65 return nullptr;
66 }
67 if (cJSON_IsNull(config) || (cJSON_IsObject(config) && (config->child == nullptr)) ||
68 (cJSON_IsArray(config) && (cJSON_GetArraySize(config) == 0))) {
69 cJSON_Delete(config);
70 HDF_LOGW("cJSON parse result is empty, power config is %{public}s", content.c_str());
71 return nullptr;
72 }
73 return config;
74 }
75
ParseConfig()76 bool PowerConfig::ParseConfig()
77 {
78 char buf[MAX_PATH_LEN];
79 char* path = GetOneCfgFile(POWER_CONFIG_PATH, buf, MAX_PATH_LEN);
80 if (path == nullptr || *path == '\0') {
81 HDF_LOGW("GetOneCfgFile power_config.json is NULL");
82 path = const_cast<char*>(POWER_CONFIG_EXCEPTION_PATH);
83 }
84 HDF_LOGI("GetOneCfgFile power_config.json");
85
86 std::ifstream ifsConf;
87 if (!OpenFile(ifsConf, path)) {
88 return false;
89 }
90
91 cJSON* config = ParseJsonStream(ifsConf);
92 ifsConf.close();
93 if (!config) {
94 HDF_LOGE("Failed to parse JSON");
95 return false;
96 }
97
98 ParseConfInner(config);
99 cJSON_Delete(config);
100 config = nullptr;
101 return true;
102 }
103
OpenFile(std::ifstream & ifsConf,const std::string & configPath)104 bool PowerConfig::OpenFile(std::ifstream& ifsConf, const std::string& configPath)
105 {
106 bool isOpen = false;
107 if (!configPath.empty()) {
108 ifsConf.open(configPath);
109 isOpen = ifsConf.is_open();
110 HDF_LOGI("path is %{public}s", configPath.c_str());
111 HDF_LOGI("open file is %{public}d", isOpen);
112 }
113 if (isOpen) {
114 return true;
115 }
116
117 ifsConf.open(VENDOR_POWER_CONFIG_PATH);
118 isOpen = ifsConf.is_open();
119 HDF_LOGI("open then vendor battery_config.json is %{public}d", isOpen);
120
121 if (isOpen) {
122 return true;
123 }
124
125 ifsConf.open(SYSTEM_POWER_CONFIG_PATH);
126 isOpen = ifsConf.is_open();
127 HDF_LOGI("open then system battery_config.json is %{public}d", isOpen);
128 return isOpen;
129 }
130
ParseConfInner(const cJSON * config)131 void PowerConfig::ParseConfInner(const cJSON* config)
132 {
133 HDF_LOGI("start parse power config inner");
134 cJSON* sceneNode = GetValue(config, "scene");
135 ParseSceneConfig(sceneNode);
136 }
137
SplitKey(const std::string & key,std::vector<std::string> & keys) const138 bool PowerConfig::SplitKey(const std::string& key, std::vector<std::string>& keys) const
139 {
140 SplitStr(TrimStr(key), ".", keys);
141 return (keys.size() < MIN_DEPTH || keys.size() > MAX_DEPTH) ? false : true;
142 }
143
GetValue(const cJSON * config,std::string key) const144 cJSON* PowerConfig::GetValue(const cJSON* config, std::string key) const
145 {
146 std::vector<std::string> keys;
147 if (!SplitKey(key, keys)) {
148 HDF_LOGW("The key does not meet the. key=%{public}s", key.c_str());
149 return nullptr;
150 }
151
152 std::string firstKey = keys[MAP_KEY_INDEX];
153 cJSON* value = (config && cJSON_IsObject(config) && cJSON_HasObjectItem(config, firstKey.c_str())) ?
154 cJSON_GetObjectItemCaseSensitive(config, firstKey.c_str()) : nullptr;
155 if (!value || cJSON_IsNull(value)) {
156 HDF_LOGW("Value is empty. key=%{public}s", key.c_str());
157 return value;
158 }
159 for (size_t i = 1; i < keys.size(); ++i) {
160 if (!cJSON_IsObject(value) || !cJSON_HasObjectItem(value, keys[i].c_str())) {
161 HDF_LOGW("Invalid JSON type for key: %{public}s", keys[i].c_str());
162 break;
163 }
164 value = cJSON_GetObjectItemCaseSensitive(value, keys[i].c_str());
165 }
166 return value;
167 }
168
ParseSceneConfig(const cJSON * sceneConfig)169 void PowerConfig::ParseSceneConfig(const cJSON* sceneConfig)
170 {
171 if (!IsValidJsonObject(sceneConfig)) {
172 HDF_LOGW("sceneConfig is invalid");
173 return;
174 }
175
176 sceneConfigMap_.clear();
177 cJSON* item = nullptr;
178 cJSON_ArrayForEach(item, sceneConfig) {
179 if (!cJSON_IsObject(item)) {
180 continue;
181 }
182
183 const char* key = item->string;
184 if (key == nullptr || strlen(key) == 0) {
185 HDF_LOGW("Invalid scene key");
186 continue;
187 }
188
189 PowerSceneConfig tempConfig;
190 cJSON* getPath = GetValue(item, "get.path");
191 cJSON* setPath = GetValue(item, "set.path");
192
193 if (IsValidJsonString(getPath)) {
194 tempConfig.getPath = getPath->valuestring;
195 HDF_LOGI("getPath key=%{public}s", tempConfig.getPath.c_str());
196 }
197 if (IsValidJsonString(setPath)) {
198 tempConfig.setPath = setPath->valuestring;
199 HDF_LOGI("setPath key=%{public}s", tempConfig.setPath.c_str());
200 }
201
202 sceneConfigMap_.emplace(key, tempConfig);
203 }
204 HDF_LOGI("The charge scene config size: %{public}d", static_cast<int32_t>(sceneConfigMap_.size()));
205 }
206
IsValidJsonString(const cJSON * jsonValue) const207 bool PowerConfig::IsValidJsonString(const cJSON* jsonValue) const
208 {
209 return jsonValue && cJSON_IsString(jsonValue) && jsonValue->valuestring != nullptr;
210 }
211
IsValidJsonObject(const cJSON * jsonValue) const212 bool PowerConfig::IsValidJsonObject(const cJSON* jsonValue) const
213 {
214 return jsonValue && cJSON_IsObject(jsonValue);
215 }
216 } // namespace V1_2
217 } // namespace Power
218 } // namespace HDI
219 } // namespace OHOS
220