1e0dac50fSopenharmony_ci/*
2e0dac50fSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3e0dac50fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4e0dac50fSopenharmony_ci * you may not use this file except in compliance with the License.
5e0dac50fSopenharmony_ci * You may obtain a copy of the License at
6e0dac50fSopenharmony_ci *
7e0dac50fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8e0dac50fSopenharmony_ci *
9e0dac50fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10e0dac50fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11e0dac50fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e0dac50fSopenharmony_ci * See the License for the specific language governing permissions and
13e0dac50fSopenharmony_ci * limitations under the License.
14e0dac50fSopenharmony_ci */
15e0dac50fSopenharmony_ci#include "display_manager_config.h"
16e0dac50fSopenharmony_ci
17e0dac50fSopenharmony_ci#include <climits>
18e0dac50fSopenharmony_ci#include <cstdint>
19e0dac50fSopenharmony_ci#include <cstdlib>
20e0dac50fSopenharmony_ci#include <libxml/globals.h>
21e0dac50fSopenharmony_ci#include <libxml/xmlstring.h>
22e0dac50fSopenharmony_ci#include <map>
23e0dac50fSopenharmony_ci#include <string>
24e0dac50fSopenharmony_ci#include <utility>
25e0dac50fSopenharmony_ci#include <vector>
26e0dac50fSopenharmony_ci
27e0dac50fSopenharmony_ci#include "config_policy_utils.h"
28e0dac50fSopenharmony_ci#include "window_manager_hilog.h"
29e0dac50fSopenharmony_ci
30e0dac50fSopenharmony_ci
31e0dac50fSopenharmony_cinamespace OHOS::Rosen {
32e0dac50fSopenharmony_cinamespace {
33e0dac50fSopenharmony_ciconstexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayManagerConfig"};
34e0dac50fSopenharmony_ci}
35e0dac50fSopenharmony_ci
36e0dac50fSopenharmony_cistd::map<std::string, bool> DisplayManagerConfig::enableConfig_;
37e0dac50fSopenharmony_cistd::map<std::string, std::vector<int>> DisplayManagerConfig::intNumbersConfig_;
38e0dac50fSopenharmony_cistd::map<std::string, std::string> DisplayManagerConfig::stringConfig_;
39e0dac50fSopenharmony_ci
40e0dac50fSopenharmony_cistd::vector<std::string> DisplayManagerConfig::Split(std::string str, std::string pattern)
41e0dac50fSopenharmony_ci{
42e0dac50fSopenharmony_ci    std::vector<std::string> result;
43e0dac50fSopenharmony_ci    str += pattern;
44e0dac50fSopenharmony_ci    size_t length = str.size();
45e0dac50fSopenharmony_ci    for (size_t i = 0; i < length; i++) {
46e0dac50fSopenharmony_ci        size_t position = str.find(pattern, i);
47e0dac50fSopenharmony_ci        if (position < length) {
48e0dac50fSopenharmony_ci            std::string tmp = str.substr(i, position - i);
49e0dac50fSopenharmony_ci            result.push_back(tmp);
50e0dac50fSopenharmony_ci            i = position + pattern.size() - 1;
51e0dac50fSopenharmony_ci        }
52e0dac50fSopenharmony_ci    }
53e0dac50fSopenharmony_ci    return result;
54e0dac50fSopenharmony_ci}
55e0dac50fSopenharmony_ci
56e0dac50fSopenharmony_cibool inline DisplayManagerConfig::IsNumber(std::string str)
57e0dac50fSopenharmony_ci{
58e0dac50fSopenharmony_ci    for (int32_t i = 0; i < static_cast<int32_t>(str.size()); i++) {
59e0dac50fSopenharmony_ci        if (str.at(i) < '0' || str.at(i) > '9') {
60e0dac50fSopenharmony_ci            return false;
61e0dac50fSopenharmony_ci        }
62e0dac50fSopenharmony_ci    }
63e0dac50fSopenharmony_ci    return true;
64e0dac50fSopenharmony_ci}
65e0dac50fSopenharmony_ci
66e0dac50fSopenharmony_cistd::string DisplayManagerConfig::GetConfigPath(const std::string& configFileName)
67e0dac50fSopenharmony_ci{
68e0dac50fSopenharmony_ci    char buf[PATH_MAX + 1];
69e0dac50fSopenharmony_ci    char* configPath = GetOneCfgFile(configFileName.c_str(), buf, PATH_MAX + 1);
70e0dac50fSopenharmony_ci    char tmpPath[PATH_MAX + 1] = { 0 };
71e0dac50fSopenharmony_ci    if (!configPath || strlen(configPath) == 0 || strlen(configPath) > PATH_MAX || !realpath(configPath, tmpPath)) {
72e0dac50fSopenharmony_ci        WLOGFI("[DmConfig] can not get customization config file");
73e0dac50fSopenharmony_ci        return "/system/" + configFileName;
74e0dac50fSopenharmony_ci    }
75e0dac50fSopenharmony_ci    return std::string(tmpPath);
76e0dac50fSopenharmony_ci}
77e0dac50fSopenharmony_ci
78e0dac50fSopenharmony_cibool DisplayManagerConfig::LoadConfigXml()
79e0dac50fSopenharmony_ci{
80e0dac50fSopenharmony_ci    auto configFilePath = GetConfigPath("etc/window/resources/display_manager_config.xml");
81e0dac50fSopenharmony_ci    xmlDocPtr docPtr = nullptr;
82e0dac50fSopenharmony_ci    {
83e0dac50fSopenharmony_ci        std::lock_guard<std::recursive_mutex> lock(mutex_);
84e0dac50fSopenharmony_ci        docPtr = xmlReadFile(configFilePath.c_str(), nullptr, XML_PARSE_NOBLANKS);
85e0dac50fSopenharmony_ci    }
86e0dac50fSopenharmony_ci    WLOGFI("[DmConfig] filePath: %{public}s", configFilePath.c_str());
87e0dac50fSopenharmony_ci    if (docPtr == nullptr) {
88e0dac50fSopenharmony_ci        WLOGFE("[DmConfig] load xml error!");
89e0dac50fSopenharmony_ci        return false;
90e0dac50fSopenharmony_ci    }
91e0dac50fSopenharmony_ci
92e0dac50fSopenharmony_ci    xmlNodePtr rootPtr = xmlDocGetRootElement(docPtr);
93e0dac50fSopenharmony_ci    if (rootPtr == nullptr || rootPtr->name == nullptr ||
94e0dac50fSopenharmony_ci        xmlStrcmp(rootPtr->name, reinterpret_cast<const xmlChar*>("Configs"))) {
95e0dac50fSopenharmony_ci        WLOGFE("[DmConfig] get root element failed!");
96e0dac50fSopenharmony_ci        xmlFreeDoc(docPtr);
97e0dac50fSopenharmony_ci        return false;
98e0dac50fSopenharmony_ci    }
99e0dac50fSopenharmony_ci
100e0dac50fSopenharmony_ci    for (xmlNodePtr curNodePtr = rootPtr->xmlChildrenNode; curNodePtr != nullptr; curNodePtr = curNodePtr->next) {
101e0dac50fSopenharmony_ci        if (!IsValidNode(*curNodePtr)) {
102e0dac50fSopenharmony_ci            WLOGFE("DmConfig]: invalid node!");
103e0dac50fSopenharmony_ci            continue;
104e0dac50fSopenharmony_ci        }
105e0dac50fSopenharmony_ci
106e0dac50fSopenharmony_ci        auto nodeName = curNodePtr->name;
107e0dac50fSopenharmony_ci        if (!xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("isWaterfallDisplay")) ||
108e0dac50fSopenharmony_ci            !xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("isWaterfallAreaCompressionEnableWhenHorizontal"))) {
109e0dac50fSopenharmony_ci            ReadEnableConfigInfo(curNodePtr);
110e0dac50fSopenharmony_ci            continue;
111e0dac50fSopenharmony_ci        }
112e0dac50fSopenharmony_ci        if (!xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("dpi")) ||
113e0dac50fSopenharmony_ci            !xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("defaultDeviceRotationOffset")) ||
114e0dac50fSopenharmony_ci            !xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("cutoutArea")) ||
115e0dac50fSopenharmony_ci            !xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("curvedScreenBoundary")) ||
116e0dac50fSopenharmony_ci            !xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("waterfallAreaCompressionSizeWhenHorzontal")) ||
117e0dac50fSopenharmony_ci            !xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("buildInDefaultOrientation"))) {
118e0dac50fSopenharmony_ci            ReadIntNumbersConfigInfo(curNodePtr);
119e0dac50fSopenharmony_ci            continue;
120e0dac50fSopenharmony_ci        }
121e0dac50fSopenharmony_ci        if (!xmlStrcmp(nodeName, reinterpret_cast<const xmlChar*>("defaultDisplayCutoutPath"))) {
122e0dac50fSopenharmony_ci            ReadStringConfigInfo(curNodePtr);
123e0dac50fSopenharmony_ci            continue;
124e0dac50fSopenharmony_ci        }
125e0dac50fSopenharmony_ci    }
126e0dac50fSopenharmony_ci    xmlFreeDoc(docPtr);
127e0dac50fSopenharmony_ci    return true;
128e0dac50fSopenharmony_ci}
129e0dac50fSopenharmony_ci
130e0dac50fSopenharmony_cibool DisplayManagerConfig::IsValidNode(const xmlNode& currNode)
131e0dac50fSopenharmony_ci{
132e0dac50fSopenharmony_ci    if (currNode.name == nullptr || currNode.type == XML_COMMENT_NODE) {
133e0dac50fSopenharmony_ci        return false;
134e0dac50fSopenharmony_ci    }
135e0dac50fSopenharmony_ci    return true;
136e0dac50fSopenharmony_ci}
137e0dac50fSopenharmony_ci
138e0dac50fSopenharmony_civoid DisplayManagerConfig::ReadIntNumbersConfigInfo(const xmlNodePtr& currNode)
139e0dac50fSopenharmony_ci{
140e0dac50fSopenharmony_ci    xmlChar* context = xmlNodeGetContent(currNode);
141e0dac50fSopenharmony_ci    if (context == nullptr) {
142e0dac50fSopenharmony_ci        WLOGFE("[DmConfig] read xml node error: nodeName:(%{public}s)", currNode->name);
143e0dac50fSopenharmony_ci        return;
144e0dac50fSopenharmony_ci    }
145e0dac50fSopenharmony_ci
146e0dac50fSopenharmony_ci    std::vector<int> numbersVec;
147e0dac50fSopenharmony_ci    std::string numbersStr = reinterpret_cast<const char*>(context);
148e0dac50fSopenharmony_ci    if (numbersStr.empty()) {
149e0dac50fSopenharmony_ci        xmlFree(context);
150e0dac50fSopenharmony_ci        return;
151e0dac50fSopenharmony_ci    }
152e0dac50fSopenharmony_ci    auto numbers = Split(numbersStr, " ");
153e0dac50fSopenharmony_ci    for (auto& num : numbers) {
154e0dac50fSopenharmony_ci        if (!IsNumber(num)) {
155e0dac50fSopenharmony_ci            WLOGFE("[DmConfig] read number error: nodeName:(%{public}s)", currNode->name);
156e0dac50fSopenharmony_ci            xmlFree(context);
157e0dac50fSopenharmony_ci            return;
158e0dac50fSopenharmony_ci        }
159e0dac50fSopenharmony_ci        numbersVec.emplace_back(std::stoi(num));
160e0dac50fSopenharmony_ci    }
161e0dac50fSopenharmony_ci
162e0dac50fSopenharmony_ci    std::string nodeName = reinterpret_cast<const char *>(currNode->name);
163e0dac50fSopenharmony_ci    intNumbersConfig_[nodeName] = numbersVec;
164e0dac50fSopenharmony_ci    xmlFree(context);
165e0dac50fSopenharmony_ci}
166e0dac50fSopenharmony_ci
167e0dac50fSopenharmony_civoid DisplayManagerConfig::ReadEnableConfigInfo(const xmlNodePtr& currNode)
168e0dac50fSopenharmony_ci{
169e0dac50fSopenharmony_ci    xmlChar* enable = xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("enable"));
170e0dac50fSopenharmony_ci    if (enable == nullptr) {
171e0dac50fSopenharmony_ci        WLOGFE("[DmConfig] read xml node error: nodeName:(%{public}s)", currNode->name);
172e0dac50fSopenharmony_ci        return;
173e0dac50fSopenharmony_ci    }
174e0dac50fSopenharmony_ci
175e0dac50fSopenharmony_ci    std::string nodeName = reinterpret_cast<const char *>(currNode->name);
176e0dac50fSopenharmony_ci    if (!xmlStrcmp(enable, reinterpret_cast<const xmlChar*>("true"))) {
177e0dac50fSopenharmony_ci        enableConfig_[nodeName] = true;
178e0dac50fSopenharmony_ci    } else {
179e0dac50fSopenharmony_ci        enableConfig_[nodeName] = false;
180e0dac50fSopenharmony_ci    }
181e0dac50fSopenharmony_ci    xmlFree(enable);
182e0dac50fSopenharmony_ci}
183e0dac50fSopenharmony_ci
184e0dac50fSopenharmony_civoid DisplayManagerConfig::ReadStringConfigInfo(const xmlNodePtr& currNode)
185e0dac50fSopenharmony_ci{
186e0dac50fSopenharmony_ci    xmlChar* context = xmlNodeGetContent(currNode);
187e0dac50fSopenharmony_ci    if (context == nullptr) {
188e0dac50fSopenharmony_ci        WLOGFE("[DmConfig] read xml node error: nodeName:(%{public}s)", currNode->name);
189e0dac50fSopenharmony_ci        return;
190e0dac50fSopenharmony_ci    }
191e0dac50fSopenharmony_ci
192e0dac50fSopenharmony_ci    std::string inputString = reinterpret_cast<const char*>(context);
193e0dac50fSopenharmony_ci    std::string nodeName = reinterpret_cast<const char*>(currNode->name);
194e0dac50fSopenharmony_ci    stringConfig_[nodeName] = inputString;
195e0dac50fSopenharmony_ci    xmlFree(context);
196e0dac50fSopenharmony_ci}
197e0dac50fSopenharmony_ci
198e0dac50fSopenharmony_ciconst std::map<std::string, bool>& DisplayManagerConfig::GetEnableConfig()
199e0dac50fSopenharmony_ci{
200e0dac50fSopenharmony_ci    return enableConfig_;
201e0dac50fSopenharmony_ci}
202e0dac50fSopenharmony_ci
203e0dac50fSopenharmony_ciconst std::map<std::string, std::vector<int>>& DisplayManagerConfig::GetIntNumbersConfig()
204e0dac50fSopenharmony_ci{
205e0dac50fSopenharmony_ci    return intNumbersConfig_;
206e0dac50fSopenharmony_ci}
207e0dac50fSopenharmony_ci
208e0dac50fSopenharmony_ciconst std::map<std::string, std::string>& DisplayManagerConfig::GetStringConfig()
209e0dac50fSopenharmony_ci{
210e0dac50fSopenharmony_ci    return stringConfig_;
211e0dac50fSopenharmony_ci}
212e0dac50fSopenharmony_ci
213e0dac50fSopenharmony_civoid DisplayManagerConfig::DumpConfig()
214e0dac50fSopenharmony_ci{
215e0dac50fSopenharmony_ci    for (auto& enable : enableConfig_) {
216e0dac50fSopenharmony_ci        WLOGFI("[DmConfig] Enable: %{public}s %{public}u", enable.first.c_str(), enable.second);
217e0dac50fSopenharmony_ci    }
218e0dac50fSopenharmony_ci    for (auto& numbers : intNumbersConfig_) {
219e0dac50fSopenharmony_ci        WLOGFI("[DmConfig] Numbers: %{public}s %{public}zu", numbers.first.c_str(), numbers.second.size());
220e0dac50fSopenharmony_ci        for (auto& num : numbers.second) {
221e0dac50fSopenharmony_ci            WLOGFI("[DmConfig] Num: %{public}d", num);
222e0dac50fSopenharmony_ci        }
223e0dac50fSopenharmony_ci    }
224e0dac50fSopenharmony_ci    for (auto& string : stringConfig_) {
225e0dac50fSopenharmony_ci        WLOGFI("[DmConfig] String: %{public}s", string.first.c_str());
226e0dac50fSopenharmony_ci    }
227e0dac50fSopenharmony_ci}
228e0dac50fSopenharmony_ci} // namespace OHOS::Rosen
229