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