1 /*
2 * Copyright (c) 2022 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
16 #include "thermal_config_file_parser.h"
17
18 #include "string_operation.h"
19
20 namespace OHOS {
21 namespace PowerMgr {
22 namespace {
23 static const std::string VENDOR_THERMAL_SRV_CONFIG_XML = "/vendor/etc/thermal_config/thermal_service_config.xml";
24 static const std::string SYSTEM_THERMAL_SRV_CONFIG_XML = "/system/etc/thermal_config/thermal_service_config.xml";
25 } // namespace
Init()26 bool ThermalConfigFileParser::Init()
27 {
28 if (!LoadThermalSrvConfigXml(VENDOR_THERMAL_SRV_CONFIG_XML)) {
29 THERMAL_HILOGE(LABEL_TEST, "Failed to load vendor thermal config xml file");
30 if (!LoadThermalSrvConfigXml(SYSTEM_THERMAL_SRV_CONFIG_XML)) {
31 THERMAL_HILOGE(LABEL_TEST, "Failed to load system thermal config xml file");
32 return false;
33 }
34 }
35 return true;
36 }
37
GetActionEnableEvent(const std::string & actionName)38 bool ThermalConfigFileParser::GetActionEnableEvent(const std::string& actionName)
39 {
40 for (auto iter : actionItem_) {
41 if (iter.name.compare(actionName) == 0 ||
42 actionName.find(iter.name) != std::string::npos) {
43 return iter.enableEvent;
44 }
45 }
46 return false;
47 }
48
GetActionStrict(const std::string & actionName)49 bool ThermalConfigFileParser::GetActionStrict(const std::string& actionName)
50 {
51 for (auto iter : actionItem_) {
52 if (iter.name.compare(actionName) == 0 ||
53 actionName.find(iter.name) != std::string::npos) {
54 return iter.strict;
55 }
56 }
57 return false;
58 }
59
GetActionPolicy(const std::string & name,uint32_t level,std::vector<PolicyAction> & policy)60 bool ThermalConfigFileParser::GetActionPolicy(const std::string& name, uint32_t level,
61 std::vector<PolicyAction>& policy)
62 {
63 auto vPolicyCfg = policyConfigMap_.find(name);
64 if (vPolicyCfg != policyConfigMap_.end()) {
65 for (auto cfgIter : vPolicyCfg->second) {
66 if (cfgIter.level == level) {
67 policy = cfgIter.vPolicyAction;
68 return true;
69 }
70 }
71 }
72 return false;
73 }
74
GetStateItem()75 std::vector<StateItem> ThermalConfigFileParser::GetStateItem()
76 {
77 return stateItem_;
78 }
79
LoadThermalSrvConfigXml(const std::string & path)80 bool ThermalConfigFileParser::LoadThermalSrvConfigXml(const std::string& path)
81 {
82 if (!ParseXmlFile(path)) {
83 return false;
84 }
85 return true;
86 }
87
ParseXmlFile(const std::string & path)88 bool ThermalConfigFileParser::ParseXmlFile(const std::string& path)
89 {
90 std::unique_ptr<xmlDoc, decltype(&xmlFreeDoc)> docPtr(
91 xmlReadFile(path.c_str(), nullptr, XML_PARSE_NOBLANKS), xmlFreeDoc);
92 if (docPtr == nullptr) {
93 THERMAL_HILOGE(LABEL_TEST, "ParseXMLFile::Init failed, read file failed.");
94 return false;
95 }
96
97 auto rootNode = xmlDocGetRootElement(docPtr.get());
98 if (rootNode == nullptr) {
99 THERMAL_HILOGE(LABEL_TEST, "ParseXMLFile::Get root node failed.");
100 return false;
101 }
102
103 for (auto node = rootNode->children; node; node = node->next) {
104 if (node == nullptr) {
105 continue;
106 }
107 if (!xmlStrcmp(node->name, BAD_CAST"base")) {
108 ParseBaseNode(node);
109 } else if (!xmlStrcmp(node->name, BAD_CAST"level")) {
110 ParseLevelNode(node);
111 } else if (!xmlStrcmp(node->name, BAD_CAST"state")) {
112 ParseStateNode(node);
113 } else if (!xmlStrcmp(node->name, BAD_CAST"action")) {
114 ParseActionNode(node);
115 } else if (!xmlStrcmp(node->name, BAD_CAST"policy")) {
116 ParsePolicyNode(node);
117 } else if (!xmlStrcmp(node->name, BAD_CAST"idle")) {
118 ParseIdleNode(node);
119 }
120 }
121 return true;
122 }
123
ParseBaseNode(xmlNodePtr node)124 void ThermalConfigFileParser::ParseBaseNode(xmlNodePtr node)
125 {
126 auto curNode = node->xmlChildrenNode;
127 while (curNode != nullptr) {
128 BaseItem item;
129 xmlChar* xmlTag = xmlGetProp(curNode, BAD_CAST"tag");
130 if (xmlTag != nullptr) {
131 item.tag = (char *)xmlTag;
132 xmlFree(xmlTag);
133 }
134
135 xmlChar* xmlValue = xmlGetProp(curNode, BAD_CAST"value");
136 if (xmlValue != nullptr) {
137 item.value = (char *)xmlValue;
138 xmlFree(xmlValue);
139 }
140 baseInfoMap_.emplace(item.tag, item.value);
141 curNode = curNode->next;
142 THERMAL_HILOGD(LABEL_TEST, "tag: %{public}s, value:%{public}s",
143 item.tag.c_str(), item.value.c_str());
144 }
145 }
146
ParseLevelNode(xmlNodePtr node)147 void ThermalConfigFileParser::ParseLevelNode(xmlNodePtr node)
148 {
149 auto curNode = node->xmlChildrenNode;
150 while (curNode != nullptr) {
151 std::string name;
152 std::shared_ptr<ThermalConfigSensorCluster> sc = std::make_shared<ThermalConfigSensorCluster>();
153 xmlChar* xmlName = xmlGetProp(curNode, BAD_CAST"name");
154 if (xmlName != nullptr) {
155 name = (char *)xmlName;
156 xmlFree(xmlName);
157 }
158 ParseAuxSensorInfo(curNode, sc);
159 ParseSensorInfo(curNode, sc);
160 xmlChar* desc = xmlGetProp(curNode, BAD_CAST("desc"));
161 if (desc != nullptr) {
162 std::string descValue = (char *)desc;
163 if (atoi(descValue.c_str()) == 1) {
164 sc->SetDescFlag(true);
165 }
166 xmlFree(desc);
167 }
168 sensorClusterMap_.emplace(std::pair(name, sc));
169 curNode = curNode->next;
170 }
171 }
172
ParseStateNode(xmlNodePtr node)173 void ThermalConfigFileParser::ParseStateNode(xmlNodePtr node)
174 {
175 auto curNode = node->xmlChildrenNode;
176 while (curNode != nullptr) {
177 StateItem si;
178 xmlChar* xmlName = xmlGetProp(curNode, BAD_CAST"name");
179 if (xmlName != nullptr) {
180 si.name = (char *)xmlName;
181 xmlFree(xmlName);
182 }
183
184 xmlChar* param = xmlGetProp(curNode, BAD_CAST("param"));
185 if (param != nullptr) {
186 si.params =(char *)param;
187 si.isExistParam = true;
188 xmlFree(param);
189 }
190 stateItem_.push_back(si);
191 THERMAL_HILOGI(LABEL_TEST, "si.name: %{public}s, si.params %{public}s",
192 si.name.c_str(), si.params.c_str());
193 curNode = curNode->next;
194 }
195 }
196
ParseActionNode(xmlNodePtr node)197 void ThermalConfigFileParser::ParseActionNode(xmlNodePtr node)
198 {
199 auto curNode = node->xmlChildrenNode;
200 while (curNode != nullptr) {
201 if (!xmlStrcmp(curNode->name, BAD_CAST"item")) {
202 ActionItem ai;
203 xmlChar* xmlName = xmlGetProp(curNode, BAD_CAST"name");
204 if (xmlName != nullptr) {
205 ai.name = (char *)xmlName;
206 xmlFree(xmlName);
207 }
208 xmlChar* param = xmlGetProp(curNode, BAD_CAST("param"));
209 if (param != nullptr) {
210 ai.params = (char *) param;
211 xmlFree(param);
212 }
213 xmlChar* protocol = xmlGetProp(curNode, BAD_CAST("protocol"));
214 if (protocol != nullptr) {
215 ai.protocol = (char *) protocol;
216 xmlFree(protocol);
217 }
218 xmlChar* strict = xmlGetProp(curNode, BAD_CAST("strict"));
219 if (strict != nullptr) {
220 std::string strictValue = (char *)strict;
221 ai.strict = atoi(strictValue.c_str()) == 1 ? true : false;
222 xmlFree(strict);
223 }
224 xmlChar* event = xmlGetProp(curNode, BAD_CAST("event"));
225 if (event != nullptr) {
226 std::string eventValue = (char *)event;
227 ai.enableEvent = atoi(eventValue.c_str()) == 1 ? true : false;
228 xmlFree(event);
229 }
230 THERMAL_HILOGD(LABEL_TEST,
231 "ai.name: %{public}s, ai.strict: %{public}d, ai.params: %{public}s, ai.strict: %{public}s, " \
232 "ai.enableEvent: %{public}d",
233 ai.name.c_str(), ai.strict, ai.params.c_str(), ai.protocol.c_str(), ai.enableEvent);
234
235 actionItem_.push_back(ai);
236 }
237 curNode = curNode->next;
238 }
239 }
240
ParsePolicyNode(xmlNodePtr node)241 void ThermalConfigFileParser::ParsePolicyNode(xmlNodePtr node)
242 {
243 auto curNode = node->xmlChildrenNode;
244 while (curNode != nullptr) {
245 PolicyConfig policyConfig;
246 std::string clusterName;
247 xmlChar* xmlName = xmlGetProp(curNode, BAD_CAST"name");
248 if (xmlName != nullptr) {
249 clusterName = (char *)xmlName;
250 xmlFree(xmlName);
251 }
252
253 xmlChar* xmlLevel = xmlGetProp(curNode, BAD_CAST"level");
254 if (xmlLevel != nullptr) {
255 uint32_t level = static_cast<uint32_t>(atoi((char *)xmlLevel));
256 policyConfig.level = level;
257 THERMAL_HILOGD(LABEL_TEST, "policyConfig.name: %{public}s, policyConfig.level:%{public}d",
258 clusterName.c_str(), level);
259 xmlFree(xmlLevel);
260 }
261
262 ParsePolicySubnode(curNode, policyConfig);
263
264 const auto& clusterIter = policyConfigMap_.find(clusterName);
265 THERMAL_HILOGD(LABEL_TEST, "clusterName: %{public}s", clusterName.c_str());
266 if (clusterIter == policyConfigMap_.end()) {
267 std::vector<PolicyConfig> policyList;
268 policyList.push_back(policyConfig);
269 policyConfigMap_.emplace(clusterName, policyList);
270 } else {
271 clusterIter->second.push_back(policyConfig);
272 }
273 curNode = curNode->next;
274 }
275 }
276
ParseIdleNode(xmlNodePtr node)277 void ThermalConfigFileParser::ParseIdleNode(xmlNodePtr node)
278 {
279 IdleState idleState;
280 for (auto subNode = node->children; subNode != nullptr; subNode = subNode->next) {
281 if (!xmlStrcmp(subNode->name, BAD_CAST"thermallevel")) {
282 xmlChar* value = xmlNodeGetContent(subNode);
283 if (value != nullptr) {
284 idleState.level = atoi((char *)value);
285 xmlFree(value);
286 }
287 } else if (!xmlStrcmp(subNode->name, BAD_CAST"soc")) {
288 xmlChar* value = xmlNodeGetContent(subNode);
289 if (value != nullptr) {
290 idleState.soc = atoi((char *)value);
291 xmlFree(value);
292 }
293 } else if (!xmlStrcmp(subNode->name, BAD_CAST"charging")) {
294 xmlChar* value = xmlNodeGetContent(subNode);
295 if (value != nullptr) {
296 idleState.charging = atoi((char *)value);
297 xmlFree(value);
298 }
299 } else if (!xmlStrcmp(subNode->name, BAD_CAST"current")) {
300 xmlChar* value = xmlNodeGetContent(subNode);
301 if (value != nullptr) {
302 idleState.current = atoi((char *)value);
303 xmlFree(value);
304 }
305 } else {
306 THERMAL_HILOGD(LABEL_TEST, "not supported node, name=%{public}s", subNode->name);
307 }
308 }
309 THERMAL_HILOGI(LABEL_TEST, "level=%{public}d, soc=%{public}d, charging=%{public}d, current=%{public}d",
310 idleState.level, idleState.soc, idleState.charging, idleState.current);
311 }
312
ParseAuxSensorInfo(const xmlNode * cur,std::shared_ptr<ThermalConfigSensorCluster> & sc)313 void ThermalConfigFileParser::ParseAuxSensorInfo(const xmlNode* cur, std::shared_ptr<ThermalConfigSensorCluster>& sc)
314 {
315 xmlChar* auxSensorInfo = xmlGetProp(cur, BAD_CAST"aux_sensor");
316 if (auxSensorInfo != nullptr) {
317 std::vector<std::string> auxSensorList;
318 AuxSensorInfoMap auxSensorLevelInfo;
319 std::string auxSensor = (char *)auxSensorInfo;
320 sc->SetAuxFlag(true);
321 StringOperation::SplitString(auxSensor, auxSensorList, ",");
322 for (uint32_t i = 0; i < auxSensorList.size(); i++) {
323 std::string sensorType = auxSensorList[i];
324 if (auxSensorList[i].empty()) {
325 continue;
326 }
327 THERMAL_HILOGD(LABEL_TEST, "aux_sensor item: %{public}s", sensorType.c_str());
328 auxSensorLevelInfo.emplace(sensorType, ParseAuxSensorSubnodeInfo(cur, auxSensorList, i));
329 }
330 sc->SetAuxSensorLevelInfo(auxSensorLevelInfo);
331 xmlFree(auxSensorInfo);
332 }
333 }
334
ParseSensorInfo(const xmlNode * cur,std::shared_ptr<ThermalConfigSensorCluster> & sc)335 void ThermalConfigFileParser::ParseSensorInfo(const xmlNode* cur, std::shared_ptr<ThermalConfigSensorCluster>& sc)
336 {
337 SensorInfoMap sensorLevelInfo;
338 std::vector<std::string> sensors;
339 xmlChar* xmlSensor = xmlGetProp(cur, BAD_CAST"sensor");
340 if (xmlSensor != nullptr) {
341 StringOperation::SplitString((char *)xmlSensor, sensors, ",");
342 for (uint32_t i = 0; i < sensors.size(); i++) {
343 std::string sensorType = sensors.at(i);
344 std::vector<LevelItem> vItem;
345 ParseSensorSubnodeInfo(cur, vItem, sensors, i, sc);
346 sensorLevelInfo.emplace(std::pair(sensorType, vItem));
347 }
348 sc->SetSensorLevelInfo(sensorLevelInfo);
349 xmlFree(xmlSensor);
350 }
351 }
352
ParseAuxSensorSubnodeInfo(const xmlNode * cur,std::vector<std::string> & auxSensorList,const uint32_t i)353 std::vector<AuxLevelItem> ThermalConfigFileParser::ParseAuxSensorSubnodeInfo(const xmlNode* cur,
354 std::vector<std::string>& auxSensorList, const uint32_t i)
355 {
356 std::vector<AuxLevelItem> auxItems;
357 for (auto subNode = cur->children; subNode != nullptr; subNode = subNode->next) {
358 if (subNode == nullptr) {
359 continue;
360 }
361 std::string tempRanges;
362 AuxLevelItem auxlevelItem;
363 if (ParseAuxSensorSubnodeInfoTrigerRange(subNode, auxSensorList, tempRanges, i) == false) {
364 break;
365 }
366
367 std::vector<std::string> tempRiseRanges;
368 StringOperation::SplitString(tempRanges, tempRiseRanges, "_");
369 auxlevelItem.lowerTemp = atoi(tempRiseRanges[0].c_str());
370 auxlevelItem.upperTemp = atoi(tempRiseRanges[1].c_str());
371 xmlChar* xmlLevel = xmlGetProp(subNode, BAD_CAST("level"));
372 if (xmlLevel != nullptr) {
373 auxlevelItem.level = atoi((char *)xmlLevel);
374 xmlFree(xmlLevel);
375 }
376 THERMAL_HILOGD(LABEL_TEST, "aux_trigger_range: %{public}s",
377 tempRanges.c_str());
378 THERMAL_HILOGD(LABEL_TEST, "lowerTemp: %{public}d, upperTemp: %{public}d",
379 auxlevelItem.lowerTemp, auxlevelItem.upperTemp);
380 auxItems.push_back(auxlevelItem);
381 }
382 return auxItems;
383 }
384
ParseAuxSensorSubnodeInfoTrigerRange(const xmlNode * subNode,std::vector<std::string> & auxSensorList,std::string & tempRanges,const uint32_t i)385 bool ThermalConfigFileParser::ParseAuxSensorSubnodeInfoTrigerRange(const xmlNode* subNode,
386 std::vector<std::string>& auxSensorList, std::string& tempRanges, const uint32_t i)
387 {
388 xmlChar* xmlTriggerRange = xmlGetProp(subNode, BAD_CAST("aux_trigger_range"));
389 if (xmlTriggerRange != nullptr) {
390 std::string auxTriggerRange = (char *)xmlTriggerRange;
391 if (!auxTriggerRange.empty()) {
392 std::vector<std::string> auxTempranges;
393 StringOperation::SplitString(auxTriggerRange, auxTempranges, ",");
394 if (auxSensorList.size() > auxTempranges.size()) {
395 THERMAL_HILOGI(LABEL_TEST, "The auxiliary sensor does not match the threshold range");
396 xmlFree(xmlTriggerRange);
397 return false;
398 }
399 tempRanges = auxTempranges[i];
400 }
401 xmlFree(xmlTriggerRange);
402 }
403 return true;
404 }
405
ParseSensorSubnodeInfo(const xmlNode * cur,std::vector<LevelItem> & vItem,std::vector<std::string> & sensors,const uint32_t i,std::shared_ptr<ThermalConfigSensorCluster> & sc)406 void ThermalConfigFileParser::ParseSensorSubnodeInfo(const xmlNode* cur, std::vector<LevelItem>& vItem,
407 std::vector<std::string>& sensors, const uint32_t i, std::shared_ptr<ThermalConfigSensorCluster>& sc)
408 {
409 for (auto subNode = cur->children; subNode; subNode = subNode->next) {
410 if (subNode == nullptr) {
411 continue;
412 }
413 LevelItem levelItem;
414 std::vector<std::string> thresholds;
415 std::vector<std::string> thresholdClrs;
416 std::vector<std::string> rates;
417 xmlChar* xmlThreshold = xmlGetProp(subNode, BAD_CAST("threshold"));
418 if (xmlThreshold != nullptr) {
419 StringOperation::SplitString((char *)xmlThreshold, thresholds, ",");
420 xmlFree(xmlThreshold);
421 }
422 xmlChar* xmlThresholdClr = xmlGetProp(subNode, BAD_CAST("threshold_clr"));
423 if (xmlThresholdClr != nullptr) {
424 StringOperation::SplitString((char *)xmlThresholdClr, thresholdClrs, ",");
425 xmlFree(xmlThresholdClr);
426 }
427 if (sensors.size() > thresholds.size() || sensors.size() > thresholdClrs.size()) {
428 THERMAL_HILOGI(LABEL_TEST, "The sensor does not match the threshold range");
429 break;
430 }
431 xmlChar* xmlLevel = xmlGetProp(subNode, BAD_CAST("level"));
432 if (xmlLevel != nullptr) {
433 levelItem.level = static_cast<uint32_t>(atoi(((char *)xmlLevel)));
434 xmlFree(xmlLevel);
435 }
436
437 levelItem.threshold = atoi(thresholds.at(i).c_str());
438 levelItem.thresholdClr = atoi(thresholdClrs.at(i).c_str());
439 xmlChar* tempRiseRates = xmlGetProp(subNode, BAD_CAST("temp_rise_rate"));
440 if (tempRiseRates != nullptr) {
441 sc->SetRateFlag(true);
442 StringOperation::SplitString((char *)tempRiseRates, rates, ",");
443 if (sensors.size() > rates.size()) {
444 break;
445 }
446 levelItem.tempRiseRate = atof(rates.at(i).c_str());
447 }
448 vItem.push_back(levelItem);
449 xmlFree(tempRiseRates);
450 }
451 }
452
ParsePolicySubnode(const xmlNode * cur,PolicyConfig & policyConfig)453 void ThermalConfigFileParser::ParsePolicySubnode(const xmlNode* cur, PolicyConfig& policyConfig)
454 {
455 for (auto subNode = cur->children; subNode != nullptr; subNode = subNode->next) {
456 if (subNode == nullptr) {
457 continue;
458 }
459 PolicyAction policyAction;
460 policyAction.actionName = (char *)subNode->name;
461 xmlChar* xmlActionValue = xmlNodeGetContent(subNode);
462 if (xmlActionValue != nullptr) {
463 policyAction.actionValue = (char *)xmlActionValue;
464 THERMAL_HILOGD(LABEL_TEST,
465 "policyAction.actionNodeName: %{public}s, policyAction.value:%{public}s",
466 policyAction.actionName.c_str(), policyAction.actionValue.c_str());
467 xmlFree(xmlActionValue);
468 }
469
470 if (subNode->properties == nullptr) {
471 THERMAL_HILOGD(LABEL_TEST, "action prop is nullptr");
472 policyAction.isProp = false;
473 policyConfig.vPolicyAction.push_back(policyAction);
474 continue;
475 }
476 for (auto actionProp = subNode->properties; actionProp != nullptr; actionProp = actionProp->next) {
477 std::string propName = (char *)actionProp->name;
478 xmlChar* xmlPropValue = xmlGetProp(subNode, actionProp->name);
479 if (xmlPropValue != nullptr) {
480 std::string propValue = (char *)xmlPropValue;
481 THERMAL_HILOGD(LABEL_TEST, "propName.name: %{public}s, propValue:%{public}s",
482 propName.c_str(), propValue.c_str());
483 policyAction.mActionProp.emplace(std::pair(propName, propValue));
484 xmlFree(xmlPropValue);
485 }
486 policyAction.isProp = true;
487 }
488 policyConfig.vPolicyAction.push_back(policyAction);
489 }
490 }
491 } // namespace PowerMgr
492 } // namespace OHOS
493