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