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 namespace OHOS::Rosen {
LoadConfiguration()19 int32_t XMLParser::LoadConfiguration()
20 {
21 if (!xmlDocument_) {
22 HGM_LOGI("XMLParser opening xml file");
23 xmlDocument_ = xmlReadFile(CONFIG_FILE, nullptr, 0);
24 }
25
26 if (!xmlDocument_) {
27 HGM_LOGE("XMLParser xmlReadFile failed");
28 return XML_FILE_LOAD_FAIL;
29 }
30
31 if (!mParsedData_) {
32 HGM_LOGI("XMLParser initializing parsed data");
33 mParsedData_ = std::make_unique<ParsedConfigData>();
34 }
35 return EXEC_SUCCESS;
36 }
37
Parse()38 int32_t XMLParser::Parse()
39 {
40 HGM_LOGD("XMLParser Parse");
41 if (!xmlDocument_) {
42 HGM_LOGE("XMLParser xmlDocument_ is empty, should do LoadConfiguration first");
43 return HGM_ERROR;
44 }
45 xmlNode *root = xmlDocGetRootElement(xmlDocument_);
46 if (root == nullptr) {
47 HGM_LOGE("XMLParser xmlDocGetRootElement failed");
48 return XML_GET_ROOT_FAIL;
49 }
50
51 if (ParseInternal(*root) == false) {
52 return XML_PARSE_INTERNAL_FAIL;
53 }
54 return EXEC_SUCCESS;
55 }
56
Destroy()57 void XMLParser::Destroy()
58 {
59 HGM_LOGD("XMLParser Destroying the parser");
60 if (xmlDocument_ != nullptr) {
61 xmlFreeDoc(xmlDocument_);
62 xmlDocument_ = nullptr;
63 }
64 }
65
GetHgmXmlNodeAsInt(xmlNode & node) const66 int32_t XMLParser::GetHgmXmlNodeAsInt(xmlNode &node) const
67 {
68 if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("Param"))) {
69 return HGM_XML_PARAM;
70 }
71 if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("Params"))) {
72 return HGM_XML_PARAMS;
73 }
74 HGM_LOGD("XMLParser failed to identify a xml node : %{public}s", node.name);
75 return HGM_XML_UNDEFINED;
76 }
77
ParseInternal(xmlNode & node)78 bool XMLParser::ParseInternal(xmlNode &node)
79 {
80 HGM_LOGD("XMLParser parsing an internal node");
81 xmlNode *currNode = &node;
82 if (currNode->xmlChildrenNode == nullptr) {
83 HGM_LOGD("XMLParser stop parsing internal, no children nodes");
84 return false;
85 }
86 currNode = currNode->xmlChildrenNode;
87 int32_t parseSuccess = EXEC_SUCCESS;
88
89 for (; currNode; currNode = currNode->next) {
90 if (currNode->type != XML_ELEMENT_NODE) {
91 continue;
92 }
93 if (parseSuccess != EXEC_SUCCESS) {
94 return false;
95 }
96
97 if (GetHgmXmlNodeAsInt(*currNode) == HGM_XML_PARAM) {
98 parseSuccess = ParseParam(*currNode);
99 } else if (GetHgmXmlNodeAsInt(*currNode) == HGM_XML_PARAMS) {
100 parseSuccess = ParseParams(*currNode);
101 }
102 }
103 return true;
104 }
105
ParseParam(xmlNode & node)106 int32_t XMLParser::ParseParam(xmlNode &node)
107 {
108 HGM_LOGI("XMLParser parsing a parameter");
109 if (!mParsedData_) {
110 HGM_LOGE("XMLParser mParsedData_ is not initialized");
111 return HGM_ERROR;
112 }
113
114 std::string paraName = ExtractPropertyValue("name", node);
115 if (paraName == "default_refreshrate_mode") {
116 HGM_LOGD("XMLParser parsing default_refreshrate_mode");
117 std::string mode = ExtractPropertyValue("value", node);
118 mParsedData_->defaultRefreshRateMode_ = mode;
119 }
120
121 if (paraName == "general_config_enable") {
122 HGM_LOGD("XMLParser parsing general_config_enable");
123 std::string parsed = ExtractPropertyValue("value", node);
124 mParsedData_->isDynamicFrameRateEnable_ = parsed;
125 }
126
127 HGM_LOGD("XMLParser parsing general_config_enable finish: %{public}s",
128 mParsedData_->isDynamicFrameRateEnable_.c_str());
129 return EXEC_SUCCESS;
130 }
131
ParseParams(xmlNode & node)132 int32_t XMLParser::ParseParams(xmlNode &node)
133 {
134 std::string paraName = ExtractPropertyValue("name", node);
135 if (paraName.empty()) {
136 HGM_LOGD("XMLParser No name provided for %{public}s", node.name);
137 return XML_PARSE_INTERNAL_FAIL;
138 }
139 if (!mParsedData_) {
140 HGM_LOGE("XMLParser mParsedData_ is not initialized");
141 return HGM_ERROR;
142 }
143
144 if (paraName == "detailed_strategies") {
145 if (ParseStrat(node) != EXEC_SUCCESS) {
146 HGM_LOGD("XMLParser failed to parse detailed_strategies");
147 }
148 return EXEC_SUCCESS;
149 }
150
151 if (paraName == "customer_setting_config") {
152 if (ParseSetting(node, mParsedData_->customerSettingConfig_) != EXEC_SUCCESS) {
153 HGM_LOGD("XMLParser failed to parse customer_setting_config");
154 }
155 return EXEC_SUCCESS;
156 }
157
158 if (paraName == "bundle_name_black_list") {
159 if (ParseSetting(node, mParsedData_->bundle_black_list_) != EXEC_SUCCESS) {
160 HGM_LOGD("XMLParser failed to parse bundle_black_list_");
161 }
162 return EXEC_SUCCESS;
163 }
164
165 if (paraName == "bundle_name_white_list") {
166 if (ParseSetting(node, mParsedData_->bundle_white_list_) != EXEC_SUCCESS) {
167 HGM_LOGD("XMLParser failed to parse bundle_white_list_");
168 }
169 return EXEC_SUCCESS;
170 }
171
172 if (paraName == "animation_dynamic_settings") {
173 if (ParseSetting(node, mParsedData_->animationDynamicStrats_) != EXEC_SUCCESS) {
174 HGM_LOGD("XMLParser failed to parse animation_dynamic_settings");
175 }
176 return EXEC_SUCCESS;
177 }
178
179 if (paraName == "property_animation_dynamic_settings") {
180 if (ParserAnimationDynamicSetting(node) != EXEC_SUCCESS) {
181 HGM_LOGD("XMLParser failed to parse property_animation_dynamic_settings");
182 }
183 return EXEC_SUCCESS;
184 }
185
186 HGM_LOGD("XMLParser parsing params finish");
187 return XML_PARSE_INTERNAL_FAIL;
188 }
189
ParseStrat(xmlNode & node)190 int32_t XMLParser::ParseStrat(xmlNode &node)
191 {
192 xmlNode *currNode = &node;
193 if (currNode->xmlChildrenNode == nullptr) {
194 HGM_LOGD("XMLParser stop parsing strats, no children nodes");
195 return HGM_ERROR;
196 }
197 if (!mParsedData_) {
198 HGM_LOGE("XMLParser mParsedData_ is not initialized");
199 return HGM_ERROR;
200 }
201
202 currNode = currNode->xmlChildrenNode;
203 for (; currNode; currNode = currNode->next) {
204 if (currNode->type != XML_ELEMENT_NODE) {
205 continue;
206 }
207
208 ParsedConfigData::detailedStrat strat;
209 strat.name = ExtractPropertyValue("name", *currNode);
210 strat.isDynamic = ExtractPropertyValue("isDynamic", *currNode);
211 strat.min = ExtractPropertyValue("min", *currNode);
212 strat.max = ExtractPropertyValue("max", *currNode);
213 mParsedData_->detailedStrategies_[strat.name] = strat;
214 }
215
216 return EXEC_SUCCESS;
217 }
218
ParseSetting(xmlNode & node,std::unordered_map<std::string,std::string> & config)219 int32_t XMLParser::ParseSetting(xmlNode &node, std::unordered_map<std::string, std::string> &config)
220 {
221 HGM_LOGD("XMLParser parsing strats");
222 xmlNode *currNode = &node;
223 if (currNode->xmlChildrenNode == nullptr) {
224 HGM_LOGD("XMLParser stop parsing settings, no children nodes");
225 return HGM_ERROR;
226 }
227 currNode = currNode->xmlChildrenNode;
228
229 for (; currNode; currNode = currNode->next) {
230 if (currNode->type != XML_ELEMENT_NODE) {
231 continue;
232 }
233
234 std::string name = "";
235 std::string value = "";
236 name = ExtractPropertyValue("name", *currNode);
237 value = ExtractPropertyValue("value", *currNode);
238 if (name.empty() || value.empty()) {
239 return XML_PARSE_INTERNAL_FAIL;
240 }
241 config[name] = value;
242 }
243
244 return EXEC_SUCCESS;
245 }
246
ParserAnimationDynamicSetting(xmlNode & node)247 int32_t XMLParser::ParserAnimationDynamicSetting(xmlNode &node)
248 {
249 xmlNode *currNode = &node;
250 if (currNode->xmlChildrenNode == nullptr) {
251 return HGM_ERROR;
252 }
253 currNode = currNode->xmlChildrenNode;
254 for (; currNode; currNode = currNode->next) {
255 auto dynamicSettingType = ExtractPropertyValue("name", *currNode);
256 if (mParsedData_->dynamicSetting_.find(dynamicSettingType) == mParsedData_->dynamicSetting_.end()) {
257 continue;
258 }
259 for (xmlNode *thresholdNode = currNode->xmlChildrenNode; thresholdNode; thresholdNode = thresholdNode->next) {
260 if (thresholdNode->type != XML_ELEMENT_NODE) {
261 continue;
262 }
263 auto name = ExtractPropertyValue("name", *thresholdNode);
264 auto min = ExtractPropertyValue("min", *thresholdNode);
265 auto max = ExtractPropertyValue("max", *thresholdNode);
266 auto preferred_fps = ExtractPropertyValue("preferred_fps", *thresholdNode);
267 if (!IsNumber(min) || !IsNumber(max) || !IsNumber(preferred_fps)) {
268 mParsedData_->dynamicSetting_[dynamicSettingType].clear();
269 break;
270 }
271 ParsedConfigData::AnimationDynamicSetting animationDynamicSetting;
272 animationDynamicSetting.min = std::stoi(ExtractPropertyValue("min", *thresholdNode));
273 animationDynamicSetting.max = std::stoi(ExtractPropertyValue("max", *thresholdNode));
274 animationDynamicSetting.preferred_fps = std::stoi(ExtractPropertyValue("preferred_fps", *thresholdNode));
275 mParsedData_->dynamicSetting_[dynamicSettingType][name] = animationDynamicSetting;
276 }
277 }
278 return EXEC_SUCCESS;
279 }
280
ExtractPropertyValue(const std::string & propName,xmlNode & node)281 std::string XMLParser::ExtractPropertyValue(const std::string &propName, xmlNode &node)
282 {
283 HGM_LOGD("XMLParser extracting value : %{public}s", propName.c_str());
284 std::string propValue = "";
285 xmlChar *tempValue = nullptr;
286
287 if (xmlHasProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()))) {
288 tempValue = xmlGetProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()));
289 }
290
291 if (tempValue != nullptr) {
292 HGM_LOGD("XMLParser not aempty tempValue");
293 propValue = reinterpret_cast<const char*>(tempValue);
294 xmlFree(tempValue);
295 tempValue = nullptr;
296 }
297
298 return propValue;
299 }
300
IsNumber(const std::string & str)301 bool XMLParser::IsNumber(const std::string &str)
302 {
303 if (str.length() == 0) {
304 return false;
305 }
306 auto number = static_cast<uint32_t>(std::count_if(str.begin(), str.end(), [](unsigned char c) {
307 return std::isdigit(c);
308 }));
309 return number == str.length() || (str.compare(0, 1, "-") == 0 && number == str.length() - 1);
310 }
311
312 } // namespace OHOS::Rosen