• 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 "hdf_base.h"
24 #include "battery_log.h"
25 
26 namespace OHOS {
27 namespace HDI {
28 namespace Battery {
29 namespace V1_1 {
30 namespace {
31 constexpr int32_t UEVENT_BUFF_SIZE = (64 * 1024);
32 constexpr int32_t UEVENT_RESERVED_SIZE = 2;
33 constexpr int32_t UEVENT_MSG_LEN = (2 * 1024);
34 constexpr int32_t TIMER_FAST_SEC = 2;
35 constexpr int32_t SEC_TO_MSEC = 1000;
36 const std::string POWER_SUPPLY = "SUBSYSTEM=power_supply";
37 }
38 static sptr<IBatteryCallback> g_callback;
39 
InitCallback(const sptr<IBatteryCallback> & callback)40 void BatteryThread::InitCallback(const sptr<IBatteryCallback>& callback)
41 {
42     g_callback = callback;
43 }
44 
OpenUeventSocket()45 int32_t BatteryThread::OpenUeventSocket()
46 {
47     int32_t bufferSize = UEVENT_BUFF_SIZE;
48     struct sockaddr_nl address = {
49         .nl_family = AF_NETLINK,
50         .nl_pid = getpid(),
51         .nl_groups = 0xffffffff
52     };
53 
54     int32_t fd = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
55     if (fd == INVALID_FD) {
56         BATTERY_HILOGE(COMP_HDI, "open uevent socket failed, fd is invalid");
57         return INVALID_FD;
58     }
59 
60     int32_t ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
61     if (ret < 0) {
62         BATTERY_HILOGE(COMP_HDI, "set socket opt failed, ret: %{public}d", ret);
63         close(fd);
64         return INVALID_FD;
65     }
66 
67     ret = bind(fd, reinterpret_cast<const struct sockaddr*>(&address), sizeof(struct sockaddr_nl));
68     if (ret < 0) {
69         BATTERY_HILOGE(COMP_HDI, "bind socket address failed, ret: %{public}d", ret);
70         close(fd);
71         return INVALID_FD;
72     }
73     return fd;
74 }
75 
RegisterCallback(int32_t fd,EventType et)76 int32_t BatteryThread::RegisterCallback(int32_t fd, EventType et)
77 {
78     struct epoll_event ev = {0};
79 
80     ev.events = EPOLLIN;
81     if (et == EVENT_TIMER_FD) {
82         ev.events |= EPOLLWAKEUP;
83     }
84 
85     ev.data.ptr = reinterpret_cast<void*>(this);
86     ev.data.fd = fd;
87     if (epoll_ctl(epFd_, EPOLL_CTL_ADD, fd, &ev) == -1) {
88         BATTERY_HILOGE(COMP_HDI, "epoll_ctl failed, error num =%{public}d", errno);
89         return HDF_FAILURE;
90     }
91     return HDF_SUCCESS;
92 }
93 
UpdateEpollInterval(const int32_t chargeState)94 void BatteryThread::UpdateEpollInterval(const int32_t chargeState)
95 {
96     if ((chargeState != PowerSupplyProvider::CHARGE_STATE_NONE) &&
97         (chargeState != PowerSupplyProvider::CHARGE_STATE_RESERVED)) {
98         epollInterval_ = TIMER_FAST_SEC * SEC_TO_MSEC;
99     } else {
100         epollInterval_ = -1;
101     }
102 }
103 
InitUevent()104 int32_t BatteryThread::InitUevent()
105 {
106     ueventFd_ = OpenUeventSocket();
107     if (ueventFd_ == INVALID_FD) {
108         BATTERY_HILOGE(COMP_HDI, "open uevent socket failed, fd is invalid");
109         return HDF_ERR_BAD_FD;
110     }
111 
112     fcntl(ueventFd_, F_SETFL, O_NONBLOCK);
113     callbacks_.insert(std::make_pair(ueventFd_, &BatteryThread::UeventCallback));
114 
115     if (RegisterCallback(ueventFd_, EVENT_UEVENT_FD)) {
116         BATTERY_HILOGE(COMP_HDI, "register Uevent event failed");
117         return HDF_ERR_BAD_FD;
118     }
119     return HDF_SUCCESS;
120 }
121 
Init(void * service)122 int32_t BatteryThread::Init([[maybe_unused]] void* service)
123 {
124     provider_ = std::make_unique<PowerSupplyProvider>();
125     if (provider_ != nullptr) {
126         provider_->InitBatteryPath();
127         provider_->InitPowerSupplySysfs();
128     }
129 
130     epFd_ = epoll_create1(EPOLL_CLOEXEC);
131     if (epFd_ == INVALID_FD) {
132         BATTERY_HILOGE(COMP_HDI, "epoll create failed, epFd_ is invalid");
133         return HDF_ERR_BAD_FD;
134     }
135 
136     InitUevent();
137 
138     return HDF_SUCCESS;
139 }
140 
UpdateWaitInterval()141 int32_t BatteryThread::UpdateWaitInterval()
142 {
143     return HDF_FAILURE;
144 }
145 
UeventCallback(void * service)146 void BatteryThread::UeventCallback(void* service)
147 {
148     char msg[UEVENT_MSG_LEN + UEVENT_RESERVED_SIZE] = { 0 };
149 
150     ssize_t len = recv(ueventFd_, msg, UEVENT_MSG_LEN, 0);
151     if (len < 0 || len >= UEVENT_MSG_LEN) {
152         BATTERY_HILOGI(COMP_HDI, "recv return msg is invalid, len: %{public}zd", len);
153         return;
154     }
155 
156     // msg separator
157     msg[len] = '\0';
158     msg[len + 1] = '\0';
159     if (!IsPowerSupplyEvent(msg)) {
160         return;
161     }
162     UpdateBatteryInfo(service);
163 }
164 
UpdateBatteryInfo(void * service)165 void BatteryThread::UpdateBatteryInfo(void* service)
166 {
167     BatteryInfo event = {};
168     std::unique_ptr<BatterydInfo> batteryInfo = std::make_unique<BatterydInfo>();
169     if (batteryInfo == nullptr) {
170         BATTERY_HILOGE(FEATURE_BATT_INFO, "make_unique BatterydInfo error");
171         return;
172     }
173 
174     provider_->UpdateInfoByReadSysFile(batteryInfo.get());
175     event.capacity = batteryInfo->capacity_;
176     event.voltage= batteryInfo->voltage_;
177     event.temperature = batteryInfo->temperature_;
178     event.healthState = batteryInfo->healthState_;
179     event.pluggedType = batteryInfo->pluggedType_;
180     event.pluggedMaxCurrent = batteryInfo->pluggedMaxCurrent_;
181     event.pluggedMaxVoltage = batteryInfo->pluggedMaxVoltage_;
182     event.chargeState = batteryInfo->chargeState_;
183     event.chargeCounter = batteryInfo->chargeCounter_;
184     event.present = batteryInfo->present_;
185     event.technology = batteryInfo->technology_;
186     event.curNow = batteryInfo->curNow_;
187     event.remainEnergy = batteryInfo->remainEnergy_;
188     event.totalEnergy = batteryInfo->totalEnergy_;
189 
190     if (g_callback != nullptr) {
191         g_callback->Update(event);
192     } else {
193         BATTERY_HILOGI(FEATURE_BATT_INFO, "g_callback is nullptr");
194     }
195 }
196 
IsPowerSupplyEvent(const char * msg)197 bool BatteryThread::IsPowerSupplyEvent(const char* msg)
198 {
199     while (*msg) {
200         if (!strcmp(msg, POWER_SUPPLY.c_str())) {
201             return true;
202         }
203         while (*msg++) {} // move to next
204     }
205 
206     return false;
207 }
208 
LoopingThreadEntry(void * arg)209 int32_t BatteryThread::LoopingThreadEntry(void* arg)
210 {
211     int32_t nevents = 0;
212     size_t size = callbacks_.size();
213     struct epoll_event events[size];
214 
215     while (true) {
216         if (!nevents) {
217             CycleMatters();
218         }
219 
220         HandleStates();
221 
222         int32_t timeout = epollInterval_;
223         int32_t waitTimeout = UpdateWaitInterval();
224         if ((timeout < 0) || (waitTimeout > 0 && waitTimeout < timeout)) {
225             timeout = waitTimeout;
226         }
227 
228         nevents = epoll_wait(epFd_, events, static_cast<int32_t>(size), timeout);
229         if (nevents <= 0) {
230             continue;
231         }
232 
233         for (int32_t n = 0; n < nevents; ++n) {
234             if (events[n].data.ptr) {
235                 auto* func = const_cast<BatteryThread*>(this);
236                 (callbacks_.find(events[n].data.fd)->second)(func, arg);
237             }
238         }
239     }
240 }
241 
StartThread(void * service)242 void BatteryThread::StartThread(void* service)
243 {
244     Init(service);
245     Run(service);
246 }
247 
Run(void * service)248 void BatteryThread::Run(void* service)
249 {
250     std::thread batteryThread(&BatteryThread::LoopingThreadEntry, this, service);
251     pthread_setname_np(batteryThread.native_handle(), "battery_thread");
252     batteryThread.detach();
253 }
254 } // namespace V1_1
255 } // namespace Battery
256 } // namespace HDI
257 } // namespace OHOS
258