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_hdf_config.h"
17 
18 #include "thermal_hdf_utils.h"
19 #include "thermal_log.h"
20 #include "hdf_remote_service.h"
21 #include "osal_mem.h"
22 #include "string_ex.h"
23 
24 namespace OHOS {
25 namespace HDI {
26 namespace Thermal {
27 namespace V1_1 {
28 namespace {
29 const int32_t DEFAULT_POLLING_INTERVAL = 30000;
30 }
31 
GetInstance()32 ThermalHdfConfig& ThermalHdfConfig::GetInstance()
33 {
34     static ThermalHdfConfig instance;
35     return instance;
36 }
37 
ThermalHDIConfigInit(const std::string & path)38 int32_t ThermalHdfConfig::ThermalHDIConfigInit(const std::string& path)
39 {
40     if (!baseConfig_) {
41         baseConfig_ = std::make_shared<BaseInfoConfig>();
42     }
43     return ParseThermalHdiXMLConfig(path);
44 }
45 
ParseThermalHdiXMLConfig(const std::string & path)46 int32_t ThermalHdfConfig::ParseThermalHdiXMLConfig(const std::string& path)
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_HILOGW(COMP_HDI, "failed to read xml file");
52         return HDF_ERR_INVALID_OBJECT;
53     }
54 
55     auto rootNode = xmlDocGetRootElement(docPtr.get());
56     if (rootNode == nullptr) {
57         THERMAL_HILOGE(COMP_HDI, "failed to read root node");
58         return HDF_ERR_INVALID_OBJECT;
59     }
60 
61     if (!xmlStrcmp(rootNode->name, BAD_CAST"thermal")) {
62         xmlChar* xmlVersion = xmlGetProp(rootNode, BAD_CAST"version");
63         if (xmlVersion != nullptr) {
64             this->thermal_.version = std::string(reinterpret_cast<char*>(xmlVersion));
65             xmlFree(xmlVersion);
66             THERMAL_HILOGD(COMP_HDI, "version: %{public}s", this->thermal_.version.c_str());
67         }
68 
69         xmlChar* xmlProduct = xmlGetProp(rootNode, BAD_CAST"product");
70         if (xmlProduct != nullptr) {
71             this->thermal_.product = std::string(reinterpret_cast<char*>(xmlProduct));
72             xmlFree(xmlProduct);
73             THERMAL_HILOGD(COMP_HDI, "product: %{public}s", this->thermal_.product.c_str());
74         }
75     }
76 
77     for (auto node = rootNode->children; node; node = node->next) {
78         if (node == nullptr) {
79             continue;
80         }
81 
82         if (!xmlStrcmp(node->name, BAD_CAST"base")) {
83             ParseBaseNode(node);
84         } else if (!xmlStrcmp(node->name, BAD_CAST"polling")) {
85             ParsePollingNode(node);
86         } else if (!xmlStrcmp(node->name, BAD_CAST"tracing")) {
87             ParseTracingNode(node);
88         } else if (!xmlStrcmp(node->name, BAD_CAST"isolate")) {
89             ParseIsolateNode(node);
90         }
91     }
92     return HDF_SUCCESS;
93 }
94 
ParseBaseNode(xmlNodePtr node)95 void ThermalHdfConfig::ParseBaseNode(xmlNodePtr node)
96 {
97     auto cur = node->xmlChildrenNode;
98     std::vector<BaseItem> vBase;
99     while (cur != nullptr) {
100         BaseItem item;
101         xmlChar* xmlTag = xmlGetProp(cur, BAD_CAST"tag");
102         if (xmlTag != nullptr) {
103             item.tag = std::string(reinterpret_cast<char*>(xmlTag));
104             xmlFree(xmlTag);
105             THERMAL_HILOGD(COMP_HDI, "ParseBaseNode tag: %{public}s", item.tag.c_str());
106         }
107 
108         xmlChar* xmlValue = xmlGetProp(cur, BAD_CAST"value");
109         if (xmlValue != nullptr) {
110             item.value = std::string(reinterpret_cast<char*>(xmlValue));
111             xmlFree(xmlValue);
112             THERMAL_HILOGD(COMP_HDI, "ParseBaseNode value: %{public}s", item.value.c_str());
113         }
114 
115         vBase.push_back(item);
116         cur = cur->next;
117     }
118     baseConfig_->SetBase(vBase);
119 }
120 
GetXmlNodeName(xmlNodePtr node,std::string & defaultName)121 std::string ThermalHdfConfig::GetXmlNodeName(xmlNodePtr node, std::string &defaultName)
122 {
123     std::string name;
124     xmlChar* xmlName = xmlGetProp(node, BAD_CAST"name");
125     if (xmlName == nullptr) {
126         return defaultName;
127     }
128     name = std::string(reinterpret_cast<char*>(xmlName));
129     xmlFree(xmlName);
130 
131     return name;
132 }
133 
ParsePollingNode(xmlNodePtr node)134 void ThermalHdfConfig::ParsePollingNode(xmlNodePtr node)
135 {
136     std::string pollingDefaultName("thermal");
137     std::string pollingName = GetXmlNodeName(node, pollingDefaultName);
138     GroupMap groupMap;
139 
140     auto cur  = node->xmlChildrenNode;
141     while (cur != nullptr) {
142         std::shared_ptr<SensorInfoConfig> sensorInfo = std::make_shared<SensorInfoConfig>();
143         std::string groupDefaultName("actual");
144         std::string groupName = GetXmlNodeName(cur, groupDefaultName);
145         sensorInfo->SetGroupName(groupName);
146         THERMAL_HILOGD(COMP_HDI, "ParsePollingNode groupName: %{public}s", groupName.c_str());
147 
148         xmlChar* xmlInterval = xmlGetProp(cur, BAD_CAST"interval");
149         if (xmlInterval != nullptr) {
150             std::string strInterval = reinterpret_cast<char *>(xmlInterval);
151             int32_t interval = DEFAULT_POLLING_INTERVAL;
152             StrToInt(TrimStr(strInterval), interval);
153             xmlFree(xmlInterval);
154             THERMAL_HILOGD(COMP_HDI, "ParsePollingNode interval: %{public}d", interval);
155             sensorInfo->SetGroupInterval(interval);
156         }
157 
158         std::vector<XMLThermalZoneInfo> xmlTzInfoList;
159         std::vector<XMLThermalNodeInfo> xmlTnInfoList;
160         for (auto subNode = cur->children; subNode; subNode = subNode->next) {
161             if (!xmlStrcmp(subNode->name, BAD_CAST"thermal_zone")) {
162                 XMLThermalZoneInfo tz;
163                 GetThermalZoneNodeInfo(tz, subNode);
164                 THERMAL_HILOGI(COMP_HDI, "ParsePollingNode ParsePollingNodetztype: %{public}s, replace: %{public}s",
165                     tz.type.c_str(), tz.replace.c_str());
166                 xmlTzInfoList.push_back(tz);
167             } else if (!xmlStrcmp(subNode->name, BAD_CAST"thermal_node")) {
168                 XMLThermalNodeInfo tn;
169                 ParsePollingSubNode(subNode, tn);
170                 THERMAL_HILOGI(COMP_HDI, "ParsePollingNode tntype: %{public}s", tn.type.c_str());
171                 xmlTnInfoList.push_back(tn);
172             }
173         }
174         sensorInfo->SetXMLThermalZoneInfo(xmlTzInfoList);
175         sensorInfo->SetXMLThermalNodeInfo(xmlTnInfoList);
176         groupMap.insert(std::make_pair(groupName, sensorInfo));
177         cur = cur->next;
178     }
179 
180     pollingMap_.insert(std::make_pair(pollingName, groupMap));
181 }
182 
ParsePollingSubNode(xmlNodePtr node,XMLThermalNodeInfo & tn)183 void ThermalHdfConfig::ParsePollingSubNode(xmlNodePtr node, XMLThermalNodeInfo& tn)
184 {
185     DfxTraceInfo info;
186 
187     xmlChar* xmlType = xmlGetProp(node, BAD_CAST"type");
188     if (xmlType != nullptr) {
189         tn.type = std::string(reinterpret_cast<char*>(xmlType));
190         xmlFree(xmlType);
191     }
192 
193     xmlChar* xmlPath = xmlGetProp(node, BAD_CAST"path");
194     if (xmlPath != nullptr) {
195         tn.path = std::string(reinterpret_cast<char*>(xmlPath));
196         xmlFree(xmlPath);
197     }
198 }
199 
ParseTracingNode(xmlNodePtr node)200 void ThermalHdfConfig::ParseTracingNode(xmlNodePtr node)
201 {
202     xmlChar* xmlOutpath = xmlGetProp(node, BAD_CAST"outpath");
203     if (xmlOutpath != nullptr) {
204         if (strcmp(reinterpret_cast<char *>(xmlOutpath), "/data/log/thermal/thermal-log") == 0) {
205             this->traceConfig_.outPath = std::string(reinterpret_cast<char *>(xmlOutpath));
206             xmlFree(xmlOutpath);
207         } else {
208             THERMAL_HILOGE(COMP_HDI, "xmlOutpath is not /data/log/thermal/thermal-log");
209         }
210     }
211 
212     auto cur  = node->xmlChildrenNode;
213     while (cur != nullptr) {
214         ParseTracingSubNode(cur);
215         cur = cur->next;
216     }
217 }
218 
ParseTracingSubNode(xmlNodePtr node)219 void ThermalHdfConfig::ParseTracingSubNode(xmlNodePtr node)
220 {
221     std::string title;
222     DfxTraceInfo info;
223     std::string valuePath;
224 
225     for (auto subNode = node->children; subNode != nullptr; subNode = subNode->next) {
226         if (!xmlStrcmp(subNode->name, BAD_CAST"title")) {
227             xmlChar* titlePath = xmlGetProp(subNode, BAD_CAST"path");
228             if (titlePath != nullptr) {
229                 ThermalHdfUtils::ReadNode(
230                     std::string(reinterpret_cast<char*>(titlePath)), title);
231                 xmlFree(titlePath);
232             }
233 
234             xmlChar* titleName = xmlGetProp(subNode, BAD_CAST"name");
235             if (titleName != nullptr) {
236                 title = std::string(reinterpret_cast<char*>(titleName));
237                 xmlFree(titleName);
238             }
239         }
240 
241         if (!xmlStrcmp(subNode->name, BAD_CAST"value")) {
242             xmlChar* xmlValuePath = xmlGetProp(subNode, BAD_CAST"path");
243             if (xmlValuePath != nullptr) {
244                 valuePath = std::string(reinterpret_cast<char*>(xmlValuePath));
245                 xmlFree(xmlValuePath);
246             }
247         }
248     }
249 
250     info.title = title;
251     info.valuePath = valuePath;
252     traceInfo_.emplace_back(info);
253 
254     for (const auto& item : traceInfo_) {
255         THERMAL_HILOGD(COMP_HDI, "item.title = %{public}s", item.title.c_str());
256     }
257 }
258 
GetThermalZoneNodeInfo(XMLThermalZoneInfo & tz,const xmlNode * node)259 void ThermalHdfConfig::GetThermalZoneNodeInfo(XMLThermalZoneInfo& tz, const xmlNode* node)
260 {
261     xmlChar* xmlType = xmlGetProp(node, BAD_CAST"type");
262     if (xmlType != nullptr) {
263         tz.type = std::string(reinterpret_cast<char*>(xmlType));
264         xmlFree(xmlType);
265     }
266 
267     auto replace = xmlGetProp(node, BAD_CAST("replace"));
268     if (replace != nullptr) {
269         tz.replace = std::string(reinterpret_cast<char*>(replace));
270         tz.isReplace = true;
271         xmlFree(replace);
272     }
273 }
274 
ParseIsolateNode(xmlNodePtr node)275 void ThermalHdfConfig::ParseIsolateNode(xmlNodePtr node)
276 {
277     THERMAL_HILOGD(COMP_HDI, "in");
278     auto cur = node->xmlChildrenNode;
279     while (cur != nullptr) {
280         std::shared_ptr<IsolateInfoConfig> isolateInfo = std::make_shared<IsolateInfoConfig>();
281         std::string groupName;
282         xmlChar* xmlName = xmlGetProp(cur, BAD_CAST"name");
283         if (xmlName != nullptr) {
284             groupName = std::string(reinterpret_cast<char*>(xmlName));
285             xmlFree(xmlName);
286             isolateInfo->SetGroupName(groupName);
287             THERMAL_HILOGD(COMP_HDI, "groupName: %{public}s", groupName.c_str());
288         }
289 
290         std::vector<IsolateNodeInfo> xmlTnInfoList;
291         for (auto subNode = cur->children; subNode; subNode = subNode->next) {
292             if (!xmlStrcmp(subNode->name, BAD_CAST"thermal_node")) {
293                 IsolateNodeInfo tn;
294                 ParseIsolateSubNode(subNode, tn);
295                 xmlTnInfoList.push_back(tn);
296             }
297         }
298         isolateInfo->SetIsolateNodeInfo(xmlTnInfoList);
299         isolateInfoMap_.insert(std::make_pair(groupName, isolateInfo));
300         cur = cur->next;
301     }
302 }
303 
ParseIsolateSubNode(xmlNodePtr node,IsolateNodeInfo & tn)304 void ThermalHdfConfig::ParseIsolateSubNode(xmlNodePtr node, IsolateNodeInfo& tn)
305 {
306     xmlChar* xmlType = xmlGetProp(node, BAD_CAST"type");
307     if (xmlType != nullptr) {
308         tn.type = std::string(reinterpret_cast<char*>(xmlType));
309         THERMAL_HILOGD(COMP_HDI, "type: %{public}s", tn.type.c_str());
310         xmlFree(xmlType);
311     }
312 
313     xmlChar* xmlPath = xmlGetProp(node, BAD_CAST"path");
314     if (xmlPath != nullptr) {
315         tn.path = std::string(reinterpret_cast<char*>(xmlPath));
316         THERMAL_HILOGD(COMP_HDI, "path: %{public}s", tn.path.c_str());
317         xmlFree(xmlPath);
318     }
319 }
320 
GetIsolateCpuNodePath(bool isSim,const std::string & type,std::string & path)321 int32_t ThermalHdfConfig::GetIsolateCpuNodePath(bool isSim, const std::string &type, std::string &path)
322 {
323     std::string groupName = isSim ? "sim" : "actual";
324     THERMAL_HILOGI(COMP_HDI, "isSim %d, type %{public}s, groupName %{public}s", isSim, type.c_str(), groupName.c_str());
325 
326     auto mapIter = isolateInfoMap_.find(groupName);
327     if (mapIter == isolateInfoMap_.end()) {
328         THERMAL_HILOGE(COMP_HDI, "failed to get group %s config", groupName.c_str());
329         return HDF_FAILURE;
330     }
331 
332     std::vector<IsolateNodeInfo> nodeVector = mapIter->second->GetIsolateNodeInfo();
333     for (auto nodeIter : nodeVector) {
334         if (type == nodeIter.type) {
335             path = nodeIter.path;
336             THERMAL_HILOGI(COMP_HDI, "path %{public}s", path.c_str());
337             return HDF_SUCCESS;
338         }
339     }
340 
341     THERMAL_HILOGE(COMP_HDI, "failed to get type %{public}s path", type.c_str());
342     return HDF_FAILURE;
343 }
344 } // V1_1
345 } // Thermal
346 } // HDI
347 } // OHOS
348