• 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 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