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