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