• 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 "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