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 "power_config.h"
17#include "string_ex.h"
18#include "config_policy_utils.h"
19#include "power_hdf_log.h"
20
21namespace OHOS {
22namespace HDI {
23namespace Power {
24namespace V1_2 {
25namespace {
26constexpr const char* POWER_CONFIG_PATH = "etc/power_config/power_config.json";
27constexpr const char* SYSTEM_POWER_CONFIG_PATH = "/system/etc/power_config/power_config.json";
28constexpr const char* VENDOR_POWER_CONFIG_PATH = "/vendor/etc/power_config/power_config.json";
29constexpr const char* POWER_CONFIG_EXCEPTION_PATH = "";
30constexpr int32_t MAP_KEY_INDEX = 0;
31constexpr int32_t MAX_DEPTH = 5;
32constexpr int32_t MIN_DEPTH = 1;
33}
34
35std::shared_ptr<PowerConfig> PowerConfig::instance_ = nullptr;
36std::mutex PowerConfig::mutex_;
37
38PowerConfig& 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
47void PowerConfig::DestroyInstance()
48{
49    std::lock_guard<std::mutex> lock(mutex_);
50    instance_ = nullptr;
51}
52
53const std::map<std::string, PowerConfig::PowerSceneConfig>& PowerConfig::GetPowerSceneConfigMap() const
54{
55    return sceneConfigMap_;
56}
57
58bool PowerConfig::ParseConfig()
59{
60    char buf[MAX_PATH_LEN];
61    char* path = GetOneCfgFile(POWER_CONFIG_PATH, buf, MAX_PATH_LEN);
62    if (path == nullptr || *path == '\0') {
63        HDF_LOGW("GetOneCfgFile power_config.json is NULL");
64        path = const_cast<char*>(POWER_CONFIG_EXCEPTION_PATH);
65    }
66    HDF_LOGI("GetOneCfgFile power_config.json");
67
68    Json::CharReaderBuilder readerBuilder;
69    std::ifstream ifsConf;
70
71    if (!OpenFile(ifsConf, path)) {
72        return false;
73    }
74
75    Json::Value config;
76    readerBuilder["collectComments"] = false;
77    JSONCPP_STRING errs;
78
79    if (parseFromStream(readerBuilder, ifsConf, &config, &errs) && !config.empty()) {
80        ParseConfInner(config);
81    }
82    ifsConf.close();
83    return true;
84}
85
86bool PowerConfig::OpenFile(std::ifstream& ifsConf, const std::string& configPath)
87{
88    bool isOpen = false;
89    if (!configPath.empty()) {
90        ifsConf.open(configPath);
91        isOpen = ifsConf.is_open();
92        HDF_LOGI("path is %{public}s", configPath.c_str());
93        HDF_LOGI("open file is %{public}d", isOpen);
94    }
95    if (isOpen) {
96        return true;
97    }
98
99    ifsConf.open(VENDOR_POWER_CONFIG_PATH);
100    isOpen = ifsConf.is_open();
101    HDF_LOGI("open then vendor battery_config.json is %{public}d", isOpen);
102
103    if (isOpen) {
104        return true;
105    }
106
107    ifsConf.open(SYSTEM_POWER_CONFIG_PATH);
108    isOpen = ifsConf.is_open();
109    HDF_LOGI("open then system battery_config.json is %{public}d", isOpen);
110    return isOpen;
111}
112
113void PowerConfig::ParseConfInner(const Json::Value& config)
114{
115    HDF_LOGI("start parse power config inner");
116    ParseSceneConfig(GetValue(config, "scene"));
117}
118
119bool PowerConfig::SplitKey(const std::string& key, std::vector<std::string>& keys) const
120{
121    SplitStr(TrimStr(key), ".", keys);
122    return (keys.size() < MIN_DEPTH || keys.size() > MAX_DEPTH) ? false : true;
123}
124
125Json::Value PowerConfig::GetValue(const Json::Value& config, std::string key) const
126{
127    std::vector<std::string> keys;
128    if (!SplitKey(key, keys)) {
129        HDF_LOGW("The key does not meet the. key=%{public}s", key.c_str());
130        return Json::Value();
131    }
132
133    std::string firstKey = keys[MAP_KEY_INDEX];
134    Json::Value value = (config.isObject() && config.isMember(firstKey)) ? config[firstKey] : Json::Value();
135    if (value.isNull()) {
136        HDF_LOGW("Value is empty. key=%{public}s", keys[MAP_KEY_INDEX].c_str());
137        return value;
138    }
139
140    for (size_t i = 1; i < keys.size(); ++i) {
141        if (!value.isObject() || !value.isMember(keys[i])) {
142            HDF_LOGW("The key is not configured. key=%{public}s", keys[i].c_str());
143            break;
144        }
145        value = value[keys[i]];
146    }
147    return value;
148}
149
150void PowerConfig::ParseSceneConfig(const Json::Value& sceneConfig)
151{
152    if (sceneConfig.isNull() || !sceneConfig.isObject()) {
153        HDF_LOGW("sceneConfig is invalid");
154        return;
155    }
156
157    sceneConfigMap_.clear();
158    Json::Value::Members members = sceneConfig.getMemberNames();
159    for (auto iter = members.begin(); iter != members.end(); iter++) {
160        std::string key = *iter;
161        Json::Value valueObj = sceneConfig[key];
162        if (key.empty() || valueObj.isNull() || !valueObj.isObject()) {
163            HDF_LOGW("The scene config is invalid, key=%{public}s", key.c_str());
164            continue;
165        }
166
167        PowerConfig::PowerSceneConfig tempPowerSceneConfig;
168        Json::Value getPath = GetValue(valueObj, "get.path");
169        Json::Value setPath = GetValue(valueObj, "set.path");
170        if (isValidJsonString(getPath)) {
171            tempPowerSceneConfig.getPath = getPath.asString();
172            HDF_LOGI("getPath key=%{public}s", tempPowerSceneConfig.getPath.c_str());
173        }
174        if (isValidJsonString(setPath)) {
175            tempPowerSceneConfig.setPath = setPath.asString();
176            HDF_LOGI("setPath key=%{public}s", tempPowerSceneConfig.setPath.c_str());
177        }
178
179        sceneConfigMap_.insert(std::make_pair(key, tempPowerSceneConfig));
180    }
181    HDF_LOGI("The charge scene config size: %{public}d",
182        static_cast<int32_t>(sceneConfigMap_.size()));
183}
184
185bool PowerConfig::isValidJsonString(const Json::Value& config) const
186{
187    return !config.isNull() && config.isString();
188}
189
190} // namespace V1_2
191} // namespace Power
192} // namespace HDI
193} // namespace OHOS