• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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