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