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