• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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