• 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_protector_timer.h"
17 #include <cerrno>
18 #include <thread>
19 #include <fcntl.h>
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 #include "thermal_common.h"
26 
27 namespace OHOS {
28 namespace PowerMgr {
29 namespace {
30 constexpr int32_t ERR_INVALID_FD = -1;
31 constexpr int32_t MS_PER_SECOND = 1000;
32 constexpr int32_t END_TIME = 2;
33 }
ThermalProtectorTimer(const std::shared_ptr<ThermalSensorProvision> & provision)34 ThermalProtectorTimer::ThermalProtectorTimer(const std::shared_ptr<ThermalSensorProvision>& provision)
35 {
36     provision_ = provision;
37 }
38 
RegisterTask(NotifyTask task)39 void ThermalProtectorTimer::RegisterTask(NotifyTask task)
40 {
41     notify_ = task;
42 }
43 
NotifyPolicy()44 void ThermalProtectorTimer::NotifyPolicy()
45 {
46     THERMAL_HILOGD(FEATURE_PROTECTOR, "Enter");
47     provision_->ReportThermalZoneData(reportTime_, multipleList_);
48     auto tzMap = provision_->GetSensorData();
49     notify_(tzMap);
50 }
51 
CreateProvisionFd()52 int32_t ThermalProtectorTimer::CreateProvisionFd()
53 {
54     timerFd_ = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
55     if (timerFd_ == ERR_INVALID_FD) {
56         THERMAL_HILOGE(FEATURE_PROTECTOR, "epoll create failed, epFd_ is invalid");
57         return ERR_INVALID_VALUE;
58     }
59     int interval = provision_->GetMaxCd();
60     SetTimerInterval(interval, timerFd_);
61     fcntl(timerFd_, F_SETFL, O_NONBLOCK);
62     callbackHandler_.insert(std::make_pair(timerFd_, &ThermalProtectorTimer::TimerProvisionCallback));
63     if (RegisterCallback(timerFd_, EVENT_TIMER_FD, epFd_)) {
64         THERMAL_HILOGI(FEATURE_PROTECTOR, "register Timer event failed");
65     }
66 
67     THERMAL_HILOGD(FEATURE_PROTECTOR, "Exit");
68     return ERR_OK;
69 }
70 
RegisterCallback(const int32_t fd,const EventType et,int32_t epfd)71 int32_t ThermalProtectorTimer::RegisterCallback(const int32_t fd, const EventType et, int32_t epfd)
72 {
73     struct epoll_event ev;
74 
75     ev.events = EPOLLIN;
76     if (et == EVENT_TIMER_FD) {
77         ev.events |= EPOLLWAKEUP;
78     }
79     THERMAL_HILOGI(FEATURE_PROTECTOR, "%{public}d, %{public}d", epfd, fd);
80     ev.data.ptr = reinterpret_cast<void*>(this);
81     ev.data.fd = fd;
82     if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
83         THERMAL_HILOGE(FEATURE_PROTECTOR, "epoll_ctl failed, error num =%{public}d", errno);
84         return -1;
85     }
86     THERMAL_HILOGD(FEATURE_PROTECTOR, "Exit");
87     return ERR_OK;
88 }
89 
TimerProvisionCallback(void * service)90 void ThermalProtectorTimer::TimerProvisionCallback(void *service)
91 {
92     unsigned long long timers;
93 
94     if (read(timerFd_, &timers, sizeof(timers)) == -1) {
95         THERMAL_HILOGE(FEATURE_PROTECTOR, "read timerFd_ failed");
96         return;
97     }
98     reportTime_ = reportTime_ + 1;
99     NotifyPolicy();
100     ResetCount();
101     return;
102 }
103 
SetTimerInterval(int32_t interval,int32_t timerfd)104 void ThermalProtectorTimer::SetTimerInterval(int32_t interval, int32_t timerfd)
105 {
106     struct itimerspec itval;
107 
108     if (timerfd == ERR_INVALID_FD) {
109         return;
110     }
111 
112     timerInterval_ = interval;
113 
114     if (interval < 0) {
115         interval = 0;
116     }
117 
118     itval.it_interval.tv_sec = interval / MS_PER_SECOND;
119     itval.it_interval.tv_nsec = 0;
120     itval.it_value.tv_sec = interval / MS_PER_SECOND;
121     itval.it_value.tv_nsec = 0;
122     if (timerfd_settime(timerfd, 0, &itval, nullptr) == -1) {
123         THERMAL_HILOGE(FEATURE_PROTECTOR, "timer failed\n");
124     }
125     THERMAL_HILOGD(FEATURE_PROTECTOR, "Exit");
126 }
127 
InitProvisionTimer()128 int32_t ThermalProtectorTimer::InitProvisionTimer()
129 {
130     int32_t ret;
131     epFd_ = epoll_create1(EPOLL_CLOEXEC);
132 
133     ret = CreateProvisionFd();
134     if (ret != ERR_OK) {
135         THERMAL_HILOGE(FEATURE_PROTECTOR, "failed to create polling fd");
136         return ret;
137     }
138     return ERR_OK;
139 }
140 
LoopingThreadEntry(void * arg,int32_t epfd)141 int32_t ThermalProtectorTimer::LoopingThreadEntry(void *arg, int32_t epfd)
142 {
143     int32_t nevents = 0;
144     size_t eventct = callbackHandler_.size();
145     struct epoll_event events[eventct];
146     THERMAL_HILOGI(FEATURE_PROTECTOR, "%{public}d, %{public}zu", epfd, eventct);
147     while (true) {
148         if (timeCount_ == END_TIME) {
149             return ERR_OK;
150         }
151         nevents = epoll_wait(epfd, events, eventct, -1);
152         if (nevents == -1) {
153             continue;
154         }
155         for (int32_t n = 0; n < nevents; ++n) {
156             if (events[n].data.ptr) {
157                 ThermalProtectorTimer *func = const_cast<ThermalProtectorTimer *>(this);
158                 (callbackHandler_.find(events[n].data.fd)->second)(func, arg);
159             }
160         }
161         timeCount_ = timeCount_ + 1;
162     }
163 }
164 
Run(void * service,int32_t epfd)165 void ThermalProtectorTimer::Run(void *service, int32_t epfd)
166 {
167     std::make_unique<std::thread>(&ThermalProtectorTimer::LoopingThreadEntry, this, service, epfd)->join();
168 }
169 
StartThread(void * service)170 void ThermalProtectorTimer::StartThread(void *service)
171 {
172     int32_t ret = InitProvisionTimer();
173     if (ret != ERR_OK) {
174         THERMAL_HILOGE(FEATURE_PROTECTOR, "init Timer failed, ret: %{public}d", ret);
175         return;
176     }
177     Run(service, epFd_);
178 }
179 
Init()180 int32_t ThermalProtectorTimer::Init()
181 {
182     StartThread(this);
183     return ERR_OK;
184 }
185 
ResetCount()186 void ThermalProtectorTimer::ResetCount()
187 {
188     THERMAL_HILOGD(FEATURE_PROTECTOR, "multipleList_:%{public}zu", multipleList_.size());
189     if (multipleList_.empty()) return;
190 
191     int32_t maxValue = *(std::max_element(multipleList_.begin(), multipleList_.end()));
192     if (reportTime_ == maxValue) {
193         THERMAL_HILOGI(FEATURE_PROTECTOR, "reportTime:%{public}d", reportTime_);
194         reportTime_ = 0;
195     }
196 }
197 } // PowerMgr
198 } // OHOS
199