• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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_zone_manager.h"
17 
18 #include <cstdio>
19 #include <cstring>
20 #include <vector>
21 #include <string>
22 #include <iostream>
23 #include <dirent.h>
24 #include <fcntl.h>
25 #include <climits>
26 #include <securec.h>
27 #include <unistd.h>
28 #include <sys/types.h>
29 
30 #include "osal/osal_mem.h"
31 #include "thermal_log.h"
32 
33 using namespace std;
34 
35 namespace OHOS {
36 namespace HDI {
37 namespace Thermal {
38 namespace V1_0 {
39 namespace {
40 const int32_t MAX_BUFF_SIZE = 128;
41 const int32_t MAX_SYSFS_SIZE = 128;
42 const std::string THERMAL_SYSFS = "/sys/devices/virtual/thermal";
43 const std::string THERMAL_ZONE_DIR_NAME = "thermal_zone%d";
44 const std::string COOLING_DEVICE_DIR_NAME = "cooling_device%d";
45 const std::string THERMAL_ZONE_DIR_PATH = "/sys/class/thermal/%s";
46 const std::string THERMAL_TEMPERATURE_PATH = "/sys/class/thermal/%s/temp";
47 const std::string THEERMAL_TYPE_PATH = "/sys/class/thermal/%s/type";
48 const std::string CDEV_DIR_NAME = "cooling_device";
49 const std::string THERMAL_ZONE_TEMP_PATH_NAME = "/sys/class/thermal/thermal_zone%d/temp";
50 const uint32_t ARG_0 = 0;
51 const int32_t NUM_ZERO = 0;
52 }
53 
FormatThermalPaths(char * path,size_t size,const char * format,const char * name)54 void ThermalZoneManager::FormatThermalPaths(char *path, size_t size, const char *format, const char* name)
55 {
56     if (snprintf_s(path, PATH_MAX, size - 1, format, name) < HDF_SUCCESS) {
57         THERMAL_HILOGW(COMP_HDI, "failed to format path of %{public}s", name);
58     }
59 }
60 
FormatThermalSysfsPaths(struct ThermalSysfsPathInfo * pTSysPathInfo)61 void ThermalZoneManager::FormatThermalSysfsPaths(struct ThermalSysfsPathInfo *pTSysPathInfo)
62 {
63     // Format Paths for thermal path
64     FormatThermalPaths(pTSysPathInfo->thermalZonePath, sizeof(pTSysPathInfo->thermalZonePath),
65         THERMAL_ZONE_DIR_PATH.c_str(), pTSysPathInfo->name);
66     // Format paths for thermal zone node
67     tzSysPathInfo_.name = pTSysPathInfo->name;
68     FormatThermalPaths(tzSysPathInfo_.temperturePath, sizeof(tzSysPathInfo_.temperturePath),
69         THERMAL_TEMPERATURE_PATH.c_str(), pTSysPathInfo->name);
70 
71     FormatThermalPaths(tzSysPathInfo_.typePath, sizeof(tzSysPathInfo_.typePath),
72         THEERMAL_TYPE_PATH.c_str(), pTSysPathInfo->name);
73 
74     tzSysPathInfo_.fd = pTSysPathInfo->fd;
75     lTzSysPathInfo_.push_back(tzSysPathInfo_);
76 }
77 
InitThermalZoneSysfs()78 int32_t ThermalZoneManager::InitThermalZoneSysfs()
79 {
80     DIR *dir = NULL;
81     struct dirent *entry = NULL;
82     int32_t index = 0;
83     int32_t id = 0;
84 
85     dir = opendir(THERMAL_SYSFS.c_str());
86     if (dir == NULL) {
87         THERMAL_HILOGE(COMP_HDI, "cannot open thermal zone path");
88         return HDF_ERR_IO;
89     }
90 
91     while (true) {
92         entry = readdir(dir);
93         if (entry == NULL) {
94             break;
95         }
96 
97         if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
98             continue;
99         }
100 
101         if (strncmp(entry->d_name, CDEV_DIR_NAME.c_str(), CDEV_DIR_NAME.size()) == 0) {
102             continue;
103         }
104 
105         if (entry->d_type == DT_DIR || entry->d_type == DT_LNK) {
106             struct ThermalSysfsPathInfo sysfsInfo = {0};
107             sysfsInfo.name = entry->d_name;
108             int32_t ret = sscanf_s(sysfsInfo.name, THERMAL_ZONE_DIR_NAME.c_str(), &id);
109             if (ret < HDF_SUCCESS) {
110                 return ret;
111             }
112 
113             sysfsInfo.fd = id;
114             if (index > MAX_SYSFS_SIZE) {
115                 THERMAL_HILOGE(COMP_HDI, "too many plugged types");
116                 break;
117             }
118 
119             FormatThermalSysfsPaths(&sysfsInfo);
120             index++;
121         }
122     }
123     closedir(dir);
124     return HDF_SUCCESS;
125 }
126 
Trim(char * str) const127 inline void ThermalZoneManager::Trim(char* str) const
128 {
129     if (str == nullptr) {
130         return;
131     }
132 
133     str[strcspn(str, "\n")] = 0;
134 }
135 
ReadSysfsFile(const char * path,char * buf,size_t size) const136 int32_t ThermalZoneManager::ReadSysfsFile(const char* path, char* buf, size_t size) const
137 {
138     int32_t readSize;
139     int32_t fd = open(path, O_RDONLY);
140     if (fd < NUM_ZERO) {
141         THERMAL_HILOGE(COMP_HDI, "failed to open %{public}s", path);
142         return HDF_ERR_IO;
143     }
144 
145     readSize = read(fd, buf, size - 1);
146     if (readSize < NUM_ZERO) {
147         THERMAL_HILOGE(COMP_HDI, "failed to read %{public}s", path);
148         close(fd);
149         return HDF_ERR_IO;
150     }
151 
152     buf[readSize] = '\0';
153     Trim(buf);
154     close(fd);
155 
156     return HDF_SUCCESS;
157 }
158 
ReadThermalSysfsToBuff(const char * path,char * buf,size_t size) const159 int32_t ThermalZoneManager::ReadThermalSysfsToBuff(const char* path, char* buf, size_t size) const
160 {
161     int32_t ret = ReadSysfsFile(path, buf, size);
162     if (ret != HDF_SUCCESS) {
163         THERMAL_HILOGW(COMP_HDI, "read path %{private}s failed, ret: %{public}d", path, ret);
164         return ret;
165     }
166 
167     return HDF_SUCCESS;
168 }
169 
ParseThermalZoneInfo()170 int32_t ThermalZoneManager::ParseThermalZoneInfo()
171 {
172     int32_t ret;
173     char bufType[MAX_BUFF_SIZE] = {0};
174     THERMAL_HILOGD(COMP_HDI, "start to parse thermal zone");
175 
176     ret = InitThermalZoneSysfs();
177     if (ret != HDF_SUCCESS) {
178         THERMAL_HILOGE(COMP_HDI, "failed to init thermal zone node");
179     }
180     std::map<std::string, std::string> tzPathMap;
181     if (!lTzSysPathInfo_.empty()) {
182         for (auto iter = lTzSysPathInfo_.begin(); iter != lTzSysPathInfo_.end(); iter++) {
183             ret = ReadThermalSysfsToBuff(iter->typePath, bufType, sizeof(bufType));
184             if (ret != HDF_SUCCESS) {
185                 THERMAL_HILOGE(COMP_HDI, "failed to read thermal zone type");
186                 return ret;
187             }
188             std::string tzType = bufType;
189             tzPathMap.insert(std::make_pair(tzType, iter->temperturePath));
190         }
191     }
192     return UpdateThermalZoneData(tzPathMap);
193 }
194 
UpdateThermalZoneData(std::map<std::string,std::string> & tzPathMap)195 int32_t ThermalZoneManager::UpdateThermalZoneData(std::map<std::string, std::string> &tzPathMap)
196 {
197     for (auto sensorIter : sensorTypeMap_) {
198         auto tzInfoList = sensorIter.second->GetXMLThermalZoneInfo();
199         auto tnInfoList = sensorIter.second->GetXMLThermalNodeInfo();
200         for (auto tzIter : tzInfoList) {
201             if (tzPathMap.empty()) {
202                 break;
203             }
204             auto typeIter = tzPathMap.find(tzIter.type);
205             if (typeIter != tzPathMap.end()) {
206                 ReportedThermalData data;
207                 if (tzIter.isReplace) {
208                     data.type = tzIter.isReplace;
209                 } else {
210                     data.type = tzIter.type;
211                 }
212                 data.tempPath = typeIter->second;
213                 sensorIter.second->thermalDataList_.push_back(data);
214             }
215         }
216         for (auto tnIter : tnInfoList) {
217             ReportedThermalData data;
218             data.type = tnIter.type;
219             if (access(tnIter.path.c_str(), 0) == NUM_ZERO) {
220                 THERMAL_HILOGD(COMP_HDI, "This directory already exists.");
221                 data.tempPath = tnIter.path;
222             }
223             sensorIter.second->thermalDataList_.push_back(data);
224         }
225     }
226     return HDF_SUCCESS;
227 }
228 
ClearThermalZoneInfo()229 void ThermalZoneManager::ClearThermalZoneInfo()
230 {
231     if (!tzInfoList_.empty()) {
232         tzInfoList_.clear();
233     } else {
234         return;
235     }
236 }
237 
CalculateMaxCd()238 void ThermalZoneManager::CalculateMaxCd()
239 {
240     sensorTypeMap_ = ThermalHdfConfig::GetInsance().GetSensorTypeMap();
241     if (sensorTypeMap_.empty()) {
242         THERMAL_HILOGE(COMP_HDI, "configed sensor info is empty");
243         return;
244     }
245 
246     std::vector<int32_t> intervalList;
247     if (!sensorTypeMap_.empty()) {
248         for (auto sensorIter : sensorTypeMap_) {
249             intervalList.push_back(sensorIter.second->GetInterval());
250         }
251     }
252     maxCd_ = GetIntervalCommonDivisor(intervalList);
253 }
254 
GetMaxCommonDivisor(int32_t a,int32_t b)255 int32_t ThermalZoneManager::GetMaxCommonDivisor(int32_t a, int32_t b)
256 {
257     if (b == 0) {
258         return NUM_ZERO;
259     }
260 
261     if (a % b == 0) {
262         return b;
263     } else {
264         return GetMaxCommonDivisor(b, a % b);
265     }
266 }
267 
GetIntervalCommonDivisor(std::vector<int32_t> intervalList)268 int32_t ThermalZoneManager::GetIntervalCommonDivisor(std::vector<int32_t> intervalList)
269 {
270     if (intervalList.empty()) {
271         return ARG_0;
272     }
273 
274     int32_t count = intervalList.size();
275     int32_t commonDivisor = intervalList[0];
276     for (int32_t i = 1; i < count; i++) {
277         commonDivisor = GetMaxCommonDivisor(commonDivisor, intervalList[i]);
278     }
279     return commonDivisor;
280 }
281 
SetMultiples()282 void ThermalZoneManager::SetMultiples()
283 {
284     if (maxCd_ == NUM_ZERO) {
285         return;
286     }
287     for (auto sensorIter : sensorTypeMap_) {
288         sensorIter.second->multiple_ = (sensorIter.second->GetInterval()) / maxCd_;
289     }
290     ThermalHdfConfig::GetInsance().SetSensorTypeMap(sensorTypeMap_);
291 }
292 
ReportThermalZoneData(int32_t reportTime,std::vector<int32_t> & multipleList)293 void ThermalZoneManager::ReportThermalZoneData(int32_t reportTime, std::vector<int32_t> &multipleList)
294 {
295     char tempBuf[MAX_BUFF_SIZE] = {0};
296     if (sensorTypeMap_.empty()) {
297         return;
298     }
299 
300     int32_t ret;
301     tzInfoAcaualEvent_.info.clear();
302     multipleList.clear();
303     for (auto sensorIter : sensorTypeMap_) {
304         multipleList.push_back(sensorIter.second->multiple_);
305         if (sensorIter.second->multiple_ == NUM_ZERO) {
306             return;
307         }
308         if (reportTime % (sensorIter.second->multiple_) == NUM_ZERO) {
309             for (auto iter : sensorIter.second->thermalDataList_) {
310                 ThermalZoneInfo info;
311                 info.type = iter.type;
312                 ret = ReadThermalSysfsToBuff(iter.tempPath.c_str(), tempBuf, sizeof(tempBuf));
313                 if (ret != NUM_ZERO) {
314                     continue;
315                 }
316                 info.temp = ConvertInt(tempBuf);
317                 tzInfoAcaualEvent_.info.push_back(info);
318             }
319         }
320     }
321 }
322 } // V1_0
323 } // Thermal
324 } // HDI
325 } // OHOS
326