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 #include "xml_parser.h"
16 #include <algorithm>
17
18 #include "config_policy_utils.h"
19
20 namespace OHOS::Rosen {
LoadConfiguration(const char * fileDir)21 int32_t XMLParser::LoadConfiguration(const char* fileDir)
22 {
23 HGM_LOGI("XMLParser opening xml file");
24 xmlDocument_ = xmlReadFile(fileDir, nullptr, 0);
25 if (!xmlDocument_) {
26 HGM_LOGE("XMLParser xmlReadFile failed");
27 return XML_FILE_LOAD_FAIL;
28 }
29
30 if (!mParsedData_) {
31 mParsedData_ = std::make_unique<PolicyConfigData>();
32 }
33
34 return EXEC_SUCCESS;
35 }
36
Parse()37 int32_t XMLParser::Parse()
38 {
39 HGM_LOGD("XMLParser Parse");
40 if (!xmlDocument_) {
41 HGM_LOGE("XMLParser xmlDocument_ is empty, should do LoadConfiguration first");
42 return HGM_ERROR;
43 }
44 xmlNode *root = xmlDocGetRootElement(xmlDocument_);
45 if (root == nullptr) {
46 HGM_LOGE("XMLParser xmlDocGetRootElement failed");
47 return XML_GET_ROOT_FAIL;
48 }
49
50 if (ParseInternal(*root) == false) {
51 return XML_PARSE_INTERNAL_FAIL;
52 }
53 return EXEC_SUCCESS;
54 }
55
Destroy()56 void XMLParser::Destroy()
57 {
58 HGM_LOGD("XMLParser Destroying the parser");
59 if (xmlDocument_ != nullptr) {
60 xmlFreeDoc(xmlDocument_);
61 xmlDocument_ = nullptr;
62 }
63 }
64
GetHgmXmlNodeAsInt(xmlNode & node)65 int32_t XMLParser::GetHgmXmlNodeAsInt(xmlNode &node)
66 {
67 if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("Param"))) {
68 return HGM_XML_PARAM;
69 }
70 if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("Params"))) {
71 return HGM_XML_PARAMS;
72 }
73 HGM_LOGD("XMLParser failed to identify a xml node : %{public}s", node.name);
74 return HGM_XML_UNDEFINED;
75 }
76
ParseInternal(xmlNode & node)77 bool XMLParser::ParseInternal(xmlNode &node)
78 {
79 HGM_LOGD("XMLParser parsing an internal node");
80 xmlNode *currNode = &node;
81 if (currNode->xmlChildrenNode == nullptr) {
82 HGM_LOGD("XMLParser stop parsing internal, no children nodes");
83 return false;
84 }
85 currNode = currNode->xmlChildrenNode;
86 int32_t parseSuccess = EXEC_SUCCESS;
87
88 for (; currNode; currNode = currNode->next) {
89 if (currNode->type != XML_ELEMENT_NODE) {
90 continue;
91 }
92 if (parseSuccess != EXEC_SUCCESS) {
93 return false;
94 }
95 int xmlParamType = GetHgmXmlNodeAsInt(*currNode);
96 if (xmlParamType == HGM_XML_PARAM) {
97 parseSuccess = ParseParam(*currNode);
98 } else if (xmlParamType == HGM_XML_PARAMS) {
99 parseSuccess = ParseParams(*currNode);
100 }
101 }
102 return true;
103 }
104
ParseParam(xmlNode & node)105 int32_t XMLParser::ParseParam(xmlNode &node)
106 {
107 HGM_LOGI("XMLParser parsing a parameter");
108 if (!mParsedData_) {
109 HGM_LOGE("XMLParser mParsedData_ is not initialized");
110 return HGM_ERROR;
111 }
112
113 std::string paraName = ExtractPropertyValue("name", node);
114 if (paraName == "default_refreshrate_mode") {
115 HGM_LOGD("XMLParser parsing default_refreshrate_mode");
116 std::string mode = ExtractPropertyValue("value", node);
117 mParsedData_->defaultRefreshRateMode_ = mode;
118
119 HGM_LOGI("HgmXMLParser ParseParam default_refreshrate_mode %{public}s",
120 mParsedData_->defaultRefreshRateMode_.c_str());
121 }
122
123 return EXEC_SUCCESS;
124 }
125
ParseParams(xmlNode & node)126 int32_t XMLParser::ParseParams(xmlNode &node)
127 {
128 std::string paraName = ExtractPropertyValue("name", node);
129 if (paraName.empty()) {
130 HGM_LOGD("XMLParser No name provided for %{public}s", node.name);
131 return XML_PARSE_INTERNAL_FAIL;
132 }
133 if (!mParsedData_) {
134 HGM_LOGE("XMLParser mParsedData_ is not initialized");
135 return HGM_ERROR;
136 }
137
138 int32_t setResult = EXEC_SUCCESS;
139 if (paraName == "refresh_rate_4settings") {
140 setResult = ParseSimplex(node, mParsedData_->refreshRateForSettings_);
141 } else if (paraName == "refreshRate_strategy_config") {
142 setResult = ParseStrategyConfig(node);
143 } else if (paraName == "refreshRate_virtual_display_config") {
144 if (ExtractPropertyValue("switch", node) == "1") {
145 setResult = ParseSimplex(node, mParsedData_->virtualDisplayConfigs_, "strategy");
146 mParsedData_->virtualDisplaySwitch_ = true;
147 } else {
148 mParsedData_->virtualDisplayConfigs_.clear();
149 mParsedData_->virtualDisplaySwitch_ = false;
150 }
151 } else if (paraName == "screen_strategy_config") {
152 setResult = ParseSimplex(node, mParsedData_->screenStrategyConfigs_, "type");
153 } else if (paraName == "screen_config") {
154 setResult = ParseScreenConfig(node);
155 } else {
156 setResult = 0;
157 }
158
159 if (setResult != EXEC_SUCCESS) {
160 HGM_LOGI("XMLParser failed to ParseParams %{public}s", paraName.c_str());
161 }
162 return EXEC_SUCCESS;
163 }
164
ParseStrategyConfig(xmlNode & node)165 int32_t XMLParser::ParseStrategyConfig(xmlNode &node)
166 {
167 HGM_LOGD("XMLParser parsing strategyConfig");
168 xmlNode *currNode = &node;
169 if (currNode->xmlChildrenNode == nullptr) {
170 HGM_LOGD("XMLParser stop parsing strategyConfig, no children nodes");
171 return HGM_ERROR;
172 }
173
174 // re-parse
175 mParsedData_->strategyConfigs_.clear();
176 currNode = currNode->xmlChildrenNode;
177 for (; currNode; currNode = currNode->next) {
178 if (currNode->type != XML_ELEMENT_NODE) {
179 continue;
180 }
181
182 auto name = ExtractPropertyValue("name", *currNode);
183 auto min = ExtractPropertyValue("min", *currNode);
184 auto max = ExtractPropertyValue("max", *currNode);
185 auto dynamicMode = ExtractPropertyValue("dynamicMode", *currNode);
186 auto drawMin = ExtractPropertyValue("drawMin", *currNode);
187 auto drawMax = ExtractPropertyValue("drawMax", *currNode);
188 if (!IsNumber(min) || !IsNumber(max) || !IsNumber(dynamicMode)) {
189 return HGM_ERROR;
190 }
191
192 PolicyConfigData::StrategyConfig strategy;
193 strategy.min = std::stoi(min);
194 strategy.max = std::stoi(max);
195 strategy.dynamicMode = std::stoi(dynamicMode);
196 strategy.drawMin = IsNumber(drawMin) ? std::stoi(drawMin) : 0;
197 strategy.drawMax = IsNumber(drawMax) ? std::stoi(drawMax) : 0;
198
199 mParsedData_->strategyConfigs_[name] = strategy;
200 HGM_LOGI("HgmXMLParser ParseStrategyConfig name=%{public}s min=%{public}d drawMin=%{public}d",
201 name.c_str(), mParsedData_->strategyConfigs_[name].min, mParsedData_->strategyConfigs_[name].drawMin);
202 }
203
204 return EXEC_SUCCESS;
205 }
206
ParseScreenConfig(xmlNode & node)207 int32_t XMLParser::ParseScreenConfig(xmlNode &node)
208 {
209 HGM_LOGD("XMLParser parsing screenConfig");
210 xmlNode *currNode = &node;
211 if (currNode->xmlChildrenNode == nullptr) {
212 HGM_LOGD("XMLParser stop parsing screenConfig, no children nodes");
213 return HGM_ERROR;
214 }
215
216 auto type = ExtractPropertyValue("type", *currNode);
217 PolicyConfigData::ScreenConfig screenConfig;
218 currNode = currNode->xmlChildrenNode;
219 for (; currNode; currNode = currNode->next) {
220 if (currNode->type != XML_ELEMENT_NODE) {
221 continue;
222 }
223 PolicyConfigData::ScreenSetting screenSetting;
224 auto id = ExtractPropertyValue("id", *currNode);
225 screenSetting.strategy = ExtractPropertyValue("strategy", *currNode);
226 for (xmlNode *thresholdNode = currNode->xmlChildrenNode; thresholdNode; thresholdNode = thresholdNode->next) {
227 if (thresholdNode->type != XML_ELEMENT_NODE) {
228 continue;
229 }
230 auto name = ExtractPropertyValue("name", *thresholdNode);
231 int32_t setResult = EXEC_SUCCESS;
232 if (name == "LTPO_config") {
233 setResult = ParseSimplex(*thresholdNode, screenSetting.ltpoConfig);
234 } else if (name == "property_animation_dynamic_settings") {
235 setResult = ParserDynamicSetting(*thresholdNode, screenSetting.animationDynamicSettings);
236 } else if (name == "ace_scene_dynamic_settings") {
237 setResult = ParserDynamicSetting(*thresholdNode, screenSetting.aceSceneDynamicSettings);
238 } else if (name == "scene_list") {
239 setResult = ParseSceneList(*thresholdNode, screenSetting.sceneList);
240 } else if (name == "app_list") {
241 setResult = ParseSimplex(*thresholdNode, screenSetting.appList, "strategy");
242 } else {
243 setResult = 0;
244 }
245
246 if (setResult != EXEC_SUCCESS) {
247 HGM_LOGI("XMLParser failed to ParseScreenConfig %{public}s", name.c_str());
248 }
249 }
250 screenConfig[id] = screenSetting;
251 HGM_LOGI("HgmXMLParser ParseScreenConfig id=%{public}s", id.c_str());
252 }
253 mParsedData_->screenConfigs_[type] = screenConfig;
254 return EXEC_SUCCESS;
255 }
256
ParseSimplex(xmlNode & node,std::unordered_map<std::string,std::string> & config,const std::string valueName,const std::string keyName)257 int32_t XMLParser::ParseSimplex(xmlNode &node, std::unordered_map<std::string, std::string> &config,
258 const std::string valueName, const std::string keyName)
259 {
260 HGM_LOGD("XMLParser parsing simplex");
261 xmlNode *currNode = &node;
262 if (currNode->xmlChildrenNode == nullptr) {
263 HGM_LOGD("XMLParser stop parsing simplex, no children nodes");
264 return HGM_ERROR;
265 }
266
267 // re-parse
268 config.clear();
269 currNode = currNode->xmlChildrenNode;
270 for (; currNode; currNode = currNode->next) {
271 if (currNode->type != XML_ELEMENT_NODE) {
272 continue;
273 }
274
275 auto key = ExtractPropertyValue(keyName, *currNode);
276 auto value = ExtractPropertyValue(valueName, *currNode);
277 if (key.empty() || value.empty()) {
278 return XML_PARSE_INTERNAL_FAIL;
279 }
280 config[key] = value;
281
282 HGM_LOGI("HgmXMLParser ParseSimplex %{public}s=%{public}s %{public}s=%{public}s",
283 keyName.c_str(), key.c_str(), valueName.c_str(), config[key].c_str());
284 }
285
286 return EXEC_SUCCESS;
287 }
288
ParserDynamicSetting(xmlNode & node,PolicyConfigData::DynamicSettingMap & dynamicSettingMap)289 int32_t XMLParser::ParserDynamicSetting(xmlNode &node, PolicyConfigData::DynamicSettingMap &dynamicSettingMap)
290 {
291 HGM_LOGD("XMLParser parsing dynamicSetting");
292 xmlNode *currNode = &node;
293 if (currNode->xmlChildrenNode == nullptr) {
294 HGM_LOGD("XMLParser stop parsing dynamicSetting, no children nodes");
295 return HGM_ERROR;
296 }
297
298 // re-parse
299 dynamicSettingMap.clear();
300 currNode = currNode->xmlChildrenNode;
301 for (; currNode; currNode = currNode->next) {
302 auto dynamicSettingType = ExtractPropertyValue("name", *currNode);
303 PolicyConfigData::DynamicSetting dynamicSetting;
304 dynamicSettingMap[dynamicSettingType] = dynamicSetting;
305 for (xmlNode *thresholdNode = currNode->xmlChildrenNode; thresholdNode; thresholdNode = thresholdNode->next) {
306 if (thresholdNode->type != XML_ELEMENT_NODE) {
307 continue;
308 }
309 auto name = ExtractPropertyValue("name", *thresholdNode);
310 auto min = ExtractPropertyValue("min", *thresholdNode);
311 auto max = ExtractPropertyValue("max", *thresholdNode);
312 auto preferred_fps = ExtractPropertyValue("preferred_fps", *thresholdNode);
313 if (!IsNumber(min) || !IsNumber(max) || !IsNumber(preferred_fps)) {
314 dynamicSettingMap[dynamicSettingType].clear();
315 break;
316 }
317 PolicyConfigData::DynamicConfig dynamicConfig;
318 dynamicConfig.min = std::stoi(min);
319 dynamicConfig.max = std::stoi(max);
320 dynamicConfig.preferred_fps = std::stoi(preferred_fps);
321 dynamicSettingMap[dynamicSettingType][name] = dynamicConfig;
322
323 HGM_LOGI("HgmXMLParser ParserDynamicSetting dynamicType=%{public}s name=%{public}s min=%{public}d",
324 dynamicSettingType.c_str(), name.c_str(), dynamicSettingMap[dynamicSettingType][name].min);
325 }
326 }
327 return EXEC_SUCCESS;
328 }
329
ParseSceneList(xmlNode & node,PolicyConfigData::SceneConfigMap & sceneList)330 int32_t XMLParser::ParseSceneList(xmlNode &node, PolicyConfigData::SceneConfigMap &sceneList)
331 {
332 HGM_LOGD("XMLParser parsing sceneList");
333 xmlNode *currNode = &node;
334 if (currNode->xmlChildrenNode == nullptr) {
335 HGM_LOGD("XMLParser stop parsing sceneList, no children nodes");
336 return HGM_ERROR;
337 }
338
339 // re-parse
340 sceneList.clear();
341 currNode = currNode->xmlChildrenNode;
342 for (; currNode; currNode = currNode->next) {
343 if (currNode->type != XML_ELEMENT_NODE) {
344 continue;
345 }
346 PolicyConfigData::SceneConfig sceneConfig;
347 auto name = ExtractPropertyValue("name", *currNode);
348 sceneConfig.strategy = ExtractPropertyValue("strategy", *currNode);
349 sceneConfig.priority = ExtractPropertyValue("priority", *currNode);
350
351 sceneList[name] = sceneConfig;
352 HGM_LOGI("HgmXMLParser ParseSceneList name=%{public}s strategy=%{public}s priority=%{public}s",
353 name.c_str(), sceneList[name].strategy.c_str(), sceneList[name].priority.c_str());
354 }
355
356 return EXEC_SUCCESS;
357 }
358
ExtractPropertyValue(const std::string & propName,xmlNode & node)359 std::string XMLParser::ExtractPropertyValue(const std::string &propName, xmlNode &node)
360 {
361 HGM_LOGD("XMLParser extracting value : %{public}s", propName.c_str());
362 std::string propValue = "";
363 xmlChar *tempValue = nullptr;
364
365 if (xmlHasProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()))) {
366 tempValue = xmlGetProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()));
367 }
368
369 if (tempValue != nullptr) {
370 HGM_LOGD("XMLParser not aempty tempValue");
371 propValue = reinterpret_cast<const char*>(tempValue);
372 xmlFree(tempValue);
373 tempValue = nullptr;
374 }
375
376 return propValue;
377 }
378
IsNumber(const std::string & str)379 bool XMLParser::IsNumber(const std::string &str)
380 {
381 if (str.length() == 0) {
382 return false;
383 }
384 auto number = static_cast<uint32_t>(std::count_if(str.begin(), str.end(), [](unsigned char c) {
385 return std::isdigit(c);
386 }));
387 return number == str.length() || (str.compare(0, 1, "-") == 0 && number == str.length() - 1);
388 }
389
390 } // namespace OHOS::Rosen