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