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 { "maxMidSceneNum", WindowSceneConfig::ValueType::INTS },
100 };
101
SplitNodeContent(const xmlNodePtr & node,const std::string & pattern)102 std::vector<std::string> WindowSceneConfig::SplitNodeContent(const xmlNodePtr& node, const std::string& pattern)
103 {
104 xmlChar* content = xmlNodeGetContent(node);
105 if (content == nullptr) {
106 WLOGFE("read xml node error: nodeName:(%{public}s)", node->name);
107 return std::vector<std::string>();
108 }
109
110 std::string contentStr = reinterpret_cast<const char*>(content);
111 xmlFree(content);
112 if (contentStr.size() == 0) {
113 return std::vector<std::string>();
114 }
115 return WindowHelper::Split(contentStr, pattern);
116 }
117
GetConfigPath(const std::string & configFileName)118 std::string WindowSceneConfig::GetConfigPath(const std::string& configFileName)
119 {
120 char buf[PATH_MAX + 1];
121 char* configPath = GetOneCfgFile(configFileName.c_str(), buf, PATH_MAX + 1);
122 char tmpPath[PATH_MAX + 1] = { 0 };
123 if (!configPath || strlen(configPath) == 0 || strlen(configPath) > PATH_MAX || !realpath(configPath, tmpPath)) {
124 WLOGI("can not get customization config file");
125 return "/system/" + configFileName;
126 }
127 return std::string(tmpPath);
128 }
129
ReadConfig(const xmlNodePtr & rootPtr,std::map<std::string,ConfigItem> & mapValue)130 void WindowSceneConfig::ReadConfig(const xmlNodePtr& rootPtr, std::map<std::string, ConfigItem>& mapValue)
131 {
132 for (xmlNodePtr curNodePtr = rootPtr->xmlChildrenNode; curNodePtr != nullptr; curNodePtr = curNodePtr->next) {
133 if (!IsValidNode(*curNodePtr)) {
134 WLOGFE("[WmConfig]: invalid node!");
135 continue;
136 }
137 std::string nodeName = reinterpret_cast<const char*>(curNodePtr->name);
138 if (configItemTypeMap_.count(nodeName)) {
139 std::map<std::string, ConfigItem> p = ReadProperty(curNodePtr);
140 if (p.size() > 0) {
141 mapValue[reinterpret_cast<const char*>(curNodePtr->name)].SetProperty(p);
142 }
143 switch (configItemTypeMap_.at(nodeName)) {
144 case ValueType::INTS: {
145 std::vector<int> v = ReadIntNumbersConfigInfo(curNodePtr);
146 mapValue[reinterpret_cast<const char*>(curNodePtr->name)].SetValue(v);
147 break;
148 }
149 case ValueType::POSITIVE_FLOATS: {
150 std::vector<float> v = ReadFloatNumbersConfigInfo(curNodePtr, false);
151 mapValue[reinterpret_cast<const char*>(curNodePtr->name)].SetValue(v);
152 break;
153 }
154 case ValueType::FLOATS: {
155 std::vector<float> v = ReadFloatNumbersConfigInfo(curNodePtr, true);
156 mapValue[reinterpret_cast<const char*>(curNodePtr->name)].SetValue(v);
157 break;
158 }
159 case ValueType::MAP: {
160 std::map<std::string, ConfigItem> v;
161 ReadConfig(curNodePtr, v);
162 mapValue[reinterpret_cast<const char*>(curNodePtr->name)].SetValue(v);
163 break;
164 }
165 case ValueType::STRING: {
166 std::string v = ReadStringConfigInfo(curNodePtr);
167 mapValue[reinterpret_cast<const char*>(curNodePtr->name)].SetValue(v);
168 break;
169 }
170 case ValueType::STRINGS: {
171 std::vector<std::string> v = ReadStringsConfigInfo(curNodePtr);
172 mapValue[reinterpret_cast<const char*>(curNodePtr->name)].SetValue(v);
173 break;
174 }
175 default:
176 break;
177 }
178 }
179 }
180 }
181
LoadConfigXml()182 bool WindowSceneConfig::LoadConfigXml()
183 {
184 auto configFilePath = GetConfigPath("etc/window/resources/window_manager_config.xml");
185 xmlDocPtr docPtr = nullptr;
186 {
187 std::lock_guard<std::recursive_mutex> lock(mutex_);
188 docPtr = xmlReadFile(configFilePath.c_str(), nullptr, XML_PARSE_NOBLANKS);
189 }
190 WLOGI("filePath: %{public}s", configFilePath.c_str());
191 if (docPtr == nullptr) {
192 WLOGFE("load xml error!");
193 return false;
194 }
195
196 xmlNodePtr rootPtr = xmlDocGetRootElement(docPtr);
197 if (rootPtr == nullptr || rootPtr->name == nullptr ||
198 xmlStrcmp(rootPtr->name, reinterpret_cast<const xmlChar*>("Configs"))) {
199 WLOGFE("get root element failed!");
200 xmlFreeDoc(docPtr);
201 return false;
202 }
203
204 std::map<std::string, ConfigItem> configMap;
205 config_.SetValue(configMap);
206 ReadConfig(rootPtr, *config_.mapValue_);
207
208 xmlFreeDoc(docPtr);
209 return true;
210 }
211
IsValidNode(const xmlNode & currNode)212 bool WindowSceneConfig::IsValidNode(const xmlNode& currNode)
213 {
214 if (currNode.name == nullptr || currNode.type == XML_COMMENT_NODE) {
215 return false;
216 }
217 return true;
218 }
219
ReadProperty(const xmlNodePtr & currNode)220 std::map<std::string, XmlConfigBase::ConfigItem> WindowSceneConfig::ReadProperty(const xmlNodePtr& currNode)
221 {
222 std::map<std::string, ConfigItem> property;
223 xmlChar* prop = xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("enable"));
224 if (prop != nullptr) {
225 if (!xmlStrcmp(prop, reinterpret_cast<const xmlChar*>("true"))) {
226 property["enable"].SetValue(true);
227 } else if (!xmlStrcmp(prop, reinterpret_cast<const xmlChar*>("false"))) {
228 property["enable"].SetValue(false);
229 }
230 xmlFree(prop);
231 }
232
233 prop = xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("name"));
234 if (prop != nullptr) {
235 property["name"].SetValue(std::string(reinterpret_cast<const char*>(prop)));
236 xmlFree(prop);
237 }
238
239 return property;
240 }
241
ReadIntNumbersConfigInfo(const xmlNodePtr & currNode)242 std::vector<int> WindowSceneConfig::ReadIntNumbersConfigInfo(const xmlNodePtr& currNode)
243 {
244 std::vector<int> intsValue;
245 auto numbers = SplitNodeContent(currNode);
246 for (auto& num : numbers) {
247 if (!WindowHelper::IsNumber(num)) {
248 WLOGFE("read int number error: nodeName:(%{public}s)", currNode->name);
249 return {};
250 }
251 intsValue.push_back(std::stoi(num));
252 }
253 return intsValue;
254 }
255
ReadStringsConfigInfo(const xmlNodePtr & currNode)256 std::vector<std::string> WindowSceneConfig::ReadStringsConfigInfo(const xmlNodePtr& currNode)
257 {
258 return SplitNodeContent(currNode);
259 }
260
ReadFloatNumbersConfigInfo(const xmlNodePtr & currNode,bool allowNeg)261 std::vector<float> WindowSceneConfig::ReadFloatNumbersConfigInfo(const xmlNodePtr& currNode, bool allowNeg)
262 {
263 std::vector<float> floatsValue;
264 auto numbers = SplitNodeContent(currNode);
265 for (auto& num : numbers) {
266 if (!WindowHelper::IsFloatingNumber(num, allowNeg)) {
267 WLOGFE("read float number error: nodeName:(%{public}s)", currNode->name);
268 return {};
269 }
270 floatsValue.push_back(std::stof(num));
271 }
272 return floatsValue;
273 }
274
ReadStringConfigInfo(const xmlNodePtr & currNode)275 std::string WindowSceneConfig::ReadStringConfigInfo(const xmlNodePtr& currNode)
276 {
277 std::string stringValue;
278 xmlChar* context = xmlNodeGetContent(currNode);
279 if (context == nullptr) {
280 WLOGFE("read xml node error: nodeName:(%{public}s)", currNode->name);
281 return {};
282 }
283
284 stringValue = std::string(reinterpret_cast<const char*>(context));
285 xmlFree(context);
286 return stringValue;
287 }
288
DumpConfig(const std::map<std::string,ConfigItem> & config)289 void WindowSceneConfig::DumpConfig(const std::map<std::string, ConfigItem>& config)
290 {
291 for (auto& conf : config) {
292 WLOGI("%{public}s", conf.first.c_str());
293 std::map<std::string, ConfigItem> propMap;
294 if (conf.second.property_) {
295 propMap = *conf.second.property_;
296 }
297 for (auto prop : propMap) {
298 switch (prop.second.type_) {
299 case ValueType::BOOL:
300 WLOGI("Prop: %{public}s %{public}u", prop.first.c_str(), prop.second.boolValue_);
301 break;
302 case ValueType::STRING:
303 WLOGI("Prop: %{public}s %{public}s", prop.first.c_str(),
304 prop.second.stringValue_.c_str());
305 break;
306 default:
307 break;
308 }
309 }
310 switch (conf.second.type_) {
311 case ValueType::MAP:
312 if (conf.second.mapValue_) {
313 DumpConfig(*conf.second.mapValue_);
314 }
315 break;
316 case ValueType::BOOL:
317 WLOGI("%{public}u", conf.second.boolValue_);
318 break;
319 case ValueType::STRING:
320 WLOGI("%{public}s", conf.second.stringValue_.c_str());
321 break;
322 case ValueType::INTS:
323 for (auto& num : *conf.second.intsValue_) {
324 WLOGI("Num: %{public}d", num);
325 }
326 break;
327 case ValueType::FLOATS:
328 for (auto& num : *conf.second.floatsValue_) {
329 WLOGI("Num: %{public}f", num);
330 }
331 break;
332 default:
333 break;
334 }
335 }
336 }
337
338 } // namespace Rosen
339 } // namespace OHOS
340