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