• 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_provider.h"
17 
18 #include <cerrno>
19 #include <thread>
20 #include <unistd.h>
21 #include <sys/socket.h>
22 #include <sys/epoll.h>
23 #include <sys/timerfd.h>
24 #include <linux/netlink.h>
25 
26 #include "thermal_kernel_config_file.h"
27 #include "thermal_common.h"
28 
29 namespace OHOS {
30 namespace PowerMgr {
31 namespace {
32 const int ERR_INVALID_FD = -1;
33 const int32_t MS_PER_SECOND = 1000;
34 }
35 
InitProvider()36 bool ThermalSensorProvider::InitProvider()
37 {
38     int32_t ret = -1;
39 
40     ret = InitThermalZoneSysfs();
41     if (ret != ERR_OK) {
42         THERMAL_HILOGE(FEATURE_PROTECTOR, "failed to get path info.");
43         return false;
44     }
45 
46     StartThread(this);
47     return true;
48 }
49 
GetThermalSensorInfo()50 void ThermalSensorProvider::GetThermalSensorInfo()
51 {
52     THERMAL_HILOGD(FEATURE_PROTECTOR, "Enter");
53     int32_t ret = -1;
54 
55     ret = ParseThermalZoneInfo();
56     if (ret != ERR_OK) {
57         THERMAL_HILOGE(FEATURE_PROTECTOR, "failed to thermal zone info");
58         return;
59     }
60     tzInfoList_ = tzInfoAcaualEvent_.info;
61 
62     THERMAL_HILOGI(FEATURE_PROTECTOR, "size = %{public}zu", tzInfoList_.size());
63 
64     for (auto type : intervalMap_) {
65         THERMAL_HILOGI(FEATURE_PROTECTOR, "configType = %{public}s", type.first.c_str());
66     }
67 
68     for (auto iter = tzInfoList_.begin(); iter != tzInfoList_.end(); iter++) {
69         THERMAL_HILOGD(FEATURE_PROTECTOR, "type = %{public}s", iter->type.c_str());
70         THERMAL_HILOGD(FEATURE_PROTECTOR, "temp = %{public}d", iter->temp);
71         for (auto intervalIter = intervalMap_.begin(); intervalIter != intervalMap_.end(); intervalIter++) {
72             if (iter->type.find(intervalIter->first) != std::string::npos) {
73                 THERMAL_HILOGI(FEATURE_PROTECTOR, "success to find type");
74                 typeTempMap_.insert(std::make_pair(intervalIter->first, iter->temp));
75             }
76         }
77     }
78 }
79 
SetIntervalMap(IntervalMap & intervalMap)80 void ThermalSensorProvider::SetIntervalMap(IntervalMap &intervalMap)
81 {
82     intervalMap_ = intervalMap;
83 }
84 
RegisterTask(NotifyTask task)85 void ThermalSensorProvider::RegisterTask(NotifyTask task)
86 {
87     notify_ = task;
88 }
89 
NotifyPolicy()90 void ThermalSensorProvider::NotifyPolicy()
91 {
92     THERMAL_HILOGD(FEATURE_PROTECTOR, "Enter");
93     GetThermalSensorInfo();
94     for (auto info : typeTempMap_) {
95         THERMAL_HILOGD(FEATURE_PROTECTOR, "type = %{public}s, temp = %{public}d",
96             info.first.c_str(), info.second);
97     }
98     notify_(typeTempMap_);
99 }
100 
InitProviderTimer()101 int32_t ThermalSensorProvider::InitProviderTimer()
102 {
103     THERMAL_HILOGD(FEATURE_PROTECTOR, "Enter");
104     int32_t ret = -1;
105     epFd_ = epoll_create1(EPOLL_CLOEXEC);
106 
107     ret = CreateProviderFd();
108     if (ret != ERR_OK) {
109         THERMAL_HILOGE(FEATURE_PROTECTOR, "failed to create polling fd");
110         return ret;
111     }
112     return ERR_OK;
113 }
114 
GetTypeInterval()115 void ThermalSensorProvider::GetTypeInterval()
116 {
117     for (auto iter : intervalMap_) {
118         interval_ = iter.second;
119     }
120 }
121 
CreateProviderFd()122 int32_t ThermalSensorProvider::CreateProviderFd()
123 {
124     timerFd_ = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
125     if (timerFd_ == ERR_INVALID_FD) {
126         THERMAL_HILOGE(FEATURE_PROTECTOR, "epoll create failed, epFd_ is invalid");
127         return ERR_INVALID_FD;
128     }
129     GetTypeInterval();
130     THERMAL_HILOGD(FEATURE_PROTECTOR, "interval_ is %{public}d", interval_);
131     SetTimerInterval(interval_, timerFd_);
132     fcntl(timerFd_, F_SETFL, O_NONBLOCK);
133     callbackHandler_.insert(std::make_pair(timerFd_, &ThermalSensorProvider::TimerProviderCallback));
134     if (RegisterCallback(timerFd_, EVENT_TIMER_FD, epFd_)) {
135         THERMAL_HILOGE(FEATURE_PROTECTOR, "register Timer event failed");
136     }
137     THERMAL_HILOGD(FEATURE_PROTECTOR, "Exit");
138     return ERR_OK;
139 }
140 
TimerProviderCallback(void * service)141 void ThermalSensorProvider::TimerProviderCallback(void *service)
142 {
143     THERMAL_HILOGD(FEATURE_PROTECTOR, "Enter");
144     unsigned long long timers;
145 
146     if (read(timerFd_, &timers, sizeof(timers)) == -1) {
147         THERMAL_HILOGE(FEATURE_PROTECTOR, "read timerFd_ failed");
148         return;
149     }
150     NotifyPolicy();
151     return;
152 }
153 
SetTimerInterval(int interval,int32_t timerfd)154 void ThermalSensorProvider::SetTimerInterval(int interval, int32_t timerfd)
155 {
156     THERMAL_HILOGD(FEATURE_PROTECTOR, "start SetTimerInterval: %{public}d", timerfd);
157     struct itimerspec itval;
158 
159     if (timerfd == ERR_INVALID_FD) {
160         return;
161     }
162     timerInterval_ = interval;
163     if (interval < 0) {
164         interval = 0;
165     }
166 
167     itval.it_interval.tv_sec = interval / MS_PER_SECOND;
168     itval.it_interval.tv_nsec = 0;
169     itval.it_value.tv_sec = interval / MS_PER_SECOND;
170     itval.it_value.tv_nsec = 0;
171     if (timerfd_settime(timerfd, 0, &itval, nullptr) == -1) {
172         THERMAL_HILOGE(FEATURE_PROTECTOR, "timer failed.");
173     }
174     THERMAL_HILOGD(FEATURE_PROTECTOR, "Exit");
175 }
176 
RegisterCallback(const int fd,const EventType et,int32_t epfd)177 int32_t ThermalSensorProvider::RegisterCallback(const int fd, const EventType et, int32_t epfd)
178 {
179     THERMAL_HILOGD(FEATURE_PROTECTOR, "Enter");
180     struct epoll_event ev;
181 
182     ev.events = EPOLLIN;
183     if (et == EVENT_TIMER_FD) {
184         ev.events |= EPOLLWAKEUP;
185     }
186     THERMAL_HILOGI(FEATURE_PROTECTOR, "epfd: %{public}d, fd: %{public}d", epfd, fd);
187     ev.data.ptr = reinterpret_cast<void*>(this);
188     ev.data.fd = fd;
189     if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
190         THERMAL_HILOGE(FEATURE_PROTECTOR, "epoll_ctl failed, error num =%{public}d", errno);
191         return -1;
192     }
193     THERMAL_HILOGD(FEATURE_PROTECTOR, "Exit");
194     return ERR_OK;
195 }
196 
LoopingThreadEntry(void * arg,int32_t epfd)197 int32_t ThermalSensorProvider::LoopingThreadEntry(void *arg, int32_t epfd)
198 {
199     size_t eventct = callbackHandler_.size();
200     struct epoll_event events[eventct];
201     THERMAL_HILOGD(FEATURE_PROTECTOR, "epfd: %{public}d, eventct: %{public}zu", epfd, eventct);
202     while (true) {
203         int32_t nevents = epoll_wait(epfd, events, eventct, -1);
204         if (nevents == -1) {
205             continue;
206         }
207         for (int n = 0; n < nevents; ++n) {
208             if (events[n].data.ptr) {
209                 ThermalSensorProvider *func = const_cast<ThermalSensorProvider *>(this);
210                 (callbackHandler_.find(events[n].data.fd)->second)(func, arg);
211             }
212         }
213     }
214 }
215 
Run(void * service,int32_t epfd)216 void ThermalSensorProvider::Run(void *service, int32_t epfd)
217 {
218     std::make_unique<std::thread>(&ThermalSensorProvider::LoopingThreadEntry, this, service, epfd)->join();
219 }
220 
StartThread(void * service)221 void ThermalSensorProvider::StartThread(void *service)
222 {
223     THERMAL_HILOGD(FEATURE_PROTECTOR, "Enter");
224     int ret = -1;
225     ret = InitProviderTimer();
226     if (ret != ERR_OK) {
227         THERMAL_HILOGE(FEATURE_PROTECTOR, "init Timer failed, ret: %{public}d", ret);
228         return;
229     }
230     Run(service, epFd_);
231     while (true) {
232         pause();
233     }
234     THERMAL_HILOGD(FEATURE_PROTECTOR, "Exit");
235 }
236 } // namespace PowerMgr
237 } // namespace OHOS
238