• 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_hdf_timer.h"
17 #include <cerrno>
18 #include <thread>
19 #include <fcntl.h>
20 #include <unistd.h>
21 #include <hdf_base.h>
22 #include <sys/socket.h>
23 #include <sys/epoll.h>
24 #include <sys/timerfd.h>
25 #include <linux/netlink.h>
26 #include "thermal_log.h"
27 
28 namespace OHOS {
29 namespace HDI {
30 namespace Thermal {
31 namespace V1_0 {
32 namespace {
33 const int32_t ERR_INVALID_FD = -1;
34 const int32_t MS_PER_SECOND = 1000;
35 const std::string THERMAL_SIMULATION_TAG = "sim_tz";
36 }
ThermalHdfTimer(const std::shared_ptr<ThermalSimulationNode> & node,const std::shared_ptr<ThermalZoneManager> & thermalZoneMgr)37 ThermalHdfTimer::ThermalHdfTimer(const std::shared_ptr<ThermalSimulationNode> &node,
38     const std::shared_ptr<ThermalZoneManager> &thermalZoneMgr)
39 {
40     node_ = node;
41     thermalZoneMgr_ = thermalZoneMgr;
42     reportTime_ = 0;
43 }
44 
SetThermalEventCb(const sptr<IThermalCallback> & thermalCb)45 void ThermalHdfTimer::SetThermalEventCb(const sptr<IThermalCallback> &thermalCb)
46 {
47     thermalCb_ = thermalCb;
48 }
49 
SetSimluationFlag()50 void ThermalHdfTimer::SetSimluationFlag()
51 {
52     auto baseConfigList = ThermalHdfConfig::GetInsance().GetBaseConfig()->GetBaseItem();
53     if (baseConfigList.empty()) {
54         THERMAL_HILOGE(COMP_HDI, "baseConfigList is empty");
55         return;
56     }
57     auto baseIter = std::find(baseConfigList.begin(), baseConfigList.end(), THERMAL_SIMULATION_TAG);
58     if (baseIter != baseConfigList.end()) {
59         isSim_ = atoi(baseIter->value.c_str());
60         THERMAL_HILOGD(COMP_HDI, "isSim value:%{public}d", isSim_);
61     } else {
62         THERMAL_HILOGD(COMP_HDI, "not found");
63     }
64 }
65 
SetSimFlag(int32_t flag)66 void ThermalHdfTimer::SetSimFlag(int32_t flag)
67 {
68     isSim_ = flag;
69 }
70 
GetSimluationFlag()71 int32_t ThermalHdfTimer::GetSimluationFlag()
72 {
73     return isSim_;
74 }
75 
CreateProviderFd()76 int32_t ThermalHdfTimer::CreateProviderFd()
77 {
78     timerFd_ = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
79     if (timerFd_ == ERR_INVALID_FD) {
80         THERMAL_HILOGE(COMP_HDI, "epoll create failed, epFd_ is invalid");
81         return HDF_ERR_INVALID_PARAM;
82     }
83 
84     THERMAL_HILOGD(COMP_HDI, "interval %{public}d", thermalZoneMgr_->maxCd_);
85     SetTimerInterval(thermalZoneMgr_->maxCd_, timerFd_);
86     fcntl(timerFd_, F_SETFL, O_NONBLOCK);
87     callbackHandler_.insert(std::make_pair(timerFd_, &ThermalHdfTimer::TimerProviderCallback));
88     if (RegisterCallback(timerFd_, EVENT_TIMER_FD, epFd_)) {
89         THERMAL_HILOGD(COMP_HDI, "register Timer event failed");
90     }
91 
92     THERMAL_HILOGD(COMP_HDI, "return");
93     return HDF_SUCCESS;
94 }
95 
RegisterCallback(const int32_t fd,const EventType et,int32_t epfd)96 int32_t ThermalHdfTimer::RegisterCallback(const int32_t fd, const EventType et, int32_t epfd)
97 {
98     struct epoll_event ev;
99 
100     ev.events = EPOLLIN;
101     if (et == EVENT_TIMER_FD) {
102         ev.events |= EPOLLWAKEUP;
103     }
104     THERMAL_HILOGD(COMP_HDI, "%{public}d, %{public}d", epfd, fd);
105     ev.data.ptr = reinterpret_cast<void*>(this);
106     ev.data.fd = fd;
107     if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == HDF_FAILURE) {
108         THERMAL_HILOGE(COMP_HDI, "epoll_ctl failed, error num =%{public}d",
109             errno);
110         return HDF_FAILURE;
111     }
112     THERMAL_HILOGD(COMP_HDI, "return");
113     return HDF_SUCCESS;
114 }
115 
TimerProviderCallback(void * service)116 void ThermalHdfTimer::TimerProviderCallback(void *service)
117 {
118     unsigned long long timers;
119 
120     if (read(timerFd_, &timers, sizeof(timers)) == -1) {
121         THERMAL_HILOGE(COMP_HDI, "read timerFd_ failed");
122         return;
123     }
124 
125     reportTime_ = reportTime_ + 1;
126     ReportThermalData();
127     ResetCount();
128     return;
129 }
130 
SetTimerInterval(int32_t interval,int32_t timerfd)131 void ThermalHdfTimer::SetTimerInterval(int32_t interval, int32_t timerfd)
132 {
133     struct itimerspec itval;
134 
135     if (timerfd == ERR_INVALID_FD) {
136         return;
137     }
138 
139     timerInterval_ = interval;
140 
141     if (interval < 0) {
142         interval = 0;
143     }
144 
145     itval.it_interval.tv_sec = interval / MS_PER_SECOND;
146     itval.it_interval.tv_nsec = 0;
147     itval.it_value.tv_sec = interval / MS_PER_SECOND;
148     itval.it_value.tv_nsec = 0;
149     if (timerfd_settime(timerfd, 0, &itval, nullptr) == -1) {
150         THERMAL_HILOGE(COMP_HDI, "timer failed\n");
151     }
152     THERMAL_HILOGD(COMP_HDI, "return");
153 }
154 
InitProviderTimer()155 int32_t ThermalHdfTimer::InitProviderTimer()
156 {
157     int32_t ret;
158     epFd_ = epoll_create1(EPOLL_CLOEXEC);
159 
160     ret = CreateProviderFd();
161     if (ret != HDF_SUCCESS) {
162         THERMAL_HILOGE(COMP_HDI, "failed to create polling fd");
163         return ret;
164     }
165     return HDF_SUCCESS;
166 }
167 
LoopingThreadEntry(void * arg,int32_t epfd)168 int32_t ThermalHdfTimer::LoopingThreadEntry(void *arg, int32_t epfd)
169 {
170     int32_t nevents = 0;
171     size_t eventct = callbackHandler_.size();
172     struct epoll_event events[eventct];
173     THERMAL_HILOGD(COMP_HDI, "%{public}d, %{public}zu", epfd, eventct);
174     while (true) {
175         nevents = epoll_wait(epfd, events, eventct, -1);
176         if (nevents == -1) {
177             continue;
178         }
179         for (int32_t n = 0; n < nevents; ++n) {
180             if (events[n].data.ptr) {
181                 ThermalHdfTimer *func = const_cast<ThermalHdfTimer *>(this);
182                 (callbackHandler_.find(events[n].data.fd)->second)(func, arg);
183             }
184         }
185     }
186 }
187 
Run(void * service,int32_t epfd)188 void ThermalHdfTimer::Run(void *service, int32_t epfd)
189 {
190     std::make_unique<std::thread>(&ThermalHdfTimer::LoopingThreadEntry, this, service, epfd)->detach();
191 }
192 
StartThread(void * service)193 void ThermalHdfTimer::StartThread(void *service)
194 {
195     int32_t ret = InitProviderTimer();
196     if (ret != HDF_SUCCESS) {
197         THERMAL_HILOGE(COMP_HDI, "init Timer failed, ret: %{public}d", ret);
198         return;
199     }
200     Run(service, epFd_);
201 }
202 
Init()203 int32_t ThermalHdfTimer::Init()
204 {
205     StartThread(this);
206     return HDF_SUCCESS;
207 }
208 
ReportThermalData()209 void ThermalHdfTimer::ReportThermalData()
210 {
211     if (thermalCb_ == nullptr) {
212         THERMAL_HILOGE(COMP_HDI, "check thermalCb_ failed");
213         return;
214     }
215 
216     thermalZoneMgr_->ReportThermalZoneData(reportTime_, multipleList_);
217     tzInfoEvent_ = thermalZoneMgr_->tzInfoAcaualEvent_;
218     // callback thermal event
219     thermalCb_->OnThermalDataEvent(tzInfoEvent_);
220 }
221 
ResetCount()222 void ThermalHdfTimer::ResetCount()
223 {
224     if (multipleList_.empty()) return;
225 
226     int32_t maxValue = *(std::max_element(multipleList_.begin(), multipleList_.end()));
227     if (reportTime_ == maxValue) {
228         reportTime_ = 0;
229     }
230     tzInfoEvent_.info.clear();
231 }
232 
DumpSensorConfigInfo()233 void ThermalHdfTimer::DumpSensorConfigInfo()
234 {
235     auto sensorTypeMap = ThermalHdfConfig::GetInsance().GetSensorTypeMap();
236     for (auto sensorIter : sensorTypeMap) {
237         THERMAL_HILOGD(COMP_HDI, "groupName %{public}s, interval %{public}d, multiple %{public}d",
238             sensorIter.first.c_str(), sensorIter.second->GetInterval(), sensorIter.second->multiple_);
239         for (auto tzIter : sensorIter.second->GetXMLThermalZoneInfo()) {
240             THERMAL_HILOGD(COMP_HDI, "type %{public}s, replace %{public}s", tzIter.type.c_str(),
241                 tzIter.replace.c_str());
242         }
243         for (auto tnIter : sensorIter.second->GetXMLThermalNodeInfo()) {
244             THERMAL_HILOGD(COMP_HDI, "type %{public}s, path %{public}s", tnIter.type.c_str(),
245                 tnIter.path.c_str());
246         }
247         for (auto dataIter : sensorIter.second->thermalDataList_) {
248             THERMAL_HILOGD(COMP_HDI, "data type %{public}s, data temp path %{public}s", dataIter.type.c_str(),
249                 dataIter.tempPath.c_str());
250         }
251     }
252 }
253 } // V1_0
254 } // Thermal
255 } // HDI
256 } // OHOS
257