1/*
2 * Copyright (c) 2023-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 "config_parser_base.h"
17
18#include <fstream>
19#include <iostream>
20#include <unistd.h>
21
22#include "display_log.h"
23
24namespace OHOS {
25namespace DisplayPowerMgr {
26namespace {
27constexpr int DISPLAY_ID_MAX = 5;
28constexpr uint16_t POINT_XY_SIZE = 2;
29const std::string CONFIG_PATH_FOR_ROOT = "/sys_prod/etc/display/";
30const std::string CONFIG_PATH_TYP = ".json";
31const std::string CONFIG_PATHS[DISPLAY_ID_MAX] = {
32    "brightness_config/", // Unkonwn config, default path
33    "full/brightness_config/", // Full config
34    "brightness_config/", // Main config
35    "sub/brightness_config/", // Sub config
36    "brightness_config/", // Others config
37};
38} // namespace
39
40using namespace OHOS::DisplayPowerMgr;
41
42ConfigParserBase& ConfigParserBase::Get()
43{
44    static ConfigParserBase brightnessConfigParserBase;
45    return brightnessConfigParserBase;
46}
47
48void ConfigParserBase::Initialize()
49{
50    std::lock_guard<std::mutex> lock(mLock);
51    if (mIsInitialized.load()) [[unlikely]]
52    {
53        DISPLAY_HILOGI(FEAT_BRIGHTNESS, "Already init!");
54        return;
55    }
56    for (int displayId = 0; displayId < DISPLAY_ID_MAX; displayId++) {
57        DISPLAY_HILOGI(FEAT_BRIGHTNESS, "[%{public}d] Already init!", displayId);
58        mConfigInfo[displayId] = ConfigInfo{};
59    }
60    mIsInitialized = true;
61}
62
63std::unordered_map<int, ConfigParserBase::ConfigInfo>::iterator ConfigParserBase::GetDispIter(int displayId)
64{
65    std::unordered_map<int, ConfigInfo>::iterator itDisp = mConfigInfo.find(displayId);
66    if (itDisp == mConfigInfo.end()) {
67        DISPLAY_HILOGW(FEAT_BRIGHTNESS, "[%{public}d]Failed to find config", displayId);
68    }
69    return itDisp;
70}
71
72std::unordered_map<int, ConfigParserBase::ConfigInfo>::const_iterator ConfigParserBase::GetConstDispIter(
73    int displayId) const
74{
75    std::unordered_map<int, ConfigInfo>::const_iterator itDisp = mConfigInfo.find(displayId);
76    if (itDisp == mConfigInfo.end()) {
77        DISPLAY_HILOGW(FEAT_BRIGHTNESS, "[%{public}d]Failed to find config", displayId);
78    }
79    return itDisp;
80}
81
82const std::string ConfigParserBase::LoadConfigPath(int displayId, const std::string& configName) const
83{
84    auto itDisp = GetConstDispIter(displayId);
85    std::string configPath{};
86    configPath.append(CONFIG_PATH_FOR_ROOT).append(CONFIG_PATHS[displayId]).append(configName);
87    // default path
88    if (itDisp == mConfigInfo.end()) {
89        configPath.append(CONFIG_PATH_TYP);
90        DISPLAY_HILOGW(FEAT_BRIGHTNESS, "[%{public}d] default path [%{public}s]!", displayId, configPath.c_str());
91        return configPath;
92    }
93
94    // default path
95    const ConfigInfo& configInfo = itDisp->second;
96    if (configInfo.panelName.empty()) {
97        configPath.append(CONFIG_PATH_TYP);
98        DISPLAY_HILOGW(FEAT_BRIGHTNESS, "[%{public}d] default path [%{public}s]!", displayId, configPath.c_str());
99        return configPath;
100    }
101
102    // name + version path
103    configPath.append("_").append(configInfo.panelName);
104    if (!configInfo.panelVersion.empty()) {
105        configPath = configPath.append("_").append(configInfo.panelVersion).append(CONFIG_PATH_TYP);
106        if (access(configPath.c_str(), R_OK) == 0) {
107            DISPLAY_HILOGW(FEAT_BRIGHTNESS, "[%{public}d] name + version path [%{public}s]!",
108                displayId, configPath.c_str());
109            return configPath;
110        }
111    }
112
113    // version path
114    configPath.append(CONFIG_PATH_TYP);
115    if (access(configPath.c_str(), R_OK) == 0) {
116        DISPLAY_HILOGW(FEAT_BRIGHTNESS, "[%{public}d] version path [%{public}s]!", displayId, configPath.c_str());
117        return configPath;
118    }
119
120    // default path
121    configPath.clear();
122    configPath.append(CONFIG_PATH_FOR_ROOT).append(CONFIG_PATHS[displayId]).append(configName).append(CONFIG_PATH_TYP);
123    DISPLAY_HILOGW(FEAT_BRIGHTNESS, "[%{public}d] default path [%{public}s]!", displayId, configPath.c_str());
124    return configPath;
125}
126
127const Json::Value ConfigParserBase::LoadConfigRoot(int displayId, const std::string& configName) const
128{
129    DISPLAY_HILOGI(FEAT_BRIGHTNESS, "[%{public}d] LoadConfigRoot [%{public}s]!", displayId, configName.c_str());
130    const std::string configPath = LoadConfigPath(displayId, configName);
131    std::ifstream fileStream(configPath, std::ios::in | std::ios::binary);
132    if (!fileStream) {
133        DISPLAY_HILOGE(FEAT_BRIGHTNESS, "Open file %{public}s failure.", configName.c_str());
134        return Json::Value();
135    }
136    Json::Reader reader;
137    Json::Value root;
138    if (reader.parse(fileStream, root)) {
139        fileStream.close();
140        return root;
141    }
142    fileStream.close();
143    return Json::Value();
144}
145
146void ConfigParserBase::ParsePointXy(
147    const Json::Value& root, const std::string& name, std::vector<PointXy>& data) const
148{
149    data.clear();
150    if (!root[name.c_str()].isArray()) {
151        DISPLAY_HILOGW(FEAT_BRIGHTNESS, "root <%{public}s> is not found!", name.c_str());
152        return;
153    }
154    Json::Value array = root[name.c_str()];
155    for (auto value : array) {
156        if (!value.isArray()) {
157            DISPLAY_HILOGW(FEAT_BRIGHTNESS, "array <%{public}s> is not found!", name.c_str());
158            return;
159        }
160        PointXy pointXy{};
161        if (static_cast<uint32_t>(value.size()) != POINT_XY_SIZE) {
162            DISPLAY_HILOGW(FEAT_BRIGHTNESS, "array <%{public}s> size!=%{public}d!", name.c_str(), POINT_XY_SIZE);
163            return;
164        }
165        if (value[0].isNumeric()) {
166            pointXy.x = value[0].asFloat();
167        } else {
168            DISPLAY_HILOGW(FEAT_BRIGHTNESS, "parse [%{public}s] error!", name.c_str());
169        }
170        if (value[1].isNumeric()) {
171            pointXy.y = value[1].asFloat();
172        } else {
173            DISPLAY_HILOGW(FEAT_BRIGHTNESS, "parse [%{public}s] error!", name.c_str());
174        }
175        data.emplace_back(pointXy);
176    }
177}
178
179const std::string ConfigParserBase::PointXyToString(
180    const std::string& name, const std::vector<PointXy>& data) const
181{
182    std::string text{};
183    text.append(name).append(": ");
184    for (auto value : data) {
185        text.append(std::to_string(value.x)).append(" ").append(std::to_string(value.y)).append(", ");
186    }
187    return text;
188}
189
190
191void ConfigParserBase::ParseScreenData(const Json::Value& root, const std::string& name,
192    std::unordered_map<int, ScreenData>& data, const std::string paramName) const
193{
194    data.clear();
195    if (!root[name.c_str()].isArray()) {
196        DISPLAY_HILOGW(FEAT_BRIGHTNESS, "root <%{public}s> is not found!", name.c_str());
197        return;
198    }
199    Json::Value array = root[name.c_str()];
200    for (auto value : array) {
201        ScreenData screenData{};
202        int displayMode = 0;
203        if (value[paramName].isNumeric()) {
204            displayMode = value[paramName].asInt();
205        }
206        if (value["displayId"].isNumeric()) {
207            screenData.displayId = value["displayId"].asInt();
208        }
209        if (value["sensorId"].isNumeric()) {
210            screenData.sensorId = value["sensorId"].asInt();
211        }
212        data[displayMode] = screenData;
213    }
214}
215
216const std::string ConfigParserBase::ScreenDataToString(const std::string& name,
217    const std::unordered_map<int, ScreenData>& data, const std::string paramName) const
218{
219    std::string text{};
220    text.append(name).append(": ");
221    for (const auto& [key, value] : data) {
222        text.append(paramName).append(": ").append(std::to_string(key)).append(" ");
223        text.append("displayId").append(": ").append(std::to_string(value.displayId)).append(" ");
224        text.append("sensorId").append(": ").append(std::to_string(value.sensorId)).append(" ");
225    }
226    return text;
227}
228} // namespace DisplayPowerMgr
229} // namespace OHOS
230