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
24namespace OHOS {
25namespace HDI {
26namespace Thermal {
27namespace V1_1 {
28namespace {
29const int32_t DEFAULT_POLLING_INTERVAL = 30000;
30}
31
32ThermalHdfConfig& ThermalHdfConfig::GetInstance()
33{
34    static ThermalHdfConfig instance;
35    return instance;
36}
37
38int32_t ThermalHdfConfig::ThermalHDIConfigInit(const std::string& path)
39{
40    if (!baseConfig_) {
41        baseConfig_ = std::make_shared<BaseInfoConfig>();
42    }
43    return ParseThermalHdiXMLConfig(path);
44}
45
46int32_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
95void 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
121std::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
134void 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
183void 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
200void 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    THERMAL_HILOGI(COMP_HDI, "DfxTraceInfo number = %{public}zu", traceInfo_.size());
219}
220
221void ThermalHdfConfig::ParseTracingSubNode(xmlNodePtr node)
222{
223    DfxTraceInfo info;
224    std::string title;
225    std::string valuePath;
226
227    for (auto subNode = node->children; subNode != nullptr; subNode = subNode->next) {
228        if (!xmlStrcmp(subNode->name, BAD_CAST"title")) {
229            xmlChar* titlePath = xmlGetProp(subNode, BAD_CAST"path");
230            if (titlePath != nullptr) {
231                ThermalHdfUtils::ReadNode(std::string(reinterpret_cast<char*>(titlePath)), title);
232                xmlFree(titlePath);
233            }
234
235            xmlChar* titleName = xmlGetProp(subNode, BAD_CAST"name");
236            if (titleName != nullptr) {
237                title = std::string(reinterpret_cast<char*>(titleName));
238                xmlFree(titleName);
239            }
240        }
241
242        if (!xmlStrcmp(subNode->name, BAD_CAST"value")) {
243            xmlChar* xmlValuePath = xmlGetProp(subNode, BAD_CAST"path");
244            if (xmlValuePath != nullptr) {
245                valuePath = std::string(reinterpret_cast<char*>(xmlValuePath));
246                xmlFree(xmlValuePath);
247            }
248        }
249    }
250
251    info.title = title;
252    info.valuePath = valuePath;
253    traceInfo_.emplace_back(info);
254    THERMAL_HILOGD(
255        COMP_HDI, "traceInfo.title = %{public}s, traceInfo.valuePath = %{private}s", title.c_str(), valuePath.c_str());
256}
257
258void ThermalHdfConfig::GetThermalZoneNodeInfo(XMLThermalZoneInfo& tz, const xmlNode* node)
259{
260    xmlChar* xmlType = xmlGetProp(node, BAD_CAST"type");
261    if (xmlType != nullptr) {
262        tz.type = std::string(reinterpret_cast<char*>(xmlType));
263        xmlFree(xmlType);
264    }
265
266    auto replace = xmlGetProp(node, BAD_CAST("replace"));
267    if (replace != nullptr) {
268        tz.replace = std::string(reinterpret_cast<char*>(replace));
269        tz.isReplace = true;
270        xmlFree(replace);
271    }
272}
273
274void ThermalHdfConfig::ParseIsolateNode(xmlNodePtr node)
275{
276    THERMAL_HILOGD(COMP_HDI, "in");
277    auto cur = node->xmlChildrenNode;
278    while (cur != nullptr) {
279        std::shared_ptr<IsolateInfoConfig> isolateInfo = std::make_shared<IsolateInfoConfig>();
280        std::string groupName;
281        xmlChar* xmlName = xmlGetProp(cur, BAD_CAST"name");
282        if (xmlName != nullptr) {
283            groupName = std::string(reinterpret_cast<char*>(xmlName));
284            xmlFree(xmlName);
285            isolateInfo->SetGroupName(groupName);
286            THERMAL_HILOGD(COMP_HDI, "groupName: %{public}s", groupName.c_str());
287        }
288
289        std::vector<IsolateNodeInfo> xmlTnInfoList;
290        for (auto subNode = cur->children; subNode; subNode = subNode->next) {
291            if (!xmlStrcmp(subNode->name, BAD_CAST"thermal_node")) {
292                IsolateNodeInfo tn;
293                ParseIsolateSubNode(subNode, tn);
294                xmlTnInfoList.push_back(tn);
295            }
296        }
297        isolateInfo->SetIsolateNodeInfo(xmlTnInfoList);
298        isolateInfoMap_.insert(std::make_pair(groupName, isolateInfo));
299        cur = cur->next;
300    }
301}
302
303void ThermalHdfConfig::ParseIsolateSubNode(xmlNodePtr node, IsolateNodeInfo& tn)
304{
305    xmlChar* xmlType = xmlGetProp(node, BAD_CAST"type");
306    if (xmlType != nullptr) {
307        tn.type = std::string(reinterpret_cast<char*>(xmlType));
308        THERMAL_HILOGD(COMP_HDI, "type: %{public}s", tn.type.c_str());
309        xmlFree(xmlType);
310    }
311
312    xmlChar* xmlPath = xmlGetProp(node, BAD_CAST"path");
313    if (xmlPath != nullptr) {
314        tn.path = std::string(reinterpret_cast<char*>(xmlPath));
315        THERMAL_HILOGD(COMP_HDI, "path: %{public}s", tn.path.c_str());
316        xmlFree(xmlPath);
317    }
318}
319
320int32_t ThermalHdfConfig::GetIsolateCpuNodePath(bool isSim, const std::string &type, std::string &path)
321{
322    std::string groupName = isSim ? "sim" : "actual";
323    THERMAL_HILOGI(COMP_HDI, "isSim %d, type %{public}s, groupName %{public}s", isSim, type.c_str(), groupName.c_str());
324
325    auto mapIter = isolateInfoMap_.find(groupName);
326    if (mapIter == isolateInfoMap_.end()) {
327        THERMAL_HILOGE(COMP_HDI, "failed to get group %s config", groupName.c_str());
328        return HDF_FAILURE;
329    }
330
331    std::vector<IsolateNodeInfo> nodeVector = mapIter->second->GetIsolateNodeInfo();
332    for (auto nodeIter : nodeVector) {
333        if (type == nodeIter.type) {
334            path = nodeIter.path;
335            THERMAL_HILOGI(COMP_HDI, "path %{public}s", path.c_str());
336            return HDF_SUCCESS;
337        }
338    }
339
340    THERMAL_HILOGE(COMP_HDI, "failed to get type %{public}s path", type.c_str());
341    return HDF_FAILURE;
342}
343} // V1_1
344} // Thermal
345} // HDI
346} // OHOS
347