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 26namespace OHOS { 27namespace PowerMgr { 28namespace { 29constexpr int32_t UEVENT_BUFF_SIZE = (64 * 1024); 30constexpr int32_t UEVENT_RESERVED_SIZE = 2; 31constexpr int32_t UEVENT_MSG_LEN = (2 * 1024); 32constexpr int32_t TIMER_FAST_SEC = 2; 33constexpr int32_t SEC_TO_MSEC = 1000; 34const std::string POWER_SUPPLY = "SUBSYSTEM=power_supply"; 35} 36 37int32_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 68int32_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 86void 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 96int32_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 114int32_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 133int32_t BatteryThread::UpdateWaitInterval() 134{ 135 return HDF_FAILURE; 136} 137 138void 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 157void BatteryThread::UpdateBatteryInfo(void* service) {} 158 159bool 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 171int32_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 204void BatteryThread::StartThread(void* service) 205{ 206 Init(service); 207 Run(service); 208} 209 210void BatteryThread::Run(void* service) {} 211} // namespace PowerMgr 212} // namespace OHOS 213