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