• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_sensor_provision.h"
17 
18 #include <climits>
19 #include <cerrno>
20 #include <cstdio>
21 #include <cstring>
22 #include <dirent.h>
23 #include <iostream>
24 #include <vector>
25 #include <thread>
26 #include <securec.h>
27 #include <string>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <sys/epoll.h>
31 #include <sys/timerfd.h>
32 #include <unistd.h>
33 
34 #include "thermal_kernel_config_file.h"
35 #include "thermal_common.h"
36 #include "thermal_kernel_service.h"
37 
38 namespace OHOS {
39 namespace PowerMgr {
40 namespace {
41 constexpr int32_t MAX_BUFF_SIZE = 128;
42 constexpr int32_t MAX_SYSFS_SIZE = 128;
43 constexpr uint32_t ARG_0 = 0;
44 constexpr int32_t NUM_ZERO = 0;
45 const std::string THERMAL_SYSFS = "/sys/devices/virtual/thermal";
46 const std::string THERMAL_ZONE_DIR_NAME = "thermal_zone%d";
47 const std::string COOLING_DEVICE_DIR_NAME = "cooling_device%d";
48 const std::string THERMAL_ZONE_DIR_PATH = "/sys/class/thermal/%s";
49 const std::string THERMAL_TEMPERATURE_PATH = "/sys/class/thermal/%s/temp";
50 const std::string THEERMAL_TYPE_PATH = "/sys/class/thermal/%s/type";
51 const std::string CDEV_DIR_NAME = "cooling_device";
52 const std::string THERMAL_ZONE_TEMP_PATH_NAME = "/sys/class/thermal/thermal_zone%d/temp";
53 auto &g_service = ThermalKernelService::GetInstance();
54 }
55 
InitProvision()56 bool ThermalSensorProvision::InitProvision()
57 {
58     int32_t ret = ParseThermalZoneInfo();
59     if (ret != NUM_ZERO) {
60         return false;
61     }
62     return true;
63 }
64 
ReadThermalSysfsToBuff(const char * path,char * buf,size_t size) const65 int32_t ThermalSensorProvision::ReadThermalSysfsToBuff(const char* path, char* buf, size_t size) const
66 {
67     int32_t ret = ReadSysfsFile(path, buf, size);
68     if (ret != ERR_OK) {
69         THERMAL_HILOGW(FEATURE_PROTECTOR, "read path %{private}s failed, ret: %{public}d", path, ret);
70         return ret;
71     }
72 
73     return ERR_OK;
74 }
75 
ReadSysfsFile(const char * path,char * buf,size_t size) const76 int32_t ThermalSensorProvision::ReadSysfsFile(const char* path, char* buf, size_t size) const
77 {
78     int32_t readSize;
79     int32_t fd = open(path, O_RDONLY);
80     if (fd < NUM_ZERO) {
81         THERMAL_HILOGE(FEATURE_PROTECTOR, "failed to open %{public}s", path);
82         return ERR_INVALID_OPERATION;
83     }
84 
85     readSize = read(fd, buf, size - 1);
86     if (readSize < NUM_ZERO) {
87         THERMAL_HILOGE(FEATURE_PROTECTOR, "failed to read %{public}s", path);
88         close(fd);
89         return ERR_INVALID_OPERATION;
90     }
91 
92     buf[readSize] = '\0';
93     Trim(buf);
94     close(fd);
95 
96     return ERR_OK;
97 }
98 
Trim(char * str) const99 inline void ThermalSensorProvision::Trim(char* str) const
100 {
101     if (str == nullptr) {
102         return;
103     }
104 
105     str[strcspn(str, "\n")] = 0;
106 }
107 
FormatThermalSysfsPaths(struct ThermalSysfsPathInfo * pTSysPathInfo)108 void ThermalSensorProvision::FormatThermalSysfsPaths(struct ThermalSysfsPathInfo *pTSysPathInfo)
109 {
110     // Format Paths for thermal path
111     FormatThermalPaths(pTSysPathInfo->thermalZonePath, sizeof(pTSysPathInfo->thermalZonePath),
112         THERMAL_ZONE_DIR_PATH.c_str(), pTSysPathInfo->name);
113     // Format paths for thermal zone node
114     tzSysPathInfo_.name = pTSysPathInfo->name;
115     FormatThermalPaths(tzSysPathInfo_.tempPath, sizeof(tzSysPathInfo_.tempPath),
116         THERMAL_TEMPERATURE_PATH.c_str(), pTSysPathInfo->name);
117 
118     FormatThermalPaths(tzSysPathInfo_.typePath, sizeof(tzSysPathInfo_.typePath),
119         THEERMAL_TYPE_PATH.c_str(), pTSysPathInfo->name);
120 
121     THERMAL_HILOGI(FEATURE_PROTECTOR, "temp path: %{public}s, type path: %{public}s ",
122         tzSysPathInfo_.tempPath, tzSysPathInfo_.typePath);
123 
124     tzSysPathInfo_.fd = pTSysPathInfo->fd;
125     lTzSysPathInfo_.push_back(tzSysPathInfo_);
126 }
127 
FormatThermalPaths(char * path,size_t size,const char * format,const char * name)128 void ThermalSensorProvision::FormatThermalPaths(char *path, size_t size, const char *format, const char* name)
129 {
130     if (snprintf_s(path, PATH_MAX, size - 1, format, name) < NUM_ZERO) {
131         THERMAL_HILOGW(FEATURE_PROTECTOR, "failed to format path of %{public}s", name);
132     }
133 }
134 
InitThermalZoneSysfs()135 int32_t ThermalSensorProvision::InitThermalZoneSysfs()
136 {
137     DIR *dir = NULL;
138     struct dirent *entry = NULL;
139     int32_t index = 0;
140     int32_t id = 0;
141 
142     dir = opendir(THERMAL_SYSFS.c_str());
143     if (dir == nullptr) {
144         THERMAL_HILOGE(FEATURE_PROTECTOR, "cannot open thermal zone path");
145         return ERR_INVALID_VALUE;
146     }
147 
148     while (true) {
149         entry = readdir(dir);
150         if (entry == nullptr) {
151             break;
152         }
153 
154         if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
155             continue;
156         }
157 
158         if (strncmp(entry->d_name, CDEV_DIR_NAME.c_str(), CDEV_DIR_NAME.size()) == 0) {
159             continue;
160         }
161 
162         if (entry->d_type == DT_DIR || entry->d_type == DT_LNK) {
163             struct ThermalSysfsPathInfo sysfsInfo = {0};
164             sysfsInfo.name = entry->d_name;
165             THERMAL_HILOGI(FEATURE_PROTECTOR, "init sysfs info of %{public}s", sysfsInfo.name);
166             int32_t ret = sscanf_s(sysfsInfo.name, THERMAL_ZONE_DIR_NAME.c_str(), &id);
167             if (ret < ARG_0) {
168                 return ret;
169             }
170 
171             THERMAL_HILOGI(FEATURE_PROTECTOR, "Sensor %{public}s found at tz: %{public}d", sysfsInfo.name, id);
172             sysfsInfo.fd = id;
173             if (index > MAX_SYSFS_SIZE) {
174                 THERMAL_HILOGE(FEATURE_PROTECTOR, "too many plugged types");
175                 break;
176             }
177 
178             FormatThermalSysfsPaths(&sysfsInfo);
179             index++;
180         }
181     }
182     closedir(dir);
183     return ERR_OK;
184 }
185 
ParseThermalZoneInfo()186 int32_t ThermalSensorProvision::ParseThermalZoneInfo()
187 {
188     char bufType[MAX_BUFF_SIZE] = {0};
189     int32_t ret = InitThermalZoneSysfs();
190     if (ret != ERR_OK) {
191         THERMAL_HILOGE(FEATURE_PROTECTOR, "failed to get path info.");
192         return false;
193     }
194 
195     std::map<std::string, std::string> tzPathMap;
196     if (!lTzSysPathInfo_.empty()) {
197         for (auto iter = lTzSysPathInfo_.begin(); iter != lTzSysPathInfo_.end(); iter++) {
198             int32_t ret = ReadThermalSysfsToBuff(iter->typePath, bufType, sizeof(bufType));
199             if (ret != NUM_ZERO) {
200                 THERMAL_HILOGE(FEATURE_PROTECTOR, "failed to read thermal zone type");
201                 return ret;
202             }
203             std::string tzType = bufType;
204             tzPathMap.insert(std::make_pair(tzType, iter->tempPath));
205         }
206     }
207     auto tzInfoMap = g_service.GetPolicy()->GetThermalZoneMap();
208     if (tzInfoMap.empty()) {
209         return ERR_INVALID_VALUE;
210     }
211     for (auto tzIter : tzInfoMap) {
212         auto typeIter = tzPathMap.find(tzIter.first);
213         if (typeIter != tzPathMap.end()) {
214             tzIter.second->SetPath(typeIter->second);
215         }
216     }
217     return ERR_OK;
218 }
219 
ReportThermalZoneData(int32_t reportTime,std::vector<int32_t> & multipleList)220 void ThermalSensorProvision::ReportThermalZoneData(int32_t reportTime, std::vector<int32_t> &multipleList)
221 {
222     char tempBuf[MAX_BUFF_SIZE] = {0};
223     typeTempMap_.clear();
224     multipleList.clear();
225 
226     auto tzInfoMap = g_service.GetPolicy()->GetThermalZoneMap();
227     if (tzInfoMap.empty()) {
228         return;
229     }
230 
231     for (auto sensorIter : tzInfoMap) {
232         int multiple = sensorIter.second->GetMultiple();
233         if (multiple == 0) {
234             continue;
235         }
236         int result = reportTime % multiple;
237         multipleList.push_back(multiple);
238         if (result == NUM_ZERO) {
239             if (sensorIter.second->GetPath().empty()) {
240                 continue;
241             }
242 
243             int32_t ret = ReadThermalSysfsToBuff(sensorIter.second->GetPath().c_str(), tempBuf, sizeof(tempBuf));
244             if (ret != NUM_ZERO) {
245                 continue;
246             }
247             int32_t temp = std::stoi(tempBuf);
248             typeTempMap_.insert(std::make_pair(sensorIter.first, temp));
249         }
250     }
251 }
252 
GetMaxCd()253 int32_t ThermalSensorProvision::GetMaxCd()
254 {
255     return g_service.GetPolicy()->GetMaxCd();
256 }
257 } // namespace PowerMgr
258 } // namespace OHOS
259