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