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