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 "battery_thread.h"
17 #include <cerrno>
18 #include <sys/epoll.h>
19 #include <sys/socket.h>
20 #include <sys/timerfd.h>
21 #include <unistd.h>
22 #include <linux/netlink.h>
23 #include "core/hdf_device_desc.h"
24 #include "utils/hdf_log.h"
25
26 #define HDF_LOG_TAG BatteryThread
27
28 using namespace OHOS::HDI::Battery::V1_0;
29
30 namespace OHOS {
31 namespace HDI {
32 namespace Battery {
33 namespace V1_0 {
34 const int ERR_INVALID_FD = -1;
35 const int ERR_OPERATION_FAILED = -1;
36 const int UEVENT_BUFF_SIZE = (64 * 1024);
37 const int UEVENT_RESERVED_SIZE = 2;
38 const int UEVENT_MSG_LEN = (2 * 1024);
39 const int TIMER_INTERVAL = 10;
40 const int TIMER_FAST_SEC = 2;
41 const int TIMER_SLOW_SEC = 10;
42 const int SEC_TO_MSEC = 1000;
43 const std::string POWER_SUPPLY = "SUBSYSTEM=power_supply";
44 static sptr<IBatteryCallback> g_callback;
45
InitCallback(const sptr<IBatteryCallback> & event)46 void BatteryThread::InitCallback(const sptr<IBatteryCallback>& event)
47 {
48 g_callback = event;
49 }
50
OpenUeventSocket(void) const51 int32_t BatteryThread::OpenUeventSocket(void) const
52 {
53 int32_t bufferSize = UEVENT_BUFF_SIZE;
54 struct sockaddr_nl address = {
55 .nl_pid = getpid(),
56 .nl_family = AF_NETLINK,
57 .nl_groups = 0xffffffff
58 };
59
60 int32_t fd = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
61 if (fd == ERR_INVALID_FD) {
62 HDF_LOGE("%{public}s: open uevent socket failed, fd is invalid", __func__);
63 return ERR_INVALID_FD;
64 }
65
66 int32_t ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &bufferSize, sizeof(bufferSize));
67 if (ret == ERR_OPERATION_FAILED) {
68 HDF_LOGE("%{public}s: set socket opt failed, ret: %{public}d", __func__, ret);
69 close(fd);
70 return ERR_INVALID_FD;
71 }
72
73 ret = bind(fd, reinterpret_cast<const struct sockaddr*>(&address), sizeof(struct sockaddr_nl));
74 if (ret == ERR_OPERATION_FAILED) {
75 HDF_LOGE("%{public}s: bind socket address failed, ret: %{public}d", __func__, ret);
76 close(fd);
77 return ERR_INVALID_FD;
78 }
79 return fd;
80 }
81
RegisterCallback(const int fd,const EventType et)82 int BatteryThread::RegisterCallback(const int fd, const EventType et)
83 {
84 struct epoll_event ev;
85
86 ev.events = EPOLLIN;
87 if (et == EVENT_TIMER_FD) {
88 ev.events |= EPOLLWAKEUP;
89 }
90
91 ev.data.ptr = reinterpret_cast<void*>(this);
92 ev.data.fd = fd;
93 if (epoll_ctl(epFd_, EPOLL_CTL_ADD, fd, &ev) == -1) {
94 HDF_LOGE("%{public}s: epoll_ctl failed, error num =%{public}d", __func__, errno);
95 return HDF_FAILURE;
96 }
97 return HDF_SUCCESS;
98 }
99
SetTimerInterval(int interval)100 void BatteryThread::SetTimerInterval(int interval)
101 {
102 struct itimerspec itval;
103
104 if (timerFd_ == ERR_INVALID_FD) {
105 return;
106 }
107
108 timerInterval_ = interval;
109 if (interval < 0) {
110 interval = 0;
111 }
112
113 itval.it_interval.tv_sec = interval;
114 itval.it_interval.tv_nsec = 0;
115 itval.it_value.tv_sec = interval;
116 itval.it_value.tv_nsec = 0;
117
118 if (timerfd_settime(timerFd_, 0, &itval, nullptr) == -1) {
119 HDF_LOGE("%{public}s: timer failed\n", __func__);
120 }
121 return;
122 }
123
UpdateEpollInterval(const int32_t chargeState)124 void BatteryThread::UpdateEpollInterval(const int32_t chargeState)
125 {
126 int interval;
127 if ((chargeState != PowerSupplyProvider::CHARGE_STATE_NONE) &&
128 (chargeState != PowerSupplyProvider::CHARGE_STATE_RESERVED)) {
129 interval = TIMER_FAST_SEC;
130 epollInterval_ = interval * SEC_TO_MSEC;
131 } else {
132 interval = TIMER_SLOW_SEC;
133 epollInterval_ = -1;
134 }
135
136 if ((interval != timerInterval_) && (timerInterval_ > 0)) {
137 SetTimerInterval(interval);
138 }
139 return;
140 }
141
InitUevent()142 int32_t BatteryThread::InitUevent()
143 {
144 ueventFd_ = OpenUeventSocket();
145 if (ueventFd_ == ERR_INVALID_FD) {
146 HDF_LOGE("%{public}s: open uevent socket failed, fd is invalid", __func__);
147 return HDF_ERR_BAD_FD;
148 }
149
150 fcntl(ueventFd_, F_SETFL, O_NONBLOCK);
151 callbacks_.insert(std::make_pair(ueventFd_, &BatteryThread::UeventCallback));
152
153 if (RegisterCallback(ueventFd_, EVENT_UEVENT_FD)) {
154 HDF_LOGE("%{public}s: register Uevent event failed", __func__);
155 return HDF_ERR_BAD_FD;
156 }
157 return HDF_SUCCESS;
158 }
159
Init(void * service)160 int32_t BatteryThread::Init(void* service)
161 {
162 giver_ = std::make_unique<PowerSupplyProvider>();
163 if (giver_ != nullptr) {
164 giver_->InitBatteryPath();
165 giver_->InitPowerSupplySysfs();
166 }
167
168 epFd_ = epoll_create1(EPOLL_CLOEXEC);
169 if (epFd_ == -1) {
170 HDF_LOGE("%{public}s: epoll create failed, timerFd_ is invalid", __func__);
171 return HDF_ERR_BAD_FD;
172 }
173
174 InitTimer();
175 InitUevent();
176
177 return HDF_SUCCESS;
178 }
179
UpdateWaitInterval()180 int BatteryThread::UpdateWaitInterval()
181 {
182 return HDF_FAILURE;
183 }
184
InitTimer()185 int32_t BatteryThread::InitTimer()
186 {
187 timerFd_ = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
188 if (timerFd_ == ERR_INVALID_FD) {
189 HDF_LOGE("%{public}s: epoll create failed, timerFd_ is invalid", __func__);
190 return HDF_ERR_BAD_FD;
191 }
192
193 SetTimerInterval(TIMER_INTERVAL);
194 fcntl(timerFd_, F_SETFL, O_NONBLOCK);
195 callbacks_.insert(std::make_pair(timerFd_, &BatteryThread::TimerCallback));
196
197 if (RegisterCallback(timerFd_, EVENT_TIMER_FD)) {
198 HDF_LOGE("%{public}s: register Timer event failed", __func__);
199 }
200
201 return HDF_SUCCESS;
202 }
203
TimerCallback(void * service)204 void BatteryThread::TimerCallback(void* service)
205 {
206 unsigned long long timers;
207
208 if (read(timerFd_, &timers, sizeof(timers)) == -1) {
209 HDF_LOGE("%{public}s: read timerFd_ failed", __func__);
210 return;
211 }
212
213 UpdateBatteryInfo(service);
214
215 return;
216 }
217
UeventCallback(void * service)218 void BatteryThread::UeventCallback(void* service)
219 {
220 char msg[UEVENT_MSG_LEN + UEVENT_RESERVED_SIZE] = { 0 };
221
222 int32_t len = recv(ueventFd_, msg, UEVENT_MSG_LEN, 0);
223 if (len < 0 || len >= UEVENT_MSG_LEN) {
224 HDF_LOGI("%{public}s: recv return msg is invalid, len: %{public}d", __func__, len);
225 return;
226 }
227
228 // msg separator
229 msg[len] = '\0';
230 msg[len + 1] = '\0';
231 if (!IsPowerSupplyEvent(msg)) {
232 return;
233 }
234 UpdateBatteryInfo(service, msg);
235 return;
236 }
237
UpdateBatteryInfo(void * service,char * msg)238 void BatteryThread::UpdateBatteryInfo(void* service, char* msg)
239 {
240 BatteryInfo event;
241 std::unique_ptr<BatterydInfo> batteryInfo = std::make_unique<BatterydInfo>();
242 if (batteryInfo == nullptr) {
243 HDF_LOGE("%{public}s instantiate batteryInfo error", __func__);
244 return;
245 }
246
247 giver_->ParseUeventToBatterydInfo(msg, batteryInfo.get());
248 event.capacity = batteryInfo->capacity_;
249 event.voltage= batteryInfo->voltage_;
250 event.temperature = batteryInfo->temperature_;
251 event.healthState = batteryInfo->healthState_;
252 event.pluggedType = batteryInfo->pluggedType_;
253 event.pluggedMaxCurrent = batteryInfo->pluggedMaxCurrent_;
254 event.pluggedMaxVoltage = batteryInfo->pluggedMaxVoltage_;
255 event.chargeState = batteryInfo->chargeState_;
256 event.chargeCounter = batteryInfo->chargeCounter_;
257 event.present = batteryInfo->present_;
258 event.technology = batteryInfo->technology_;
259
260 if (g_callback != nullptr) {
261 HDF_LOGI("%{public}s g_callback is not nullptr", __func__);
262 g_callback->Update(event);
263 } else {
264 HDF_LOGI("%{public}s g_callback is nullptr", __func__);
265 }
266 return;
267 }
268
UpdateBatteryInfo(void * service)269 void BatteryThread::UpdateBatteryInfo(void* service)
270 {
271 BatteryInfo event;
272 std::unique_ptr<BatterydInfo> batteryInfo = std::make_unique<BatterydInfo>();
273 if (batteryInfo == nullptr) {
274 HDF_LOGE("%{public}s instantiate batteryInfo error", __func__);
275 return;
276 }
277
278 giver_->UpdateInfoByReadSysFile(batteryInfo.get());
279 event.capacity = batteryInfo->capacity_;
280 event.voltage= batteryInfo->voltage_;
281 event.temperature = batteryInfo->temperature_;
282 event.healthState = batteryInfo->healthState_;
283 event.pluggedType = batteryInfo->pluggedType_;
284 event.pluggedMaxCurrent = batteryInfo->pluggedMaxCurrent_;
285 event.pluggedMaxVoltage = batteryInfo->pluggedMaxVoltage_;
286 event.chargeState = batteryInfo->chargeState_;
287 event.chargeCounter = batteryInfo->chargeCounter_;
288 event.present = batteryInfo->present_;
289 event.technology = batteryInfo->technology_;
290
291 if (g_callback != nullptr) {
292 g_callback->Update(event);
293 } else {
294 HDF_LOGW("%{public}s g_callback is nullptr", __func__);
295 }
296
297 return;
298 }
299
IsPowerSupplyEvent(const char * msg) const300 bool BatteryThread::IsPowerSupplyEvent(const char* msg) const
301 {
302 while (*msg) {
303 if (!strcmp(msg, POWER_SUPPLY.c_str())) {
304 return true;
305 }
306 while (*msg++) {} // move to next
307 }
308
309 return false;
310 }
311
LoopingThreadEntry(void * arg)312 int BatteryThread::LoopingThreadEntry(void* arg)
313 {
314 int nevents = 0;
315 size_t cbct = callbacks_.size();
316 struct epoll_event events[cbct];
317
318 HDF_LOGI("%{public}s: start batteryd looping", __func__);
319 while (true) {
320 if (!nevents) {
321 CycleMatters();
322 }
323
324 HandleStates();
325
326 int timeout = epollInterval_;
327 int waitTimeout = UpdateWaitInterval();
328 if ((timeout < 0) || (waitTimeout > 0 && waitTimeout < timeout)) {
329 timeout = waitTimeout;
330 }
331
332 nevents = epoll_wait(epFd_, events, cbct, timeout);
333 if (nevents == -1) {
334 continue;
335 }
336
337 for (int n = 0; n < nevents; ++n) {
338 if (events[n].data.ptr) {
339 BatteryThread* func = const_cast<BatteryThread*>(this);
340 (callbacks_.find(events[n].data.fd)->second)(func, arg);
341 }
342 }
343 }
344 }
345
StartThread(void * service)346 void BatteryThread::StartThread(void* service)
347 {
348 Init(service);
349 Run(service);
350
351 return;
352 }
353
Run(void * service)354 void BatteryThread::Run(void* service)
355 {
356 std::make_unique<std::thread>(&BatteryThread::LoopingThreadEntry, this, service)->detach();
357 }
358 } // namespace V1_0
359 } // namespace Battery
360 } // namespace HDI
361 } // namespace OHOS
362