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 {
21 namespace {
22 constexpr uint32_t FPS_MAX = 120; // for hgm_idle_detector: default max fps of third framework
23 constexpr uint32_t XML_STRING_MAX_LENGTH = 8;
24 const std::string S_UP_TIMEOUT_MS = "up_timeout_ms";
25 constexpr int32_t UP_TIMEOUT_MS = 3000;
26 }
27
LoadConfiguration(const char * fileDir)28 int32_t XMLParser::LoadConfiguration(const char* fileDir)
29 {
30 HGM_LOGI("XMLParser opening xml file");
31 xmlDocument_ = xmlReadFile(fileDir, nullptr, 0);
32 if (!xmlDocument_) {
33 HGM_LOGE("XMLParser xmlReadFile failed");
34 return XML_FILE_LOAD_FAIL;
35 }
36
37 if (!mParsedData_) {
38 mParsedData_ = std::make_unique<PolicyConfigData>();
39 }
40
41 return EXEC_SUCCESS;
42 }
43
Parse()44 int32_t XMLParser::Parse()
45 {
46 HGM_LOGD("XMLParser Parse");
47 if (!xmlDocument_) {
48 HGM_LOGE("XMLParser xmlDocument_ is empty, should do LoadConfiguration first");
49 return HGM_ERROR;
50 }
51 xmlNode* root = xmlDocGetRootElement(xmlDocument_);
52 if (root == nullptr) {
53 HGM_LOGE("XMLParser xmlDocGetRootElement failed");
54 return XML_GET_ROOT_FAIL;
55 }
56
57 if (!ParseInternal(*root)) {
58 return XML_PARSE_INTERNAL_FAIL;
59 }
60 int32_t upTimeoutMs = UP_TIMEOUT_MS;
61 auto& timeoutStrategyConfig = mParsedData_->timeoutStrategyConfig_;
62 if (timeoutStrategyConfig.find(S_UP_TIMEOUT_MS) != timeoutStrategyConfig.end() &&
63 IsNumber(timeoutStrategyConfig[S_UP_TIMEOUT_MS])) {
64 int32_t upTimeoutMsCfg = static_cast<int32_t>(std::stoi(timeoutStrategyConfig[S_UP_TIMEOUT_MS]));
65 upTimeoutMs = upTimeoutMsCfg == 0 ? upTimeoutMs : upTimeoutMsCfg;
66 }
67 for (auto& [_, val] : mParsedData_->strategyConfigs_) {
68 val.upTimeOut = val.upTimeOut == 0 ? upTimeoutMs : val.upTimeOut;
69 }
70 return EXEC_SUCCESS;
71 }
72
Destroy()73 void XMLParser::Destroy()
74 {
75 HGM_LOGD("XMLParser Destroying the parser");
76 if (xmlDocument_ != nullptr) {
77 xmlFreeDoc(xmlDocument_);
78 xmlDocument_ = nullptr;
79 }
80 }
81
GetHgmXmlNodeAsInt(xmlNode & node)82 HgmXmlNode XMLParser::GetHgmXmlNodeAsInt(xmlNode& node)
83 {
84 if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("Param"))) {
85 return HgmXmlNode::HGM_XML_PARAM;
86 }
87 if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("Params"))) {
88 return HgmXmlNode::HGM_XML_PARAMS;
89 }
90 HGM_LOGD("XMLParser failed to identify a xml node : %{public}s", node.name);
91 return HgmXmlNode::HGM_XML_UNDEFINED;
92 }
93
ParseInternal(xmlNode & node)94 bool XMLParser::ParseInternal(xmlNode& node)
95 {
96 HGM_LOGD("XMLParser parsing an internal node");
97 xmlNode* currNode = &node;
98 if (currNode->xmlChildrenNode == nullptr) {
99 HGM_LOGD("XMLParser stop parsing internal, no children nodes");
100 return false;
101 }
102 currNode = currNode->xmlChildrenNode;
103 int32_t parseSuccess = EXEC_SUCCESS;
104
105 for (; currNode; currNode = currNode->next) {
106 if (currNode->type != XML_ELEMENT_NODE) {
107 continue;
108 }
109 if (parseSuccess != EXEC_SUCCESS) {
110 return false;
111 }
112 auto xmlParamType = GetHgmXmlNodeAsInt(*currNode);
113 if (xmlParamType == HgmXmlNode::HGM_XML_PARAM) {
114 parseSuccess = ParseParam(*currNode);
115 } else if (xmlParamType == HgmXmlNode::HGM_XML_PARAMS) {
116 parseSuccess = ParseParams(*currNode);
117 }
118 }
119 return true;
120 }
121
ParseParam(xmlNode & node)122 int32_t XMLParser::ParseParam(xmlNode& node)
123 {
124 HGM_LOGI("XMLParser parsing a parameter");
125 if (!mParsedData_) {
126 HGM_LOGE("XMLParser mParsedData_ is not initialized");
127 return HGM_ERROR;
128 }
129
130 std::string paraName = ExtractPropertyValue("name", node);
131 if (paraName == "default_refreshrate_mode") {
132 HGM_LOGD("XMLParser parsing default_refreshrate_mode");
133 std::string mode = ExtractPropertyValue("value", node);
134 mParsedData_->defaultRefreshRateMode_ = mode;
135
136 HGM_LOGI("HgmXMLParser ParseParam default_refreshrate_mode %{public}s",
137 mParsedData_->defaultRefreshRateMode_.c_str());
138 }
139
140 return EXEC_SUCCESS;
141 }
142
ParseSubSequentParams(xmlNode & node,std::string & paraName)143 int32_t XMLParser::ParseSubSequentParams(xmlNode& node, std::string& paraName)
144 {
145 int32_t setResult = EXEC_SUCCESS;
146
147 if (paraName == "additional_touch_rate_config") {
148 ParseAppBufferList(node);
149 } else if (paraName == "refreshRate_strategy_config") {
150 setResult = ParseStrategyConfig(node);
151 } else if (paraName == "refreshRate_virtual_display_config") {
152 if (ExtractPropertyValue("switch", node) == "1") {
153 setResult = ParseSimplex(node, mParsedData_->virtualDisplayConfigs_, "strategy");
154 mParsedData_->virtualDisplaySwitch_ = true;
155 } else {
156 mParsedData_->virtualDisplayConfigs_.clear();
157 mParsedData_->virtualDisplaySwitch_ = false;
158 }
159 } else if (paraName == "safe_vote") {
160 // "1": enable
161 mParsedData_->safeVoteEnabled = ExtractPropertyValue("switch", node) == "1";
162 } else if (paraName == "screen_strategy_config") {
163 setResult = ParseSimplex(node, mParsedData_->screenStrategyConfigs_, "type");
164 } else if (paraName == "screen_config") {
165 setResult = ParseScreenConfig(node);
166 } else if (paraName == "rs_video_frame_rate_vote_config") {
167 setResult = ParseVideoFrameVoteConfig(node);
168 } else if (paraName == "source_tuning_for_yuv420") {
169 setResult = ParseSimplex(node, mParsedData_->sourceTuningConfig_);
170 } else if (paraName == "rs_solid_color_layer_config") {
171 setResult = ParseSimplex(node, mParsedData_->solidLayerConfig_);
172 } else if (paraName == "timeout_strategy_config") {
173 setResult = ParseSimplex(node, mParsedData_->timeoutStrategyConfig_);
174 } else if (paraName == "video_call_layer_config") {
175 setResult = ParseSimplex(node, mParsedData_->videoCallLayerConfig_);
176 } else if (paraName == "vrate_control_config") {
177 setResult = ParseSimplex(node, mParsedData_->vRateControlList_);
178 } else {
179 setResult = EXEC_SUCCESS;
180 }
181
182 return setResult;
183 }
184
ParseParams(xmlNode & node)185 int32_t XMLParser::ParseParams(xmlNode& node)
186 {
187 std::string paraName = ExtractPropertyValue("name", node);
188 if (paraName.empty()) {
189 return XML_PARSE_INTERNAL_FAIL;
190 }
191 if (!mParsedData_) {
192 HGM_LOGE("XMLParser mParsedData_ is not initialized");
193 return HGM_ERROR;
194 }
195
196 int32_t setResult = EXEC_SUCCESS;
197 if (paraName == "refresh_rate_4settings") {
198 setResult = ParseRefreshRate4Settings(node);
199 } else {
200 setResult = ParseSubSequentParams(node, paraName);
201 }
202
203 if (setResult != EXEC_SUCCESS) {
204 HGM_LOGI("XMLParser failed to ParseParams %{public}s", paraName.c_str());
205 }
206 return EXEC_SUCCESS;
207 }
208
ParseRefreshRate4Settings(xmlNode & node)209 int32_t XMLParser::ParseRefreshRate4Settings(xmlNode& node)
210 {
211 int32_t setResult = EXEC_SUCCESS;
212 std::string deviceMode = ExtractPropertyValue("type", node);
213 std::unordered_map<std::string, std::string> refreshRateForSettingsTemp;
214 std::vector<std::pair<int32_t, int32_t>> refreshRateForSettings;
215 setResult = ParseSimplex(node, refreshRateForSettingsTemp);
216 if (setResult != EXEC_SUCCESS) {
217 mParsedData_->xmlCompatibleMode_ = true;
218 setResult = ParseSimplex(node, refreshRateForSettingsTemp, "id");
219 }
220 for (auto& [name, id]: refreshRateForSettingsTemp) {
221 if (IsNumber(name) && IsNumber(id)) {
222 refreshRateForSettings.emplace_back(
223 std::pair<int32_t, int32_t>(std::stoi(name), std::stoi(id)));
224 }
225 }
226 std::sort(refreshRateForSettings.begin(), refreshRateForSettings.end(),
227 [=] (auto rateId0, auto rateId1) { return rateId0.first < rateId1.first; });
228
229 mParsedData_->refreshRateForSettingsMap_[deviceMode] = refreshRateForSettings;
230 if (deviceMode == "") {
231 mParsedData_->refreshRateForSettings_ = refreshRateForSettings;
232 }
233 return setResult;
234 }
235
ParseVideoFrameVoteConfig(xmlNode & node)236 int32_t XMLParser::ParseVideoFrameVoteConfig(xmlNode& node)
237 {
238 mParsedData_->videoFrameRateVoteSwitch_ = ExtractPropertyValue("switch", node) == "1";
239 return ParseSimplex(node, mParsedData_->videoFrameRateList_);
240 }
241
ParseStrategyConfig(xmlNode & node)242 int32_t XMLParser::ParseStrategyConfig(xmlNode& node)
243 {
244 HGM_LOGD("XMLParser parsing strategyConfig");
245 xmlNode* currNode = &node;
246 if (currNode->xmlChildrenNode == nullptr) {
247 HGM_LOGD("XMLParser stop parsing strategyConfig, no children nodes");
248 return HGM_ERROR;
249 }
250
251 // re-parse
252 mParsedData_->strategyConfigs_.clear();
253 currNode = currNode->xmlChildrenNode;
254 for (; currNode; currNode = currNode->next) {
255 if (currNode->type != XML_ELEMENT_NODE) {
256 continue;
257 }
258 auto name = ExtractPropertyValue("name", *currNode);
259 PolicyConfigData::StrategyConfig strategy;
260 if (!BuildStrategyConfig(*currNode, strategy)) {
261 return HGM_ERROR;
262 }
263 ParseBufferStrategyList(*currNode, strategy);
264 mParsedData_->strategyConfigs_[name] = strategy;
265 HGM_LOGI("HgmXMLParser ParseStrategyConfig name=%{public}s min=%{public}d drawMin=%{public}d",
266 name.c_str(), mParsedData_->strategyConfigs_[name].min, mParsedData_->strategyConfigs_[name].drawMin);
267 }
268
269 return EXEC_SUCCESS;
270 }
271
ParseAppBufferList(xmlNode & node)272 void XMLParser::ParseAppBufferList(xmlNode& node)
273 {
274 HGM_LOGD("XMLParser parsing ParseAppBufferList");
275 xmlNode* currNode = &node;
276 if (currNode->xmlChildrenNode == nullptr) {
277 HGM_LOGD("XMLParser stop parsing ParseAppBufferList, no children nodes");
278 return;
279 }
280
281 mParsedData_->appBufferList_.clear();
282 currNode = currNode->xmlChildrenNode;
283 for (; currNode; currNode = currNode->next) {
284 if (currNode->type != XML_ELEMENT_NODE) {
285 continue;
286 }
287 auto name = ExtractPropertyValue("name", *currNode);
288 mParsedData_->appBufferList_.push_back(name);
289 }
290 }
291
ParseBufferStrategyList(xmlNode & node,PolicyConfigData::StrategyConfig & strategy)292 void XMLParser::ParseBufferStrategyList(xmlNode& node, PolicyConfigData::StrategyConfig& strategy)
293 {
294 if (mParsedData_->appBufferList_.empty()) {
295 return;
296 }
297 for (auto& name : mParsedData_->appBufferList_) {
298 auto fpsStr = ExtractPropertyValue(name, node);
299 if (fpsStr == "") {
300 strategy.bufferFpsMap[name] = FPS_MAX;
301 } else if (IsNumber(fpsStr)) {
302 auto fpsNum = std::stoi(fpsStr);
303 if (fpsNum >= 0) {
304 strategy.bufferFpsMap[name] = fpsNum;
305 }
306 }
307 }
308 }
309
ParseScreenConfig(xmlNode & node)310 int32_t XMLParser::ParseScreenConfig(xmlNode& node)
311 {
312 HGM_LOGD("XMLParser parsing screenConfig");
313 xmlNode* currNode = &node;
314 if (currNode->xmlChildrenNode == nullptr) {
315 HGM_LOGD("XMLParser stop parsing screenConfig, no children nodes");
316 return HGM_ERROR;
317 }
318
319 auto type = ExtractPropertyValue("type", *currNode);
320 PolicyConfigData::ScreenConfig screenConfig;
321 currNode = currNode->xmlChildrenNode;
322 for (; currNode; currNode = currNode->next) {
323 if (currNode->type != XML_ELEMENT_NODE) {
324 continue;
325 }
326 auto name = ExtractPropertyValue("name", *currNode);
327 if (name == "supported_mode") {
328 PolicyConfigData::SupportedModeConfig supportedModeConfig;
329 if (ParseSupportedModeConfig(*currNode, supportedModeConfig) != EXEC_SUCCESS) {
330 HGM_LOGI("XMLParser failed to ParseScreenConfig %{public}s", name.c_str());
331 }
332 mParsedData_->supportedModeConfigs_[type] = supportedModeConfig;
333 continue;
334 }
335 PolicyConfigData::ScreenSetting screenSetting;
336 auto id = ExtractPropertyValue("id", *currNode);
337 screenSetting.strategy = ExtractPropertyValue("strategy", *currNode);
338 for (xmlNode* thresholdNode = currNode->xmlChildrenNode; thresholdNode; thresholdNode = thresholdNode->next) {
339 ParseSubScreenConfig(*thresholdNode, screenSetting);
340 }
341 screenConfig[id] = screenSetting;
342 HGM_LOGI("HgmXMLParser ParseScreenConfig id=%{public}s", id.c_str());
343 }
344 for (const auto& screenExtStrategy : HGM_CONFIG_SCREENEXT_STRATEGY_MAP) {
345 if (size_t pos = type.find(screenExtStrategy.first); pos != std::string::npos) {
346 auto defaultScreenConfig = mParsedData_->screenConfigs_.find(type.substr(0, pos));
347 if (defaultScreenConfig != mParsedData_->screenConfigs_.end()) {
348 ReplenishMissingScreenConfig(defaultScreenConfig->second, screenConfig);
349 } else {
350 HGM_LOGE("XMLParser failed to ReplenishMissingScreenConfig %{public}s", type.c_str());
351 return EXEC_SUCCESS;
352 }
353 }
354 }
355 mParsedData_->screenConfigs_[type] = screenConfig;
356 return EXEC_SUCCESS;
357 }
358
ParseSubScreenConfig(xmlNode & node,PolicyConfigData::ScreenSetting & screenSetting)359 int32_t XMLParser::ParseSubScreenConfig(xmlNode& node, PolicyConfigData::ScreenSetting& screenSetting)
360 {
361 xmlNode* thresholdNode = &node;
362 if (thresholdNode->type != XML_ELEMENT_NODE) {
363 return HGM_ERROR;
364 }
365 auto name = ExtractPropertyValue("name", *thresholdNode);
366 int32_t setResult = EXEC_SUCCESS;
367 if (name == "LTPO_config") {
368 setResult = ParseSimplex(*thresholdNode, screenSetting.ltpoConfig);
369 } else if (name == "property_animation_dynamic_settings") {
370 setResult = ParseDynamicSetting(*thresholdNode, screenSetting.animationDynamicSettings);
371 } else if (name == "ace_scene_dynamic_settings") {
372 setResult = ParseDynamicSetting(*thresholdNode, screenSetting.aceSceneDynamicSettings);
373 } else if (name == "small_size_property_animation_dynamic_settings") {
374 setResult = ParseSmallSizeDynamicSetting(*thresholdNode, screenSetting);
375 } else if (name == "scene_list") {
376 setResult = ParseSceneList(*thresholdNode, screenSetting.sceneList);
377 } else if (name == "game_scene_list") {
378 setResult = ParseSimplex(*thresholdNode, screenSetting.gameSceneList);
379 } else if (name == "anco_scene_list") {
380 setResult = ParseSceneList(*thresholdNode, screenSetting.ancoSceneList);
381 } else if (name == "app_list") {
382 ParseMultiAppStrategy(*thresholdNode, screenSetting);
383 } else if (name == "app_types") {
384 setResult = ParseAppTypes(*thresholdNode, screenSetting.appTypes);
385 } else if (name == "rs_animation_power_config") {
386 setResult = ParseSimplex(*thresholdNode, screenSetting.animationPowerConfig);
387 } else if (name == "ui_power_config") {
388 setResult = ParseSimplex(*thresholdNode, screenSetting.uiPowerConfig);
389 } else if (name == "component_power_config") {
390 setResult = ParsePowerStrategy(*thresholdNode, screenSetting.componentPowerConfig);
391 } else if (name == "app_page_url_config") {
392 setResult = ParsePageUrlStrategy(*thresholdNode, screenSetting.pageUrlConfig);
393 } else if (name == "performance_config") {
394 setResult = ParsePerformanceConfig(*thresholdNode, screenSetting.performanceConfig);
395 } else {
396 setResult = EXEC_SUCCESS;
397 }
398
399 if (setResult != EXEC_SUCCESS) {
400 HGM_LOGI("XMLParser failed to ParseScreenConfig %{public}s", name.c_str());
401 }
402 return setResult;
403 }
404
ParseSimplex(xmlNode & node,std::unordered_map<std::string,std::string> & config,const std::string & valueName,const std::string & keyName,const bool canBeEmpty)405 int32_t XMLParser::ParseSimplex(xmlNode& node, std::unordered_map<std::string, std::string>& config,
406 const std::string& valueName, const std::string& keyName,
407 const bool canBeEmpty)
408 {
409 HGM_LOGD("XMLParser parsing simplex");
410 xmlNode* currNode = &node;
411 if (currNode->xmlChildrenNode == nullptr) {
412 HGM_LOGD("XMLParser stop parsing simplex, no children nodes");
413 return HGM_ERROR;
414 }
415
416 // re-parse
417 config.clear();
418 currNode = currNode->xmlChildrenNode;
419 for (; currNode; currNode = currNode->next) {
420 if (currNode->type != XML_ELEMENT_NODE) {
421 continue;
422 }
423
424 auto key = ExtractPropertyValue(keyName, *currNode);
425 auto value = ExtractPropertyValue(valueName, *currNode);
426 if (key.empty()) {
427 return XML_PARSE_INTERNAL_FAIL;
428 }
429
430 if (value.empty()) {
431 if (canBeEmpty) {
432 continue;
433 }
434 return XML_PARSE_INTERNAL_FAIL;
435 }
436
437 config[key] = value;
438
439 HGM_LOGI("HgmXMLParser ParseSimplex %{public}s=%{public}s %{public}s=%{public}s",
440 keyName.c_str(), key.c_str(), valueName.c_str(), config[key].c_str());
441 }
442
443 return EXEC_SUCCESS;
444 }
445
ParsePowerStrategy(xmlNode & node,std::unordered_map<std::string,int32_t> & powerConfig)446 int32_t XMLParser::ParsePowerStrategy(xmlNode& node, std::unordered_map<std::string, int32_t>& powerConfig)
447 {
448 std::unordered_map<std::string, std::string> configs;
449 auto result = ParseSimplex(node, configs);
450 powerConfig.clear();
451 if (result != EXEC_SUCCESS) {
452 HGM_LOGI("XMLParser failed to powerConfig component_power_config");
453 return result;
454 }
455 for (const auto& item: configs) {
456 if (!IsNumber(item.second)) {
457 continue;
458 }
459 powerConfig[item.first] = std::stoi(item.second.c_str());
460 }
461 return EXEC_SUCCESS;
462 }
463
ParseSmallSizeDynamicSetting(xmlNode & node,PolicyConfigData::ScreenSetting & screenSetting)464 int32_t XMLParser::ParseSmallSizeDynamicSetting(xmlNode& node, PolicyConfigData::ScreenSetting& screenSetting)
465 {
466 auto area = ExtractPropertyValue("area", node);
467 auto length = ExtractPropertyValue("length", node);
468 if (!IsNumber(area) || !IsNumber(length)) {
469 return HGM_ERROR;
470 }
471 screenSetting.smallSizeArea = std::stoi(area);
472 screenSetting.smallSizeLength = std::stoi(length);
473 return ParseDynamicSetting(node, screenSetting.smallSizeAnimationDynamicSettings);
474 }
475
ParseDynamicSetting(xmlNode & node,PolicyConfigData::DynamicSettingMap & dynamicSettingMap)476 int32_t XMLParser::ParseDynamicSetting(xmlNode& node, PolicyConfigData::DynamicSettingMap& dynamicSettingMap)
477 {
478 HGM_LOGD("XMLParser parsing dynamicSetting");
479 xmlNode* currNode = &node;
480 if (currNode->xmlChildrenNode == nullptr) {
481 HGM_LOGD("XMLParser stop parsing dynamicSetting, no children nodes");
482 return HGM_ERROR;
483 }
484
485 // re-parse
486 dynamicSettingMap.clear();
487 currNode = currNode->xmlChildrenNode;
488 for (; currNode; currNode = currNode->next) {
489 auto dynamicSettingType = ExtractPropertyValue("name", *currNode);
490 PolicyConfigData::DynamicSetting dynamicSetting;
491 dynamicSettingMap[dynamicSettingType] = dynamicSetting;
492 for (xmlNode* thresholdNode = currNode->xmlChildrenNode; thresholdNode; thresholdNode = thresholdNode->next) {
493 if (thresholdNode->type != XML_ELEMENT_NODE) {
494 continue;
495 }
496 auto name = ExtractPropertyValue("name", *thresholdNode);
497 auto min = ExtractPropertyValue("min", *thresholdNode);
498 auto max = ExtractPropertyValue("max", *thresholdNode);
499 auto preferredFps = ExtractPropertyValue("preferred_fps", *thresholdNode);
500 if (!IsNumber(min) || !IsNumber(max) || !IsNumber(preferredFps)) {
501 dynamicSettingMap[dynamicSettingType].clear();
502 break;
503 }
504 PolicyConfigData::DynamicConfig dynamicConfig;
505 dynamicConfig.min = std::stoi(min);
506 dynamicConfig.max = std::stoi(max);
507 dynamicConfig.preferredFps = std::stoi(preferredFps);
508 dynamicSettingMap[dynamicSettingType][name] = dynamicConfig;
509
510 HGM_LOGI("HgmXMLParser ParseDynamicSetting dynamicType=%{public}s name=%{public}s min=%{public}d",
511 dynamicSettingType.c_str(), name.c_str(), dynamicSettingMap[dynamicSettingType][name].min);
512 }
513 }
514 return EXEC_SUCCESS;
515 }
516
ParseSceneList(xmlNode & node,PolicyConfigData::SceneConfigMap & sceneList)517 int32_t XMLParser::ParseSceneList(xmlNode& node, PolicyConfigData::SceneConfigMap& sceneList)
518 {
519 HGM_LOGD("XMLParser parsing sceneList");
520 xmlNode* currNode = &node;
521 if (currNode->xmlChildrenNode == nullptr) {
522 HGM_LOGD("XMLParser stop parsing sceneList, no children nodes");
523 return HGM_ERROR;
524 }
525
526 // re-parse
527 sceneList.clear();
528 currNode = currNode->xmlChildrenNode;
529 for (; currNode; currNode = currNode->next) {
530 if (currNode->type != XML_ELEMENT_NODE) {
531 continue;
532 }
533 PolicyConfigData::SceneConfig sceneConfig;
534 auto name = ExtractPropertyValue("name", *currNode);
535 sceneConfig.strategy = ExtractPropertyValue("strategy", *currNode);
536 sceneConfig.priority = ExtractPropertyValue("priority", *currNode);
537 sceneConfig.doNotAutoClear = ExtractPropertyValue("doNotAutoClear", *currNode) == "1";
538 sceneConfig.disableSafeVote = ExtractPropertyValue("disableSafeVote", *currNode) == "1";
539 sceneList[name] = sceneConfig;
540 HGM_LOGI("HgmXMLParser ParseSceneList name=%{public}s strategy=%{public}s priority=%{public}s \
541 doNotAutoClear=%{public}s disableSafeVote=%{public}s", name.c_str(),
542 sceneList[name].strategy.c_str(), sceneList[name].priority.c_str(),
543 sceneList[name].doNotAutoClear ? "true" : "false",
544 sceneList[name].disableSafeVote ? "true" : "false");
545 }
546
547 return EXEC_SUCCESS;
548 }
549
ParseSupportedModeConfig(xmlNode & node,PolicyConfigData::SupportedModeConfig & supportedModeConfig)550 int32_t XMLParser::ParseSupportedModeConfig(xmlNode& node, PolicyConfigData::SupportedModeConfig& supportedModeConfig)
551 {
552 HGM_LOGD("XMLParser parsing supportedModeConfig");
553 xmlNode* currNode = &node;
554 if (currNode->xmlChildrenNode == nullptr) {
555 HGM_LOGD("XMLParser stop parsing supportedModeConfig, no children nodes");
556 return HGM_ERROR;
557 }
558
559 // re-parse
560 supportedModeConfig.clear();
561 currNode = currNode->xmlChildrenNode;
562 for (; currNode; currNode = currNode->next) {
563 if (currNode->type != XML_ELEMENT_NODE) {
564 continue;
565 }
566 std::vector<uint32_t> supportedModeVec;
567 auto name = ExtractPropertyValue("name", *currNode);
568 auto value = ExtractPropertyValue("value", *currNode);
569 supportedModeVec = StringToVector(value);
570
571 supportedModeConfig[name] = supportedModeVec;
572 HGM_LOGI("HgmXMLParser ParseSupportedModeConfig name=%{public}s value=%{public}s",
573 name.c_str(), value.c_str());
574 }
575 return EXEC_SUCCESS;
576 }
577
ParseMultiAppStrategy(xmlNode & node,PolicyConfigData::ScreenSetting & screenSetting)578 int32_t XMLParser::ParseMultiAppStrategy(xmlNode& node, PolicyConfigData::ScreenSetting& screenSetting)
579 {
580 auto multiAppStrategy = ExtractPropertyValue("multi_app_strategy", node);
581 if (multiAppStrategy == "focus") {
582 screenSetting.multiAppStrategyType = MultiAppStrategyType::FOLLOW_FOCUS;
583 } else if (multiAppStrategy.find("strategy_") != std::string::npos) {
584 screenSetting.multiAppStrategyType = MultiAppStrategyType::USE_STRATEGY_NUM;
585 screenSetting.multiAppStrategyName = multiAppStrategy.substr(
586 std::string("strategy_").size(), multiAppStrategy.size());
587 } else {
588 screenSetting.multiAppStrategyType = MultiAppStrategyType::USE_MAX;
589 }
590 ParseSimplex(node, screenSetting.gameAppNodeList, "nodeName", "name", true);
591 return ParseSimplex(node, screenSetting.appList, "strategy");
592 }
593
594
ParseAppTypes(xmlNode & node,std::unordered_map<int32_t,std::string> & appTypes)595 int32_t XMLParser::ParseAppTypes(xmlNode& node, std::unordered_map<int32_t, std::string>& appTypes)
596 {
597 HGM_LOGD("XMLParser parsing appTypes");
598 xmlNode* currNode = &node;
599 if (currNode->xmlChildrenNode == nullptr) {
600 HGM_LOGD("XMLParser stop parsing appTypes, no children nodes");
601 return HGM_ERROR;
602 }
603
604 // re-parse
605 appTypes.clear();
606 currNode = currNode->xmlChildrenNode;
607 for (; currNode; currNode = currNode->next) {
608 if (currNode->type != XML_ELEMENT_NODE) {
609 continue;
610 }
611 auto name = ExtractPropertyValue("name", *currNode);
612 if (!IsNumber(name)) {
613 continue;
614 }
615 auto strategy = ExtractPropertyValue("strategy", *currNode);
616 appTypes[std::stoi(name)] = strategy;
617 HGM_LOGI("HgmXMLParser ParseAppTypes name=%{public}s strategy=%{public}s", name.c_str(), strategy.c_str());
618 }
619
620 return EXEC_SUCCESS;
621 }
622
ReplenishMissingScreenAppGameConfig(PolicyConfigData::ScreenSetting & screenSetting,const PolicyConfigData::ScreenSetting & screenSettingDefalut)623 void XMLParser::ReplenishMissingScreenAppGameConfig(PolicyConfigData::ScreenSetting& screenSetting,
624 const PolicyConfigData::ScreenSetting& screenSettingDefalut)
625 {
626 if (screenSetting.appList.empty()) {
627 screenSetting.appList = screenSettingDefalut.appList;
628 screenSetting.multiAppStrategyType = screenSettingDefalut.multiAppStrategyType;
629 screenSetting.multiAppStrategyName = screenSettingDefalut.multiAppStrategyName;
630 }
631 if (screenSetting.appTypes.empty()) {
632 screenSetting.appTypes = screenSettingDefalut.appTypes;
633 }
634 if (screenSetting.gameSceneList.empty()) {
635 screenSetting.gameSceneList = screenSettingDefalut.gameSceneList;
636 }
637 if (screenSetting.gameAppNodeList.empty()) {
638 screenSetting.gameAppNodeList = screenSettingDefalut.gameAppNodeList;
639 }
640 }
641
ReplenishMissingScreenConfig(const PolicyConfigData::ScreenConfig & screenConfigDefault,PolicyConfigData::ScreenConfig & screenConfig)642 int32_t XMLParser::ReplenishMissingScreenConfig(const PolicyConfigData::ScreenConfig& screenConfigDefault,
643 PolicyConfigData::ScreenConfig& screenConfig)
644 {
645 HGM_LOGD("HgmXMLParser ReplenishMissingScreenConfig");
646 for (const auto& [id, screenSettingDefalut] : screenConfigDefault) {
647 const auto& screenSetting = screenConfig.find(id);
648 if (screenSetting == screenConfig.end()) {
649 screenConfig[id] = screenSettingDefalut;
650 continue;
651 }
652 if (screenSetting->second.ltpoConfig.empty()) {
653 screenSetting->second.ltpoConfig = screenSettingDefalut.ltpoConfig;
654 }
655 if (screenSetting->second.sceneList.empty()) {
656 screenSetting->second.sceneList = screenSettingDefalut.sceneList;
657 }
658 if (screenSetting->second.animationDynamicSettings.empty()) {
659 screenSetting->second.animationDynamicSettings = screenSettingDefalut.animationDynamicSettings;
660 }
661 if (screenSetting->second.aceSceneDynamicSettings.empty()) {
662 screenSetting->second.aceSceneDynamicSettings = screenSettingDefalut.aceSceneDynamicSettings;
663 }
664 if (screenSetting->second.smallSizeAnimationDynamicSettings.empty()) {
665 screenSetting->second.smallSizeArea = screenSettingDefalut.smallSizeArea;
666 screenSetting->second.smallSizeLength = screenSettingDefalut.smallSizeLength;
667 screenSetting->second.smallSizeAnimationDynamicSettings =
668 screenSettingDefalut.smallSizeAnimationDynamicSettings;
669 }
670 if (screenSetting->second.animationPowerConfig.empty()) {
671 screenSetting->second.animationPowerConfig = screenSettingDefalut.animationPowerConfig;
672 }
673 if (screenSetting->second.uiPowerConfig.empty()) {
674 screenSetting->second.uiPowerConfig = screenSettingDefalut.uiPowerConfig;
675 }
676 if (screenSetting->second.ancoSceneList.empty()) {
677 screenSetting->second.ancoSceneList = screenSettingDefalut.ancoSceneList;
678 }
679 if (screenSetting->second.componentPowerConfig.empty()) {
680 screenSetting->second.componentPowerConfig = screenSettingDefalut.componentPowerConfig;
681 }
682 if (screenSetting->second.pageUrlConfig.empty()) {
683 screenSetting->second.pageUrlConfig = screenSettingDefalut.pageUrlConfig;
684 }
685 if (screenSetting->second.performanceConfig.empty()) {
686 screenSetting->second.performanceConfig = screenSettingDefalut.performanceConfig;
687 }
688 ReplenishMissingScreenAppGameConfig(screenSetting->second, screenSettingDefalut);
689 }
690 return EXEC_SUCCESS;
691 }
692
ParsePerformanceConfig(xmlNode & node,std::unordered_map<std::string,std::string> & performanceConfig)693 int32_t XMLParser::ParsePerformanceConfig(
694 xmlNode& node, std::unordered_map<std::string, std::string>& performanceConfig)
695 {
696 HGM_LOGD("XMLParser parsing performanceConfig");
697 xmlNode* currNode = &node;
698 if (currNode->xmlChildrenNode == nullptr) {
699 HGM_LOGD("XMLParser stop parsing performanceConfig, no children nodes");
700 return HGM_ERROR;
701 }
702
703 // re-parse
704 performanceConfig.clear();
705 currNode = currNode->xmlChildrenNode;
706 for (; currNode; currNode = currNode->next) {
707 if (currNode->type != XML_ELEMENT_NODE) {
708 continue;
709 }
710 auto name = ExtractPropertyValue("name", *currNode);
711 auto value = ExtractPropertyValue("value", *currNode);
712 HGM_LOGI("HgmXMLParser performanceConfig name=%{public}s strategy=%{public}s", name.c_str(), value.c_str());
713 performanceConfig[std::move(name)] = std::move(value);
714 }
715
716 return EXEC_SUCCESS;
717 }
718
ExtractPropertyValue(const std::string & propName,xmlNode & node)719 std::string XMLParser::ExtractPropertyValue(const std::string& propName, xmlNode& node)
720 {
721 HGM_LOGD("XMLParser extracting value : %{public}s", propName.c_str());
722 std::string propValue = "";
723 xmlChar* tempValue = nullptr;
724
725 if (xmlHasProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()))) {
726 tempValue = xmlGetProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()));
727 }
728
729 if (tempValue != nullptr) {
730 HGM_LOGD("XMLParser not aempty tempValue");
731 propValue = reinterpret_cast<const char*>(tempValue);
732 xmlFree(tempValue);
733 tempValue = nullptr;
734 }
735
736 return propValue;
737 }
738
IsNumber(const std::string & str)739 bool XMLParser::IsNumber(const std::string& str)
740 {
741 if (str.length() == 0 || str.length() > XML_STRING_MAX_LENGTH) {
742 return false;
743 }
744 auto number = static_cast<uint32_t>(std::count_if(str.begin(), str.end(), [](unsigned char c) {
745 return std::isdigit(c);
746 }));
747 return number == str.length() || (str.compare(0, 1, "-") == 0 && number == str.length() - 1);
748 }
749
StringToVector(const std::string & str,const std::string & pattern)750 std::vector<uint32_t> XMLParser::StringToVector(const std::string& str, const std::string& pattern)
751 {
752 std::vector<std::string> vstr;
753 std::string::size_type wordBegin = 0;
754 std::string::size_type wordEnd = str.find(pattern);
755 while (wordEnd != std::string::npos) {
756 vstr.push_back(str.substr(wordBegin, wordEnd - wordBegin));
757 wordBegin = wordEnd + pattern.size();
758 wordEnd = str.find(pattern, wordBegin);
759 }
760 if (wordBegin != str.length()) {
761 vstr.push_back(str.substr(wordBegin));
762 }
763
764 std::vector<uint32_t> vec;
765 for (const auto& s : vstr) {
766 if (!IsNumber(s)) {
767 continue;
768 }
769 vec.emplace_back(std::stoi(s));
770 }
771 return vec;
772 }
773
ParsePageUrlStrategy(xmlNode & node,std::unordered_map<std::string,PolicyConfigData::PageUrlConfig> & pageUrlConfigMap)774 int32_t XMLParser::ParsePageUrlStrategy(xmlNode& node,
775 std::unordered_map<std::string, PolicyConfigData::PageUrlConfig>& pageUrlConfigMap)
776 {
777 pageUrlConfigMap.clear();
778 HGM_LOGD("XMLParser parsing PageUrlConfig");
779 xmlNode* currNode = &node;
780 if (currNode->xmlChildrenNode == nullptr) {
781 HGM_LOGE("XMLParser stop parsing PageUrlConfig, no children nodes");
782 return HGM_ERROR;
783 }
784
785 currNode = currNode->xmlChildrenNode;
786 for (; currNode; currNode = currNode->next) {
787 if (currNode->type != XML_ELEMENT_NODE) {
788 continue;
789 }
790 if (currNode->xmlChildrenNode == nullptr) {
791 HGM_LOGE("XMLParser stop parsing Package, no children nodes");
792 return HGM_ERROR;
793 }
794
795 xmlNode* childNode = currNode->xmlChildrenNode;
796 PolicyConfigData::PageUrlConfig pageUrlConfig;
797 for (; childNode; childNode = childNode->next) {
798 if (childNode->type != XML_ELEMENT_NODE) {
799 continue;
800 }
801 auto name = ExtractPropertyValue("name", *childNode);
802 auto strategy = ExtractPropertyValue("strategy", *childNode);
803 mParsedData_->pageNameList_.push_back(name);
804 pageUrlConfig[name] = strategy;
805 }
806 auto packageName = ExtractPropertyValue("name", *currNode);
807 pageUrlConfigMap[packageName] = pageUrlConfig;
808 }
809 return EXEC_SUCCESS;
810 }
811
BuildStrategyConfig(xmlNode & currNode,PolicyConfigData::StrategyConfig & strategy)812 bool XMLParser::BuildStrategyConfig(xmlNode &currNode, PolicyConfigData::StrategyConfig &strategy)
813 {
814 auto min = ExtractPropertyValue("min", currNode);
815 auto max = ExtractPropertyValue("max", currNode);
816 auto dynamicMode = ExtractPropertyValue("dynamicMode", currNode);
817 auto pointerMode = ExtractPropertyValue("pointerMode", currNode);
818 auto idleFps = ExtractPropertyValue("idleFps", currNode);
819 auto isFactor = ExtractPropertyValue("isFactor", currNode) == "1"; // 1:true, other:false
820 auto drawMin = ExtractPropertyValue("drawMin", currNode);
821 auto drawMax = ExtractPropertyValue("drawMax", currNode);
822 auto down = ExtractPropertyValue("down", currNode);
823 auto supportAS = ExtractPropertyValue("supportAS", currNode);
824 auto upTimeOut = ExtractPropertyValue("upTimeOut", currNode);
825 if (!IsNumber(min) || !IsNumber(max) || !IsNumber(dynamicMode)) {
826 return false;
827 }
828 strategy.min = std::stoi(min);
829 strategy.max = std::stoi(max);
830 strategy.dynamicMode = static_cast<DynamicModeType>(std::stoi(dynamicMode));
831 strategy.pointerMode = IsNumber(pointerMode) ? static_cast<PointerModeType>(std::stoi(pointerMode)) :
832 PointerModeType::POINTER_DISENABLED;
833 strategy.idleFps = IsNumber(idleFps) ? std::clamp(std::stoi(idleFps), strategy.min, strategy.max) :
834 std::max(strategy.min, static_cast<int32_t>(OLED_60_HZ));
835 strategy.isFactor = isFactor;
836 strategy.drawMin = IsNumber(drawMin) ? std::stoi(drawMin) : 0;
837 strategy.drawMax = IsNumber(drawMax) ? std::stoi(drawMax) : 0;
838 strategy.down = IsNumber(down) ? std::stoi(down) : strategy.max;
839 strategy.supportAS = IsNumber(supportAS) ? std::stoi(supportAS) : 0;
840 strategy.upTimeOut = IsNumber(upTimeOut) ? std::stoi(upTimeOut) : 0;
841 return true;
842 }
843 } // namespace OHOS::Rosen