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