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