1 /*
2  * Copyright (c) 2021-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_srv_config_parser.h"
17 
18 #include "string_operation.h"
19 #include "thermal_common.h"
20 #include "thermal_service.h"
21 #include "string_ex.h"
22 
23 #include <dlfcn.h>
24 
25 namespace OHOS {
26 namespace PowerMgr {
27 namespace {
28 constexpr uint32_t AUX_SENSOR_RANGE_LEN = 2;
29 const std::string TRUE_STR = "1";
30 constexpr const char* GET_THERMAL_EXT_CONGIH_FUNC = "GetThermalExtConfig";
31 constexpr const char* THERMAL_CONFIG_LIBRARY_PATH = "libthermal_manager_ext.z.so";
32 const std::string SYSTEM_PREFIX = "/system";
33 constexpr int32_t SYSTEM_PREFIX_INDEX = 7;
34 constexpr int32_t THERMAL_SERVICE_CONFIG_INDEX = 2;
35 typedef int32_t(*Func)(int32_t, std::string&);
36 }
37 
ThermalSrvConfigParser()38 ThermalSrvConfigParser::ThermalSrvConfigParser() {};
39 
ThermalSrvConfigInit(const std::string & path)40 bool ThermalSrvConfigParser::ThermalSrvConfigInit(const std::string& path)
41 {
42     if (ParseXmlFile(path)) {
43         return true;
44     }
45     return false;
46 }
47 
DecryptConfig(const std::string & path,std::string & result)48 bool ThermalSrvConfigParser::DecryptConfig(const std::string& path, std::string& result)
49 {
50     if (path.compare(0, SYSTEM_PREFIX_INDEX, SYSTEM_PREFIX) == 0) {
51         return false;
52     }
53     THERMAL_HILOGI(COMP_SVC, "start DecryptConfig");
54     void *handler = dlopen(THERMAL_CONFIG_LIBRARY_PATH, RTLD_LAZY);
55     if (handler == nullptr) {
56         THERMAL_HILOGE(COMP_SVC, "dlopen failed, reason : %{public}s", dlerror());
57         return false;
58     }
59 
60     Func getDecryptConfig = reinterpret_cast<Func>(dlsym(handler, GET_THERMAL_EXT_CONGIH_FUNC));
61     if (getDecryptConfig == nullptr) {
62         THERMAL_HILOGE(COMP_SVC, "find function %{public}s failed, reason : %{public}s",
63             GET_THERMAL_EXT_CONGIH_FUNC, dlerror());
64 #ifndef FUZZ_TEST
65         dlclose(handler);
66 #endif
67         return false;
68     }
69 
70     int32_t ret = getDecryptConfig(THERMAL_SERVICE_CONFIG_INDEX, result);
71     if (ret != 0) {
72         THERMAL_HILOGE(COMP_SVC, "decrypt config failed, ret:%{public}d", ret);
73 #ifndef FUZZ_TEST
74         dlclose(handler);
75 #endif
76         return false;
77     }
78 
79 #ifndef FUZZ_TEST
80     dlclose(handler);
81 #endif
82     THERMAL_HILOGI(COMP_SVC, "end DecryptConfig");
83     return true;
84 }
85 
ParseXmlFile(const std::string & path)86 bool ThermalSrvConfigParser::ParseXmlFile(const std::string& path)
87 {
88     xmlDocPtr docParse;
89     std::string result;
90     if (DecryptConfig(path, result)) {
91         // Initialize configuration file through the decrypt results
92         docParse = xmlReadMemory(
93             result.c_str(), int(result.size()), NULL, NULL, XML_PARSE_NOBLANKS);
94     } else {
95         THERMAL_HILOGI(COMP_SVC, "don't need decrypt");
96         docParse = xmlReadFile(path.c_str(), nullptr, XML_PARSE_NOBLANKS);
97     }
98 
99     std::unique_ptr<xmlDoc, decltype(&xmlFreeDoc)> docPtr(docParse, xmlFreeDoc);
100     if (docPtr == nullptr) {
101         THERMAL_HILOGE(COMP_SVC, "init failed, read file failed");
102         return false;
103     }
104 
105     auto rootNode = xmlDocGetRootElement(docPtr.get());
106     if (rootNode == nullptr) {
107         THERMAL_HILOGE(COMP_SVC, "get root node failed");
108         return false;
109     }
110 
111     for (xmlNodePtr node = rootNode->xmlChildrenNode; node != nullptr; node = node->next) {
112         if (!ParseRootNode(node)) {
113             return false;
114         }
115     }
116     return true;
117 }
118 
ParseRootNode(const xmlNodePtr & node)119 bool ThermalSrvConfigParser::ParseRootNode(const xmlNodePtr& node)
120 {
121     bool ret = false;
122     if (!xmlStrcmp(node->name, BAD_CAST"base")) {
123         ret = ParseBaseNode(node);
124     } else if (!xmlStrcmp(node->name, BAD_CAST"level")) {
125         ret = ParseLevelNode(node);
126     } else if (!xmlStrcmp(node->name, BAD_CAST"state")) {
127         ret = ParseStateNode(node);
128     } else if (!xmlStrcmp(node->name, BAD_CAST"action")) {
129         ret = ParseActionNode(node);
130     } else if (!xmlStrcmp(node->name, BAD_CAST"policy")) {
131         ret = ParsePolicyNode(node);
132     } else if (!xmlStrcmp(node->name, BAD_CAST"idle")) {
133         ret = ParseIdleNode(node);
134     } else if (!xmlStrcmp(node->name, BAD_CAST"fan")) {
135         ret = ParseFanNode(node);
136     } else if (!xmlStrcmp(node->name, BAD_CAST"comment")) {
137         ret = true;
138     } else {
139         THERMAL_HILOGE(COMP_SVC, "unknown root node %{public}s",
140             reinterpret_cast<const char*>(node->name));
141     }
142     return ret;
143 }
144 
ParseBaseNode(const xmlNodePtr & node)145 bool ThermalSrvConfigParser::ParseBaseNode(const xmlNodePtr& node)
146 {
147     BaseInfoMap baseInfoMap;
148     xmlNodePtr cur = node->xmlChildrenNode;
149     while (cur != nullptr) {
150         if (xmlStrcmp(cur->name, BAD_CAST"item")) {
151             cur = cur->next;
152             continue;
153         }
154         BaseItem bi;
155         xmlChar* xmlTag = xmlGetProp(cur, BAD_CAST"tag");
156         if (xmlTag != nullptr) {
157             bi.tag = reinterpret_cast<char*>(xmlTag);
158             xmlFree(xmlTag);
159         } else {
160             THERMAL_HILOGE(COMP_SVC, "base tag is null");
161             return false;
162         }
163 
164         xmlChar* xmlValue = xmlGetProp(cur, BAD_CAST"value");
165         if (xmlValue != nullptr) {
166             bi.value = reinterpret_cast<char*>(xmlValue);
167             xmlFree(xmlValue);
168         } else {
169             THERMAL_HILOGE(COMP_SVC, "base value is null, tag: %{public}s", bi.tag.c_str());
170             return false;
171         }
172         baseInfoMap.emplace(bi.tag, bi.value);
173         cur = cur->next;
174         THERMAL_HILOGD(COMP_SVC, "tag: %{public}s, value: %{public}s", bi.tag.c_str(), bi.value.c_str());
175     }
176     auto tms = ThermalService::GetInstance();
177     tms->GetBaseinfoObj()->SetBaseInfo(baseInfoMap);
178     auto iter = baseInfoMap.find("sim_tz");
179     if (iter != baseInfoMap.end()) {
180         if (iter->second == "") {
181             tms->SetSimulationXml(false);
182             return true;
183         }
184         if (iter->second == "0" || iter->second == "1") {
185             tms->SetSimulationXml(static_cast<bool>(std::stoi(iter->second)));
186             return true;
187         }
188         return false;
189     }
190     tms->SetSimulationXml(false);
191     return true;
192 }
193 
ParseLevelNode(const xmlNodePtr & node)194 bool ThermalSrvConfigParser::ParseLevelNode(const xmlNodePtr& node)
195 {
196     xmlNodePtr cur = node->xmlChildrenNode;
197     SensorClusterMap msc;
198     while (cur != nullptr) {
199         if (xmlStrcmp(cur->name, BAD_CAST"sensor_cluster")) {
200             cur = cur->next;
201             continue;
202         }
203         std::string name;
204         SensorClusterPtr sc = std::make_shared<ThermalConfigSensorCluster>();
205         xmlChar* xmlName = xmlGetProp(cur, BAD_CAST"name");
206         if (xmlName != nullptr) {
207             name = reinterpret_cast<char*>(xmlName);
208             xmlFree(xmlName);
209         } else {
210             THERMAL_HILOGE(COMP_SVC, "level cluster name is null");
211             return false;
212         }
213         if (!ParseLevelState(cur, sc) || !ParseAuxSensorInfo(cur, sc) || !ParseSensorInfo(cur, sc)) {
214             THERMAL_HILOGE(COMP_SVC, "parse sensor info failed, cluster name: %{public}s", name.c_str());
215             return false;
216         }
217         xmlChar* desc = xmlGetProp(cur, BAD_CAST("desc"));
218         if (desc != nullptr) {
219             if (TrimStr(reinterpret_cast<char*>(desc)) == TRUE_STR) {
220                 sc->SetDescFlag(true);
221                 THERMAL_HILOGD(COMP_SVC, "cluster [%{public}s] is desc", name.c_str());
222             }
223             xmlFree(desc);
224         }
225         if (!sc->CheckStandard()) {
226             THERMAL_HILOGE(COMP_SVC, "cluster [%{public}s] some config error", name.c_str());
227             return false;
228         }
229         msc.emplace(std::pair(name, sc));
230         cur = cur->next;
231     }
232     auto tms = ThermalService::GetInstance();
233     tms->GetPolicy()->SetSensorClusterMap(msc);
234     return true;
235 }
236 
ParseLevelState(const xmlNodePtr & cur,SensorClusterPtr & sc)237 bool ThermalSrvConfigParser::ParseLevelState(const xmlNodePtr& cur, SensorClusterPtr& sc)
238 {
239     for (xmlNodePtr subNode = cur->xmlChildrenNode; subNode != nullptr; subNode = subNode->next) {
240         if (xmlStrcmp(subNode->name, BAD_CAST"state") || (subNode->properties == nullptr)) {
241             continue;
242         }
243         for (auto levStateProp = subNode->properties; levStateProp != nullptr; levStateProp = levStateProp->next) {
244             std::string propName = reinterpret_cast<const char*>(levStateProp->name);
245             xmlChar* xmlPropValue = xmlGetProp(subNode, levStateProp->name);
246             if (xmlPropValue != nullptr) {
247                 std::string propValue = reinterpret_cast<char*>(xmlPropValue);
248                 THERMAL_HILOGD(COMP_SVC, "level state: %{public}s, value: %{public}s",
249                     propName.c_str(), propValue.c_str());
250                 sc->AddState(propName, propValue);
251                 xmlFree(xmlPropValue);
252             } else {
253                 THERMAL_HILOGE(COMP_SVC, "level state prop [%{public}s] value is null", propName.c_str());
254                 return false;
255             }
256         }
257     }
258     return true;
259 }
260 
ParseAuxSensorInfo(const xmlNodePtr & cur,SensorClusterPtr & sc)261 bool ThermalSrvConfigParser::ParseAuxSensorInfo(const xmlNodePtr& cur, SensorClusterPtr& sc)
262 {
263     xmlChar* auxSensor = xmlGetProp(cur, BAD_CAST"aux_sensor");
264     if (auxSensor != nullptr) {
265         std::vector<std::string> auxsensors;
266         AuxSensorInfoMap auxSensorLevelInfo;
267         std::string auxsensor = reinterpret_cast<char*>(auxSensor);
268         sc->SetAuxFlag(true);
269         StringOperation::SplitString(auxsensor, auxsensors, ",");
270         for (uint32_t i = 0; i < auxsensors.size(); i++) {
271             std::vector<AuxLevelItem> auxLevelItems;
272             std::string sensorType = auxsensors[i];
273             if (sensorType.empty()) {
274                 THERMAL_HILOGE(COMP_SVC, "aux sensor type is empty");
275                 return false;
276             }
277             THERMAL_HILOGD(COMP_SVC, "parse aux sensor [%{public}s] item:", sensorType.c_str());
278             if (!ParseAuxSensorLevInfo(cur, auxsensors, i, auxLevelItems)) {
279                 THERMAL_HILOGE(COMP_SVC, "parse aux sensor [%{public}s] sub node failed", sensorType.c_str());
280                 return false;
281             }
282             if (auxLevelItems.empty()) {
283                 THERMAL_HILOGE(COMP_SVC, "aux sensor [%{public}s] level info is empty", sensorType.c_str());
284                 return false;
285             }
286             auxSensorLevelInfo.emplace(sensorType, auxLevelItems);
287         }
288         sc->SetAuxSensorLevelInfo(auxSensorLevelInfo);
289         xmlFree(auxSensor);
290     }
291     return true;
292 }
293 
ParseAuxSensorLevInfo(const xmlNodePtr & cur,std::vector<std::string> & auxsensors,const uint32_t sensorIdx,std::vector<AuxLevelItem> & auxLevelItems)294 bool ThermalSrvConfigParser::ParseAuxSensorLevInfo(const xmlNodePtr& cur,
295     std::vector<std::string>& auxsensors, const uint32_t sensorIdx, std::vector<AuxLevelItem>& auxLevelItems)
296 {
297     for (xmlNodePtr subNode = cur->xmlChildrenNode; subNode != nullptr; subNode = subNode->next) {
298         if (xmlStrcmp(subNode->name, BAD_CAST"item")) {
299             continue;
300         }
301         std::string tempRangeStr;
302         AuxLevelItem auxlevelItem;
303         if (!ParseAuxSensorTriggerRange(subNode, auxsensors, tempRangeStr, sensorIdx)) {
304             THERMAL_HILOGE(COMP_SVC, "parse aux sensor range failed");
305             return false;
306         }
307 
308         std::vector<std::string> tempRanges;
309         StringOperation::SplitString(tempRangeStr, tempRanges, "_");
310         if (static_cast<uint32_t>(tempRanges.size()) < AUX_SENSOR_RANGE_LEN) {
311             THERMAL_HILOGE(COMP_SVC, "aux sensor temp range split failed");
312             return false;
313         }
314         const int32_t INDEX0 = 0;
315         const int32_t INDEX1 = 1;
316         StrToInt(tempRanges[INDEX0], auxlevelItem.lowerTemp);
317         StrToInt(tempRanges[INDEX1], auxlevelItem.upperTemp);
318         xmlChar* xmlLevel = xmlGetProp(subNode, BAD_CAST("level"));
319         if (xmlLevel != nullptr) {
320             StrToInt(reinterpret_cast<char*>(xmlLevel), auxlevelItem.level);
321             xmlFree(xmlLevel);
322         } else {
323             THERMAL_HILOGE(COMP_SVC, "aux sensor level is null");
324             return false;
325         }
326         THERMAL_HILOGD(COMP_SVC, "lowerTemp: %{public}d, upperTemp: %{public}d",
327             auxlevelItem.lowerTemp, auxlevelItem.upperTemp);
328         auxLevelItems.push_back(auxlevelItem);
329     }
330     return true;
331 }
332 
ParseAuxSensorTriggerRange(const xmlNodePtr & subNode,std::vector<std::string> & auxsensors,std::string & tempRangeStr,const uint32_t sensorIdx)333 bool ThermalSrvConfigParser::ParseAuxSensorTriggerRange(const xmlNodePtr& subNode,
334     std::vector<std::string>& auxsensors, std::string& tempRangeStr, const uint32_t sensorIdx)
335 {
336     xmlChar* xmlTriggerRange = xmlGetProp(subNode, BAD_CAST("aux_trigger_range"));
337     if (xmlTriggerRange != nullptr) {
338         std::string auxTriggerRange = reinterpret_cast<char*>(xmlTriggerRange);
339         if (!auxTriggerRange.empty()) {
340             std::vector<std::string> auxTempranges;
341             StringOperation::SplitString(auxTriggerRange, auxTempranges, ",");
342             if (auxsensors.size() > auxTempranges.size()) {
343                 THERMAL_HILOGE(COMP_SVC, "aux sensor size (%{public}zu) don't match range size (%{public}zu)",
344                     auxsensors.size(), auxTempranges.size());
345                 xmlFree(xmlTriggerRange);
346                 return false;
347             }
348             tempRangeStr = auxTempranges[sensorIdx];
349         } else {
350             THERMAL_HILOGE(COMP_SVC, "aux sensor trigger range is empty");
351             return false;
352         }
353         xmlFree(xmlTriggerRange);
354     } else {
355         THERMAL_HILOGE(COMP_SVC, "aux sensor trigger range is null");
356         return false;
357     }
358     return true;
359 }
360 
ParseSensorInfo(const xmlNodePtr & cur,SensorClusterPtr & sc)361 bool ThermalSrvConfigParser::ParseSensorInfo(const xmlNodePtr& cur, SensorClusterPtr& sc)
362 {
363     SensorInfoMap sensorLevelInfo;
364     std::vector<std::string> sensors;
365     xmlChar* xmlSensor = xmlGetProp(cur, BAD_CAST"sensor");
366     if (xmlSensor != nullptr) {
367         StringOperation::SplitString(reinterpret_cast<char*>(xmlSensor), sensors, ",");
368         if (sensors.empty()) {
369             THERMAL_HILOGE(COMP_SVC, "sensor type is empty");
370             return false;
371         }
372         for (uint32_t i = 0; i < sensors.size(); i++) {
373             std::string sensorType = sensors.at(i);
374             std::vector<LevelItem> levelItems;
375             if (!ParseSensorLevelInfo(cur, levelItems, sensors, i, sc)) {
376                 THERMAL_HILOGE(COMP_SVC, "parse sensor [%{public}s] level failed", sensorType.c_str());
377                 return false;
378             }
379             if (levelItems.empty()) {
380                 THERMAL_HILOGE(COMP_SVC, "sensor [%{public}s] level info is empty", sensorType.c_str());
381                 return false;
382             }
383             sensorLevelInfo.emplace(std::pair(sensorType, levelItems));
384         }
385         sc->SetSensorLevelInfo(sensorLevelInfo);
386         xmlFree(xmlSensor);
387     } else {
388         THERMAL_HILOGE(COMP_SVC, "sensor type is null");
389         return false;
390     }
391     return true;
392 }
393 
ParseSensorLevelInfo(const xmlNodePtr & cur,std::vector<LevelItem> & levelItems,std::vector<std::string> & sensors,const uint32_t sensorIdx,SensorClusterPtr & sc)394 bool ThermalSrvConfigParser::ParseSensorLevelInfo(const xmlNodePtr& cur, std::vector<LevelItem>& levelItems,
395     std::vector<std::string>& sensors, const uint32_t sensorIdx, SensorClusterPtr& sc)
396 {
397     for (xmlNodePtr subNode = cur->xmlChildrenNode; subNode != nullptr; subNode = subNode->next) {
398         if (xmlStrcmp(subNode->name, BAD_CAST"item")) {
399             continue;
400         }
401         LevelItem levelItem;
402         if (!ParseLevelThreshold(subNode, levelItem, sensors, sensorIdx)) {
403             THERMAL_HILOGE(COMP_SVC, "parse level threshold failed");
404             return false;
405         }
406 
407         xmlChar* tempRiseRates = xmlGetProp(subNode, BAD_CAST("temp_rise_rate"));
408         if (tempRiseRates != nullptr) {
409             std::vector<std::string> rates;
410             sc->SetRateFlag(true);
411             StringOperation::SplitString(reinterpret_cast<char*>(tempRiseRates), rates, ",");
412             if (sensors.size() != rates.size()) {
413                 THERMAL_HILOGE(COMP_SVC, "sensor size (%{public}zu) don't match rise rate (%{public}zu)",
414                     sensors.size(), rates.size());
415                 xmlFree(tempRiseRates);
416                 return false;
417             }
418             StringOperation::StrToDouble(rates.at(sensorIdx), levelItem.tempRiseRate);
419         }
420         levelItems.push_back(levelItem);
421         xmlFree(tempRiseRates);
422     }
423     return true;
424 }
425 
ParseLevelThreshold(const xmlNodePtr & subNode,LevelItem & levelItem,std::vector<std::string> & sensors,const uint32_t sensorIdx)426 bool ThermalSrvConfigParser::ParseLevelThreshold(const xmlNodePtr& subNode, LevelItem& levelItem,
427     std::vector<std::string>& sensors, const uint32_t sensorIdx)
428 {
429     std::vector<std::string> thresholds;
430     std::vector<std::string> thresholdClrs;
431     xmlChar* xmlThreshold = xmlGetProp(subNode, BAD_CAST("threshold"));
432     if (xmlThreshold != nullptr) {
433         StringOperation::SplitString(reinterpret_cast<char*>(xmlThreshold), thresholds, ",");
434         xmlFree(xmlThreshold);
435     } else {
436         THERMAL_HILOGE(COMP_SVC, "threshold is null");
437         return false;
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     } else {
444         THERMAL_HILOGE(COMP_SVC, "threshold_clr is null");
445         return false;
446     }
447     if (sensors.size() != thresholds.size() || sensors.size() != thresholdClrs.size()) {
448         THERMAL_HILOGE(COMP_SVC,
449             "sensor size (%{public}zu) don't match threshold (%{public}zu) or clr (%{public}zu)",
450             sensors.size(), thresholds.size(), thresholdClrs.size());
451         return false;
452     }
453     xmlChar* xmlLevel = xmlGetProp(subNode, BAD_CAST("level"));
454     if (xmlLevel != nullptr) {
455         StringOperation::StrToUint(reinterpret_cast<char*>(xmlLevel), levelItem.level);
456         xmlFree(xmlLevel);
457     } else {
458         THERMAL_HILOGE(COMP_SVC, "level is null");
459         return false;
460     }
461 
462     StrToInt(thresholds.at(sensorIdx), levelItem.threshold);
463     StrToInt(thresholdClrs.at(sensorIdx), levelItem.thresholdClr);
464     return true;
465 }
466 
ParseStateNode(const xmlNodePtr & node)467 bool ThermalSrvConfigParser::ParseStateNode(const xmlNodePtr& node)
468 {
469     auto cur = node->xmlChildrenNode;
470     std::vector<StateItem> stateItems;
471     while (cur != nullptr) {
472         if (xmlStrcmp(cur->name, BAD_CAST"item")) {
473             cur = cur->next;
474             continue;
475         }
476         StateItem si;
477         xmlChar* xmlName = xmlGetProp(cur, BAD_CAST"name");
478         if (xmlName != nullptr) {
479             si.name = reinterpret_cast<char*>(xmlName);
480             xmlFree(xmlName);
481         } else {
482             THERMAL_HILOGE(COMP_SVC, "state name is null");
483             return false;
484         }
485 
486         xmlChar* param = xmlGetProp(cur, BAD_CAST("param"));
487         if (param != nullptr) {
488             si.params = reinterpret_cast<char*>(param);
489             si.isExistParam = true;
490             xmlFree(param);
491         }
492         stateItems.push_back(si);
493         THERMAL_HILOGD(COMP_SVC, "state: %{public}s, params: %{public}s", si.name.c_str(), si.params.c_str());
494         cur = cur->next;
495     }
496     auto tms = ThermalService::GetInstance();
497     tms->GetStateMachineObj()->SetStateItem(stateItems);
498     return true;
499 }
500 
ParseActionNode(const xmlNodePtr & node)501 bool ThermalSrvConfigParser::ParseActionNode(const xmlNodePtr& node)
502 {
503     auto cur = node->xmlChildrenNode;
504     std::vector<ActionItem> actionItems;
505     while (cur != nullptr) {
506         if (xmlStrcmp(cur->name, BAD_CAST"item")) {
507             cur = cur->next;
508             continue;
509         }
510 
511         ActionItem ai;
512         xmlChar* xmlName = xmlGetProp(cur, BAD_CAST"name");
513         if (xmlName != nullptr) {
514             ai.name = reinterpret_cast<char*>(xmlName);
515             xmlFree(xmlName);
516         } else {
517             THERMAL_HILOGE(COMP_SVC, "action name is null");
518             return false;
519         }
520 
521         ParseActionInfo(cur, ai);
522         actionItems.push_back(ai);
523         cur = cur->next;
524     }
525     auto tms = ThermalService::GetInstance();
526     tms->GetActionManagerObj()->SetActionItem(actionItems);
527     return true;
528 }
529 
ParseActionInfo(const xmlNodePtr & cur,ActionItem & ai)530 bool ThermalSrvConfigParser::ParseActionInfo(const xmlNodePtr& cur, ActionItem& ai)
531 {
532     xmlChar* param = xmlGetProp(cur, BAD_CAST("param"));
533     if (param != nullptr) {
534         ai.params = reinterpret_cast<char*>(param);
535         xmlFree(param);
536     }
537     xmlChar* uid = xmlGetProp(cur, BAD_CAST("uid"));
538     if (uid != nullptr) {
539         ai.uid = reinterpret_cast<char*>(uid);
540         xmlFree(uid);
541     }
542     xmlChar* protocol = xmlGetProp(cur, BAD_CAST("protocol"));
543     if (protocol != nullptr) {
544         ai.protocol = reinterpret_cast<char*>(protocol);
545         xmlFree(protocol);
546     }
547     xmlChar* strict = xmlGetProp(cur, BAD_CAST("strict"));
548     if (strict != nullptr) {
549         ai.strict = (TrimStr(reinterpret_cast<char*>(strict)) == TRUE_STR);
550         xmlFree(strict);
551     }
552     xmlChar* event = xmlGetProp(cur, BAD_CAST("event"));
553     if (event != nullptr) {
554         ai.enableEvent = (TrimStr(reinterpret_cast<char*>(event)) == TRUE_STR);
555         xmlFree(event);
556     }
557     THERMAL_HILOGD(COMP_SVC,
558         "ai.name: %{public}s, ai.strict: %{public}d, ai.params: %{public}s, ai.uid: %{public}s,"    \
559         "ai.strict: %{public}s, ai.enableEvent: %{public}d",
560         ai.name.c_str(), ai.strict, ai.params.c_str(), ai.uid.c_str(), ai.protocol.c_str(), ai.enableEvent);
561     return true;
562 }
563 
ParsePolicyNode(const xmlNodePtr & node)564 bool ThermalSrvConfigParser::ParsePolicyNode(const xmlNodePtr& node)
565 {
566     auto cur = node->xmlChildrenNode;
567     ThermalPolicy::PolicyConfigMap clusterPolicyMap;
568     while (cur != nullptr) {
569         if (xmlStrcmp(cur->name, BAD_CAST"config")) {
570             cur = cur->next;
571             continue;
572         }
573         PolicyConfig policyConfig;
574         std::string clusterName;
575         xmlChar* xmlName = xmlGetProp(cur, BAD_CAST"name");
576         if (xmlName != nullptr) {
577             clusterName = reinterpret_cast<char*>(xmlName);
578             xmlFree(xmlName);
579         } else {
580             THERMAL_HILOGE(COMP_SVC, "policy config name is null");
581             return false;
582         }
583 
584         xmlChar* xmlLevel = xmlGetProp(cur, BAD_CAST"level");
585         if (xmlLevel != nullptr) {
586             StringOperation::StrToUint(reinterpret_cast<char*>(xmlLevel), policyConfig.level);
587             THERMAL_HILOGD(COMP_SVC, "policyConfig.name: %{public}s, policyConfig.level: %{public}u",
588                 clusterName.c_str(), policyConfig.level);
589             xmlFree(xmlLevel);
590         } else {
591             THERMAL_HILOGE(COMP_SVC, "policy [%{public}s] level is null", clusterName.c_str());
592             return false;
593         }
594 
595         ParsePolicyActionInfo(cur, policyConfig);
596 
597         const auto& clusterIter = clusterPolicyMap.find(clusterName);
598         if (clusterIter == clusterPolicyMap.end()) {
599             std::vector<PolicyConfig> policyList;
600             policyList.push_back(policyConfig);
601             clusterPolicyMap.emplace(clusterName, policyList);
602         } else {
603             clusterIter->second.push_back(policyConfig);
604         }
605         cur = cur->next;
606     }
607     auto tms = ThermalService::GetInstance();
608     tms->GetPolicy()->SetPolicyMap(clusterPolicyMap);
609     return true;
610 }
611 
ParsePolicyActionInfo(const xmlNodePtr & cur,PolicyConfig & policyConfig)612 bool ThermalSrvConfigParser::ParsePolicyActionInfo(const xmlNodePtr& cur, PolicyConfig& policyConfig)
613 {
614     for (xmlNodePtr subNode = cur->xmlChildrenNode; subNode != nullptr; subNode = subNode->next) {
615         if (!xmlStrcmp(subNode->name, BAD_CAST"comment")) {
616             continue;
617         }
618         PolicyAction policyAction;
619         policyAction.actionName = reinterpret_cast<const char*>(subNode->name);
620         xmlChar* actionValue = xmlNodeGetContent(subNode);
621         if (actionValue != nullptr) {
622             policyAction.actionValue = reinterpret_cast<char*>(actionValue);
623             THERMAL_HILOGD(COMP_SVC,
624                 "policyAction.actionNodeName: %{public}s, policyAction.value: %{public}s",
625                 policyAction.actionName.c_str(), policyAction.actionValue.c_str());
626             xmlFree(actionValue);
627         } else {
628             THERMAL_HILOGE(COMP_SVC, "action [%{public}s] value is null", policyAction.actionName.c_str());
629             return false;
630         }
631 
632         if (subNode->properties == nullptr) {
633             policyAction.isProp = false;
634             policyConfig.policyActionList.push_back(policyAction);
635             continue;
636         }
637         for (auto actionProp = subNode->properties; actionProp != nullptr; actionProp = actionProp->next) {
638             std::string propName = reinterpret_cast<const char*>(actionProp->name);
639             xmlChar* xmlPropValue = xmlGetProp(subNode, actionProp->name);
640             if (xmlPropValue != nullptr) {
641                 std::string propValue = reinterpret_cast<char*>(xmlPropValue);
642                 THERMAL_HILOGD(COMP_SVC, "propName.name: %{public}s, propValue:%{public}s",
643                     propName.c_str(), propValue.c_str());
644                 policyAction.actionPropMap.emplace(std::pair(propName, propValue));
645                 xmlFree(xmlPropValue);
646             } else {
647                 THERMAL_HILOGE(COMP_SVC, "prop [%{public}s] value is null", propName.c_str());
648                 return false;
649             }
650             policyAction.isProp = true;
651         }
652         policyConfig.policyActionList.push_back(policyAction);
653     }
654     return true;
655 }
656 
ParseIdleNode(const xmlNodePtr & node)657 bool ThermalSrvConfigParser::ParseIdleNode(const xmlNodePtr& node)
658 {
659     IdleState idleState;
660     for (xmlNodePtr subNode = node->xmlChildrenNode; subNode != nullptr; subNode = subNode->next) {
661         if (!xmlStrcmp(subNode->name, BAD_CAST"thermallevel")) {
662             xmlChar* value = xmlNodeGetContent(subNode);
663             if (value != nullptr) {
664                 StrToInt(reinterpret_cast<char*>(value), idleState.level);
665                 xmlFree(value);
666             }
667         } else if (!xmlStrcmp(subNode->name, BAD_CAST"soc")) {
668             xmlChar* value = xmlNodeGetContent(subNode);
669             if (value != nullptr) {
670                 StrToInt(reinterpret_cast<char*>(value), idleState.soc);
671                 xmlFree(value);
672             }
673         } else if (!xmlStrcmp(subNode->name, BAD_CAST"charging")) {
674             xmlChar* value = xmlNodeGetContent(subNode);
675             if (value != nullptr) {
676                 StrToInt(reinterpret_cast<char*>(value), idleState.charging);
677                 xmlFree(value);
678             }
679         } else if (!xmlStrcmp(subNode->name, BAD_CAST"current")) {
680             xmlChar* value = xmlNodeGetContent(subNode);
681             if (value != nullptr) {
682                 StrToInt(reinterpret_cast<char*>(value), idleState.current);
683                 xmlFree(value);
684             }
685         } else {
686             THERMAL_HILOGD(COMP_SVC, "not supported node, name=%{public}s", subNode->name);
687         }
688     }
689     THERMAL_HILOGI(COMP_SVC, "level=%{public}d, soc=%{public}d, charging=%{public}d, current=%{public}d",
690                    idleState.level, idleState.soc, idleState.charging, idleState.current);
691     auto tms = ThermalService::GetInstance();
692     tms->GetStateMachineObj()->SetIdleStateConfig(idleState);
693     return true;
694 }
695 
ParseFanNode(const xmlNodePtr & node)696 bool ThermalSrvConfigParser::ParseFanNode(const xmlNodePtr &node)
697 {
698     FanFaultInfoMap fanFaultInfoMap;
699     xmlNodePtr cur = node->xmlChildrenNode;
700 
701     while (cur != nullptr) {
702         if (xmlStrcmp(cur->name, BAD_CAST"sensor_cluster")) {
703             cur = cur->next;
704             continue;
705         }
706         xmlChar* xmlSensor = xmlGetProp(cur, BAD_CAST"sensor");
707         if (xmlSensor == nullptr) {
708             return false;
709         }
710         std::vector<std::string> sensors;
711         std::string sensorStr = reinterpret_cast<char*>(xmlSensor);
712         StringOperation::SplitString(sensorStr, sensors, ",");
713         xmlFree(xmlSensor);
714         if (!ParseFanFaultInfo(cur, sensors, fanFaultInfoMap)) {
715             THERMAL_HILOGE(COMP_SVC, "ParseFanFaultInfo failed");
716             return false;
717         }
718         cur = cur->next;
719     }
720 
721     auto tms = ThermalService::GetInstance();
722     tms->GetFanFaultDetect()->SetFaultInfoMap(fanFaultInfoMap);
723     return true;
724 }
725 
ParseFanFaultInfo(const xmlNodePtr & node,std::vector<std::string> & sensors,FanFaultInfoMap & fanFaultInfoMap)726 bool ThermalSrvConfigParser::ParseFanFaultInfo(const xmlNodePtr& node,
727     std::vector<std::string> &sensors, FanFaultInfoMap &fanFaultInfoMap)
728 {
729     uint32_t sensorNum = sensors.size();
730     xmlNodePtr cur = node->xmlChildrenNode;
731 
732     while (cur != nullptr) {
733         if (xmlStrcmp(cur->name, BAD_CAST"item")) {
734             cur = cur->next;
735             continue;
736         }
737         FanSensorInfo fanSensorInfo;
738         xmlChar* xmlFault = xmlGetProp(cur, BAD_CAST"fault");
739         if (xmlFault == nullptr) {
740             return false;
741         }
742         std::string faultStr = reinterpret_cast<char*>(xmlFault);
743         xmlFree(xmlFault);
744         int32_t faultNum;
745         StrToInt(faultStr, faultNum);
746         xmlChar* xmlThreshold = xmlGetProp(cur, BAD_CAST"threshold");
747         if (xmlThreshold == nullptr) {
748             return false;
749         }
750         std::string thresholdStr = reinterpret_cast<char*>(xmlThreshold);
751         std::vector<std::string> thresholds;
752         StringOperation::SplitString(thresholdStr, thresholds, ",");
753         xmlFree(xmlThreshold);
754         if (thresholds.size() != sensorNum) {
755             return false;
756         }
757         for (uint32_t i = 0; i < sensorNum; i++) {
758             int32_t value;
759             StrToInt(thresholds[i], value);
760             fanSensorInfo.insert(std::make_pair(sensors[i], value));
761         }
762         fanFaultInfoMap.insert(std::make_pair(faultNum, fanSensorInfo));
763         cur = cur->next;
764     }
765 
766     return true;
767 }
768 } // namespace PowerMgr
769 } // namespace OHOS
770