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