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