• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 "charger_log.h"
25 
26 namespace OHOS {
27 namespace PowerMgr {
28 namespace {
29 constexpr int32_t UEVENT_BUFF_SIZE = (64 * 1024);
30 constexpr int32_t UEVENT_RESERVED_SIZE = 2;
31 constexpr int32_t UEVENT_MSG_LEN = (2 * 1024);
32 constexpr int32_t TIMER_FAST_SEC = 2;
33 constexpr int32_t SEC_TO_MSEC = 1000;
34 const std::string POWER_SUPPLY = "SUBSYSTEM=power_supply";
35 }
36 
OpenUeventSocket()37 int32_t BatteryThread::OpenUeventSocket()
38 {
39     int32_t bufferSize = UEVENT_BUFF_SIZE;
40     struct sockaddr_nl address = {
41         .nl_family = AF_NETLINK,
42         .nl_pid = getpid(),
43         .nl_groups = 0xffffffff
44     };
45 
46     int32_t fd = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
47     if (fd == INVALID_FD) {
48         BATTERY_HILOGE(FEATURE_CHARGING, "open uevent socket failed, fd is invalid");
49         return INVALID_FD;
50     }
51 
52     int32_t ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
53     if (ret < 0) {
54         BATTERY_HILOGE(FEATURE_CHARGING, "set socket opt failed, ret: %{public}d", ret);
55         close(fd);
56         return INVALID_FD;
57     }
58 
59     ret = bind(fd, reinterpret_cast<const struct sockaddr*>(&address), sizeof(struct sockaddr_nl));
60     if (ret < 0) {
61         BATTERY_HILOGE(FEATURE_CHARGING, "bind socket address failed, ret: %{public}d", ret);
62         close(fd);
63         return INVALID_FD;
64     }
65     return fd;
66 }
67 
RegisterCallback(int32_t fd,EventType et)68 int32_t BatteryThread::RegisterCallback(int32_t fd, EventType et)
69 {
70     struct epoll_event ev = {0};
71 
72     ev.events = EPOLLIN;
73     if (et == EVENT_TIMER_FD) {
74         ev.events |= EPOLLWAKEUP;
75     }
76 
77     ev.data.ptr = reinterpret_cast<void*>(this);
78     ev.data.fd = fd;
79     if (epoll_ctl(epFd_, EPOLL_CTL_ADD, fd, &ev) == -1) {
80         BATTERY_HILOGE(FEATURE_CHARGING, "epoll_ctl failed, error num =%{public}d", errno);
81         return HDF_FAILURE;
82     }
83     return HDF_SUCCESS;
84 }
85 
UpdateEpollInterval(const int32_t chargeState)86 void BatteryThread::UpdateEpollInterval(const int32_t chargeState)
87 {
88     if ((chargeState != PowerSupplyProvider::CHARGE_STATE_NONE) &&
89         (chargeState != PowerSupplyProvider::CHARGE_STATE_RESERVED)) {
90         epollInterval_ = TIMER_FAST_SEC * SEC_TO_MSEC;
91     } else {
92         epollInterval_ = -1;
93     }
94 }
95 
InitUevent()96 int32_t BatteryThread::InitUevent()
97 {
98     ueventFd_ = OpenUeventSocket();
99     if (ueventFd_ == INVALID_FD) {
100         BATTERY_HILOGE(FEATURE_CHARGING, "open uevent socket failed, fd is invalid");
101         return HDF_ERR_BAD_FD;
102     }
103 
104     fcntl(ueventFd_, F_SETFL, O_NONBLOCK);
105     callbacks_.insert(std::make_pair(ueventFd_, &BatteryThread::UeventCallback));
106 
107     if (RegisterCallback(ueventFd_, EVENT_UEVENT_FD)) {
108         BATTERY_HILOGE(FEATURE_CHARGING, "register Uevent event failed");
109         return HDF_ERR_BAD_FD;
110     }
111     return HDF_SUCCESS;
112 }
113 
Init(void * service)114 int32_t BatteryThread::Init([[maybe_unused]] void* service)
115 {
116     provider_ = std::make_unique<PowerSupplyProvider>();
117     if (provider_ != nullptr) {
118         provider_->InitBatteryPath();
119         provider_->InitPowerSupplySysfs();
120     }
121 
122     epFd_ = epoll_create1(EPOLL_CLOEXEC);
123     if (epFd_ == INVALID_FD) {
124         BATTERY_HILOGE(FEATURE_CHARGING, "epoll create failed, epFd_ is invalid");
125         return HDF_ERR_BAD_FD;
126     }
127 
128     InitUevent();
129 
130     return HDF_SUCCESS;
131 }
132 
UpdateWaitInterval()133 int32_t BatteryThread::UpdateWaitInterval()
134 {
135     return HDF_FAILURE;
136 }
137 
UeventCallback(void * service)138 void BatteryThread::UeventCallback(void* service)
139 {
140     char msg[UEVENT_MSG_LEN + UEVENT_RESERVED_SIZE] = { 0 };
141 
142     ssize_t len = recv(ueventFd_, msg, UEVENT_MSG_LEN, 0);
143     if (len < 0 || len >= UEVENT_MSG_LEN) {
144         BATTERY_HILOGI(FEATURE_CHARGING, "recv return msg is invalid, len: %{public}zd", len);
145         return;
146     }
147 
148     // msg separator
149     msg[len] = '\0';
150     msg[len + 1] = '\0';
151     if (!IsPowerSupplyEvent(msg)) {
152         return;
153     }
154     UpdateBatteryInfo(service);
155 }
156 
UpdateBatteryInfo(void * service)157 void BatteryThread::UpdateBatteryInfo(void* service) {}
158 
IsPowerSupplyEvent(const char * msg)159 bool BatteryThread::IsPowerSupplyEvent(const char* msg)
160 {
161     while (*msg) {
162         if (!strcmp(msg, POWER_SUPPLY.c_str())) {
163             return true;
164         }
165         while (*msg++) {} // move to next
166     }
167 
168     return false;
169 }
170 
LoopingThreadEntry(void * arg)171 int32_t BatteryThread::LoopingThreadEntry(void* arg)
172 {
173     int32_t nevents = 0;
174     size_t size = callbacks_.size();
175     struct epoll_event events[size];
176 
177     while (true) {
178         if (!nevents) {
179             CycleMatters();
180         }
181 
182         HandleStates();
183 
184         int32_t timeout = epollInterval_;
185         int32_t waitTimeout = UpdateWaitInterval();
186         if ((timeout < 0) || (waitTimeout > 0 && waitTimeout < timeout)) {
187             timeout = waitTimeout;
188         }
189 
190         nevents = epoll_wait(epFd_, events, static_cast<int32_t>(size), timeout);
191         if (nevents <= 0) {
192             continue;
193         }
194 
195         for (int32_t n = 0; n < nevents; ++n) {
196             if (events[n].data.ptr) {
197                 auto* func = const_cast<BatteryThread*>(this);
198                 (callbacks_.find(events[n].data.fd)->second)(func, arg);
199             }
200         }
201     }
202 }
203 
StartThread(void * service)204 void BatteryThread::StartThread(void* service)
205 {
206     Init(service);
207     Run(service);
208 }
209 
Run(void * service)210 void BatteryThread::Run(void* service) {}
211 } // namespace PowerMgr
212 } // namespace OHOS
213