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
16 #include "window_manager_config.h"
17 #include "config_policy_utils.h"
18 #include "window_helper.h"
19 #include "window_manager_hilog.h"
20
21 namespace OHOS {
22 namespace Rosen {
23 namespace {
24 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowManagerConfig"};
25 }
26
27 WindowManagerConfig::ConfigItem WindowManagerConfig::config_;
28 const WindowManagerConfig::ConfigItem WindowManagerConfig::ConfigItem::DEFAULT;
29 const std::map<std::string, WindowManagerConfig::ValueType> WindowManagerConfig::configItemTypeMap_ = {
30 { "maxAppWindowNumber", WindowManagerConfig::ValueType::INTS },
31 { "maxUniRenderAppWindowNumber", WindowManagerConfig::ValueType::INTS },
32 { "modeChangeHotZones", WindowManagerConfig::ValueType::INTS },
33 { "duration", WindowManagerConfig::ValueType::INTS },
34 { "durationIn", WindowManagerConfig::ValueType::INTS },
35 { "durationOut", WindowManagerConfig::ValueType::INTS },
36 { "defaultWindowMode", WindowManagerConfig::ValueType::INTS },
37 { "floatingBottomPosY", WindowManagerConfig::ValueType::INTS },
38 { "defaultFloatingWindow", WindowManagerConfig::ValueType::INTS },
39 { "windowAnimation", WindowManagerConfig::ValueType::MAP },
40 { "keyboardAnimation", WindowManagerConfig::ValueType::MAP },
41 { "timing", WindowManagerConfig::ValueType::MAP },
42 { "windowEffect", WindowManagerConfig::ValueType::MAP },
43 { "appWindows", WindowManagerConfig::ValueType::MAP },
44 { "cornerRadius", WindowManagerConfig::ValueType::MAP },
45 { "shadow", WindowManagerConfig::ValueType::MAP },
46 { "focused", WindowManagerConfig::ValueType::MAP },
47 { "unfocused", WindowManagerConfig::ValueType::MAP },
48 { "curve", WindowManagerConfig::ValueType::POSITIVE_FLOATS },
49 { "splitRatios", WindowManagerConfig::ValueType::POSITIVE_FLOATS },
50 { "exitSplitRatios", WindowManagerConfig::ValueType::POSITIVE_FLOATS },
51 { "scale", WindowManagerConfig::ValueType::POSITIVE_FLOATS },
52 { "opacity", WindowManagerConfig::ValueType::POSITIVE_FLOATS },
53 { "elevation", WindowManagerConfig::ValueType::POSITIVE_FLOATS },
54 { "alpha", WindowManagerConfig::ValueType::POSITIVE_FLOATS },
55 { "rotation", WindowManagerConfig::ValueType::FLOATS },
56 { "translate", WindowManagerConfig::ValueType::FLOATS },
57 { "offsetX", WindowManagerConfig::ValueType::FLOATS },
58 { "offsetY", WindowManagerConfig::ValueType::FLOATS },
59 { "fullScreen", WindowManagerConfig::ValueType::STRING },
60 { "split", WindowManagerConfig::ValueType::STRING },
61 { "float", WindowManagerConfig::ValueType::STRING },
62 { "color", WindowManagerConfig::ValueType::STRING },
63 { "decor", WindowManagerConfig::ValueType::UNDIFINED },
64 { "minimizeByOther", WindowManagerConfig::ValueType::UNDIFINED },
65 { "stretchable", WindowManagerConfig::ValueType::UNDIFINED },
66 { "remoteAnimation", WindowManagerConfig::ValueType::UNDIFINED },
67 };
68
ReadNumberStrings(const xmlNodePtr & node)69 std::vector<std::string> WindowManagerConfig::ReadNumberStrings(const xmlNodePtr& node)
70 {
71 xmlChar* context = xmlNodeGetContent(node);
72 if (context == nullptr) {
73 WLOGFE("[WmConfig] read xml node error: nodeName:(%{public}s)", node->name);
74 return std::vector<std::string>();
75 }
76
77 std::string numbersStr = reinterpret_cast<const char*>(context);
78 xmlFree(context);
79 if (numbersStr.size() == 0) {
80 return std::vector<std::string>();
81 }
82 return WindowHelper::Split(numbersStr, " ");
83 }
84
GetConfigPath(const std::string & configFileName)85 std::string WindowManagerConfig::GetConfigPath(const std::string& configFileName)
86 {
87 char buf[PATH_MAX + 1];
88 char* configPath = GetOneCfgFile(configFileName.c_str(), buf, PATH_MAX + 1);
89 char tmpPath[PATH_MAX + 1] = { 0 };
90 if (!configPath || strlen(configPath) == 0 || strlen(configPath) > PATH_MAX || !realpath(configPath, tmpPath)) {
91 WLOGFI("[WmConfig] can not get customization config file");
92 return "/system/" + configFileName;
93 }
94 return std::string(tmpPath);
95 }
96
ReadConfig(const xmlNodePtr & rootPtr,std::map<std::string,ConfigItem> & mapValue)97 void WindowManagerConfig::ReadConfig(const xmlNodePtr& rootPtr, std::map<std::string, ConfigItem>& mapValue)
98 {
99 for (xmlNodePtr curNodePtr = rootPtr->xmlChildrenNode; curNodePtr != nullptr; curNodePtr = curNodePtr->next) {
100 if (!IsValidNode(*curNodePtr)) {
101 WLOGFE("[WmConfig]: invalid node!");
102 continue;
103 }
104 std::string nodeName = reinterpret_cast<const char*>(curNodePtr->name);
105 if (configItemTypeMap_.count(nodeName)) {
106 std::map<std::string, ConfigItem> p;
107 ReadProperty(curNodePtr, p);
108 if (p.size() > 0) {
109 mapValue[reinterpret_cast<const char*>(curNodePtr->name)].SetProperty(p);
110 }
111 switch (configItemTypeMap_.at(nodeName)) {
112 case ValueType::INTS: {
113 std::vector<int> v;
114 ReadIntNumbersConfigInfo(curNodePtr, v);
115 mapValue[reinterpret_cast<const char*>(curNodePtr->name)].SetValue(v);
116 break;
117 }
118 case ValueType::POSITIVE_FLOATS: {
119 std::vector<float> v;
120 ReadFloatNumbersConfigInfo(curNodePtr, v, false);
121 mapValue[reinterpret_cast<const char*>(curNodePtr->name)].SetValue(v);
122 break;
123 }
124 case ValueType::FLOATS: {
125 std::vector<float> v;
126 ReadFloatNumbersConfigInfo(curNodePtr, v, true);
127 mapValue[reinterpret_cast<const char*>(curNodePtr->name)].SetValue(v);
128 break;
129 }
130 case ValueType::MAP: {
131 std::map<std::string, ConfigItem> v;
132 ReadConfig(curNodePtr, v);
133 mapValue[reinterpret_cast<const char*>(curNodePtr->name)].SetValue(v);
134 break;
135 }
136 case ValueType::STRING: {
137 std::string v;
138 ReadStringConfigInfo(curNodePtr, v);
139 mapValue[reinterpret_cast<const char*>(curNodePtr->name)].SetValue(v);
140 break;
141 }
142 default:
143 break;
144 }
145 }
146 }
147 }
148
LoadConfigXml()149 bool WindowManagerConfig::LoadConfigXml()
150 {
151 auto configFilePath = GetConfigPath("etc/window/resources/window_manager_config.xml");
152 xmlDocPtr docPtr = xmlReadFile(configFilePath.c_str(), nullptr, XML_PARSE_NOBLANKS);
153 WLOGFI("[WmConfig] filePath: %{public}s", configFilePath.c_str());
154 if (docPtr == nullptr) {
155 WLOGFE("[WmConfig] load xml error!");
156 return false;
157 }
158
159 xmlNodePtr rootPtr = xmlDocGetRootElement(docPtr);
160 if (rootPtr == nullptr || rootPtr->name == nullptr ||
161 xmlStrcmp(rootPtr->name, reinterpret_cast<const xmlChar*>("Configs"))) {
162 WLOGFE("[WmConfig] get root element failed!");
163 xmlFreeDoc(docPtr);
164 return false;
165 }
166
167 std::map<std::string, ConfigItem> configMap;
168 config_.SetValue(configMap);
169 ReadConfig(rootPtr, *config_.mapValue_);
170
171 xmlFreeDoc(docPtr);
172 return true;
173 }
174
IsValidNode(const xmlNode & currNode)175 bool WindowManagerConfig::IsValidNode(const xmlNode& currNode)
176 {
177 if (currNode.name == nullptr || currNode.type == XML_COMMENT_NODE) {
178 return false;
179 }
180 return true;
181 }
182
ReadProperty(const xmlNodePtr & currNode,std::map<std::string,ConfigItem> & property)183 void WindowManagerConfig::ReadProperty(const xmlNodePtr& currNode,
184 std::map<std::string, ConfigItem>& property)
185 {
186 xmlChar* prop = xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("enable"));
187 if (prop != nullptr) {
188 if (!xmlStrcmp(prop, reinterpret_cast<const xmlChar*>("true"))) {
189 property["enable"].SetValue(true);
190 } else if (!xmlStrcmp(prop, reinterpret_cast<const xmlChar*>("false"))) {
191 property["enable"].SetValue(false);
192 }
193 xmlFree(prop);
194 }
195
196 prop = xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("name"));
197 if (prop != nullptr) {
198 property["name"].SetValue(std::string(reinterpret_cast<const char*>(prop)));
199 xmlFree(prop);
200 }
201 }
202
ReadIntNumbersConfigInfo(const xmlNodePtr & currNode,std::vector<int> & intsValue)203 void WindowManagerConfig::ReadIntNumbersConfigInfo(const xmlNodePtr& currNode, std::vector<int>& intsValue)
204 {
205 auto numbers = ReadNumberStrings(currNode);
206 for (auto& num : numbers) {
207 if (!WindowHelper::IsNumber(num)) {
208 WLOGFE("[WmConfig] read int number error: nodeName:(%{public}s)", currNode->name);
209 return;
210 }
211 intsValue.push_back(std::stoi(num));
212 }
213 }
214
ReadFloatNumbersConfigInfo(const xmlNodePtr & currNode,std::vector<float> & floatsValue,bool allowNeg)215 void WindowManagerConfig::ReadFloatNumbersConfigInfo(const xmlNodePtr& currNode,
216 std::vector<float>& floatsValue, bool allowNeg)
217 {
218 auto numbers = ReadNumberStrings(currNode);
219 for (auto& num : numbers) {
220 if (!WindowHelper::IsFloatingNumber(num, allowNeg)) {
221 WLOGFE("[WmConfig] read float number error: nodeName:(%{public}s)", currNode->name);
222 return;
223 }
224 floatsValue.push_back(std::stof(num));
225 }
226 }
227
ReadStringConfigInfo(const xmlNodePtr & currNode,std::string & stringValue)228 void WindowManagerConfig::ReadStringConfigInfo(const xmlNodePtr& currNode, std::string& stringValue)
229 {
230 xmlChar* context = xmlNodeGetContent(currNode);
231 if (context == nullptr) {
232 WLOGFE("[WmConfig] read xml node error: nodeName:(%{public}s)", currNode->name);
233 return;
234 }
235
236 stringValue = std::string(reinterpret_cast<const char*>(context));
237 xmlFree(context);
238 }
239
DumpConfig(const std::map<std::string,ConfigItem> & config)240 void WindowManagerConfig::DumpConfig(const std::map<std::string, ConfigItem>& config)
241 {
242 for (auto& conf : config) {
243 WLOGFI("[WmConfig] %{public}s", conf.first.c_str());
244 std::map<std::string, ConfigItem> propMap;
245 if (conf.second.property_) {
246 propMap = *conf.second.property_;
247 }
248 for (auto prop : propMap) {
249 switch (prop.second.type_) {
250 case ValueType::BOOL:
251 WLOGFI("[WmConfig] Prop: %{public}s %{public}u", prop.first.c_str(), prop.second.boolValue_);
252 break;
253 case ValueType::STRING:
254 WLOGFI("[WmConfig] Prop: %{public}s %{public}s", prop.first.c_str(),
255 prop.second.stringValue_.c_str());
256 break;
257 default:
258 break;
259 }
260 }
261 switch (conf.second.type_) {
262 case ValueType::MAP:
263 if (conf.second.mapValue_) {
264 DumpConfig(*conf.second.mapValue_);
265 }
266 break;
267 case ValueType::BOOL:
268 WLOGFI("[WmConfig] %{public}u", conf.second.boolValue_);
269 break;
270 case ValueType::STRING:
271 WLOGFI("[WmConfig] %{public}s", conf.second.stringValue_.c_str());
272 break;
273 case ValueType::INTS:
274 for (auto& num : *conf.second.intsValue_) {
275 WLOGFI("[WmConfig] Num: %{public}d", num);
276 }
277 break;
278 case ValueType::FLOATS:
279 for (auto& num : *conf.second.floatsValue_) {
280 WLOGFI("[WmConfig] Num: %{public}f", num);
281 }
282 break;
283 default:
284 break;
285 }
286 }
287 }
288 } // namespace Rosen
289 } // namespace OHOS
290