1f16e0440Sopenharmony_ci/*
2f16e0440Sopenharmony_ci * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3f16e0440Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4f16e0440Sopenharmony_ci * you may not use this file except in compliance with the License.
5f16e0440Sopenharmony_ci * You may obtain a copy of the License at
6f16e0440Sopenharmony_ci *
7f16e0440Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8f16e0440Sopenharmony_ci *
9f16e0440Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10f16e0440Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11f16e0440Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12f16e0440Sopenharmony_ci * See the License for the specific language governing permissions and
13f16e0440Sopenharmony_ci * limitations under the License.
14f16e0440Sopenharmony_ci */
15f16e0440Sopenharmony_ci
16f16e0440Sopenharmony_ci#include "battery_thread.h"
17f16e0440Sopenharmony_ci#include <cerrno>
18f16e0440Sopenharmony_ci#include <sys/epoll.h>
19f16e0440Sopenharmony_ci#include <sys/socket.h>
20f16e0440Sopenharmony_ci#include <sys/timerfd.h>
21f16e0440Sopenharmony_ci#include <unistd.h>
22f16e0440Sopenharmony_ci#include <linux/netlink.h>
23f16e0440Sopenharmony_ci#include "hdf_base.h"
24f16e0440Sopenharmony_ci#include "charger_log.h"
25f16e0440Sopenharmony_ci
26f16e0440Sopenharmony_cinamespace OHOS {
27f16e0440Sopenharmony_cinamespace PowerMgr {
28f16e0440Sopenharmony_cinamespace {
29f16e0440Sopenharmony_ciconstexpr int32_t UEVENT_BUFF_SIZE = (64 * 1024);
30f16e0440Sopenharmony_ciconstexpr int32_t UEVENT_RESERVED_SIZE = 2;
31f16e0440Sopenharmony_ciconstexpr int32_t UEVENT_MSG_LEN = (2 * 1024);
32f16e0440Sopenharmony_ciconstexpr int32_t TIMER_FAST_SEC = 2;
33f16e0440Sopenharmony_ciconstexpr int32_t SEC_TO_MSEC = 1000;
34f16e0440Sopenharmony_ciconst std::string POWER_SUPPLY = "SUBSYSTEM=power_supply";
35f16e0440Sopenharmony_ci}
36f16e0440Sopenharmony_ci
37f16e0440Sopenharmony_ciint32_t BatteryThread::OpenUeventSocket()
38f16e0440Sopenharmony_ci{
39f16e0440Sopenharmony_ci    int32_t bufferSize = UEVENT_BUFF_SIZE;
40f16e0440Sopenharmony_ci    struct sockaddr_nl address = {
41f16e0440Sopenharmony_ci        .nl_family = AF_NETLINK,
42f16e0440Sopenharmony_ci        .nl_pid = getpid(),
43f16e0440Sopenharmony_ci        .nl_groups = 0xffffffff
44f16e0440Sopenharmony_ci    };
45f16e0440Sopenharmony_ci
46f16e0440Sopenharmony_ci    int32_t fd = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
47f16e0440Sopenharmony_ci    if (fd == INVALID_FD) {
48f16e0440Sopenharmony_ci        BATTERY_HILOGE(FEATURE_CHARGING, "open uevent socket failed, fd is invalid");
49f16e0440Sopenharmony_ci        return INVALID_FD;
50f16e0440Sopenharmony_ci    }
51f16e0440Sopenharmony_ci
52f16e0440Sopenharmony_ci    int32_t ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
53f16e0440Sopenharmony_ci    if (ret < 0) {
54f16e0440Sopenharmony_ci        BATTERY_HILOGE(FEATURE_CHARGING, "set socket opt failed, ret: %{public}d", ret);
55f16e0440Sopenharmony_ci        close(fd);
56f16e0440Sopenharmony_ci        return INVALID_FD;
57f16e0440Sopenharmony_ci    }
58f16e0440Sopenharmony_ci
59f16e0440Sopenharmony_ci    ret = bind(fd, reinterpret_cast<const struct sockaddr*>(&address), sizeof(struct sockaddr_nl));
60f16e0440Sopenharmony_ci    if (ret < 0) {
61f16e0440Sopenharmony_ci        BATTERY_HILOGE(FEATURE_CHARGING, "bind socket address failed, ret: %{public}d", ret);
62f16e0440Sopenharmony_ci        close(fd);
63f16e0440Sopenharmony_ci        return INVALID_FD;
64f16e0440Sopenharmony_ci    }
65f16e0440Sopenharmony_ci    return fd;
66f16e0440Sopenharmony_ci}
67f16e0440Sopenharmony_ci
68f16e0440Sopenharmony_ciint32_t BatteryThread::RegisterCallback(int32_t fd, EventType et)
69f16e0440Sopenharmony_ci{
70f16e0440Sopenharmony_ci    struct epoll_event ev = {0};
71f16e0440Sopenharmony_ci
72f16e0440Sopenharmony_ci    ev.events = EPOLLIN;
73f16e0440Sopenharmony_ci    if (et == EVENT_TIMER_FD) {
74f16e0440Sopenharmony_ci        ev.events |= EPOLLWAKEUP;
75f16e0440Sopenharmony_ci    }
76f16e0440Sopenharmony_ci
77f16e0440Sopenharmony_ci    ev.data.ptr = reinterpret_cast<void*>(this);
78f16e0440Sopenharmony_ci    ev.data.fd = fd;
79f16e0440Sopenharmony_ci    if (epoll_ctl(epFd_, EPOLL_CTL_ADD, fd, &ev) == -1) {
80f16e0440Sopenharmony_ci        BATTERY_HILOGE(FEATURE_CHARGING, "epoll_ctl failed, error num =%{public}d", errno);
81f16e0440Sopenharmony_ci        return HDF_FAILURE;
82f16e0440Sopenharmony_ci    }
83f16e0440Sopenharmony_ci    return HDF_SUCCESS;
84f16e0440Sopenharmony_ci}
85f16e0440Sopenharmony_ci
86f16e0440Sopenharmony_civoid BatteryThread::UpdateEpollInterval(const int32_t chargeState)
87f16e0440Sopenharmony_ci{
88f16e0440Sopenharmony_ci    if ((chargeState != PowerSupplyProvider::CHARGE_STATE_NONE) &&
89f16e0440Sopenharmony_ci        (chargeState != PowerSupplyProvider::CHARGE_STATE_RESERVED)) {
90f16e0440Sopenharmony_ci        epollInterval_ = TIMER_FAST_SEC * SEC_TO_MSEC;
91f16e0440Sopenharmony_ci    } else {
92f16e0440Sopenharmony_ci        epollInterval_ = -1;
93f16e0440Sopenharmony_ci    }
94f16e0440Sopenharmony_ci}
95f16e0440Sopenharmony_ci
96f16e0440Sopenharmony_ciint32_t BatteryThread::InitUevent()
97f16e0440Sopenharmony_ci{
98f16e0440Sopenharmony_ci    ueventFd_ = OpenUeventSocket();
99f16e0440Sopenharmony_ci    if (ueventFd_ == INVALID_FD) {
100f16e0440Sopenharmony_ci        BATTERY_HILOGE(FEATURE_CHARGING, "open uevent socket failed, fd is invalid");
101f16e0440Sopenharmony_ci        return HDF_ERR_BAD_FD;
102f16e0440Sopenharmony_ci    }
103f16e0440Sopenharmony_ci
104f16e0440Sopenharmony_ci    fcntl(ueventFd_, F_SETFL, O_NONBLOCK);
105f16e0440Sopenharmony_ci    callbacks_.insert(std::make_pair(ueventFd_, &BatteryThread::UeventCallback));
106f16e0440Sopenharmony_ci
107f16e0440Sopenharmony_ci    if (RegisterCallback(ueventFd_, EVENT_UEVENT_FD)) {
108f16e0440Sopenharmony_ci        BATTERY_HILOGE(FEATURE_CHARGING, "register Uevent event failed");
109f16e0440Sopenharmony_ci        return HDF_ERR_BAD_FD;
110f16e0440Sopenharmony_ci    }
111f16e0440Sopenharmony_ci    return HDF_SUCCESS;
112f16e0440Sopenharmony_ci}
113f16e0440Sopenharmony_ci
114f16e0440Sopenharmony_ciint32_t BatteryThread::Init([[maybe_unused]] void* service)
115f16e0440Sopenharmony_ci{
116f16e0440Sopenharmony_ci    provider_ = std::make_unique<PowerSupplyProvider>();
117f16e0440Sopenharmony_ci    if (provider_ != nullptr) {
118f16e0440Sopenharmony_ci        provider_->InitBatteryPath();
119f16e0440Sopenharmony_ci        provider_->InitPowerSupplySysfs();
120f16e0440Sopenharmony_ci    }
121f16e0440Sopenharmony_ci
122f16e0440Sopenharmony_ci    epFd_ = epoll_create1(EPOLL_CLOEXEC);
123f16e0440Sopenharmony_ci    if (epFd_ == INVALID_FD) {
124f16e0440Sopenharmony_ci        BATTERY_HILOGE(FEATURE_CHARGING, "epoll create failed, epFd_ is invalid");
125f16e0440Sopenharmony_ci        return HDF_ERR_BAD_FD;
126f16e0440Sopenharmony_ci    }
127f16e0440Sopenharmony_ci
128f16e0440Sopenharmony_ci    InitUevent();
129f16e0440Sopenharmony_ci
130f16e0440Sopenharmony_ci    return HDF_SUCCESS;
131f16e0440Sopenharmony_ci}
132f16e0440Sopenharmony_ci
133f16e0440Sopenharmony_ciint32_t BatteryThread::UpdateWaitInterval()
134f16e0440Sopenharmony_ci{
135f16e0440Sopenharmony_ci    return HDF_FAILURE;
136f16e0440Sopenharmony_ci}
137f16e0440Sopenharmony_ci
138f16e0440Sopenharmony_civoid BatteryThread::UeventCallback(void* service)
139f16e0440Sopenharmony_ci{
140f16e0440Sopenharmony_ci    char msg[UEVENT_MSG_LEN + UEVENT_RESERVED_SIZE] = { 0 };
141f16e0440Sopenharmony_ci
142f16e0440Sopenharmony_ci    ssize_t len = recv(ueventFd_, msg, UEVENT_MSG_LEN, 0);
143f16e0440Sopenharmony_ci    if (len < 0 || len >= UEVENT_MSG_LEN) {
144f16e0440Sopenharmony_ci        BATTERY_HILOGI(FEATURE_CHARGING, "recv return msg is invalid, len: %{public}zd", len);
145f16e0440Sopenharmony_ci        return;
146f16e0440Sopenharmony_ci    }
147f16e0440Sopenharmony_ci
148f16e0440Sopenharmony_ci    // msg separator
149f16e0440Sopenharmony_ci    msg[len] = '\0';
150f16e0440Sopenharmony_ci    msg[len + 1] = '\0';
151f16e0440Sopenharmony_ci    if (!IsPowerSupplyEvent(msg)) {
152f16e0440Sopenharmony_ci        return;
153f16e0440Sopenharmony_ci    }
154f16e0440Sopenharmony_ci    UpdateBatteryInfo(service);
155f16e0440Sopenharmony_ci}
156f16e0440Sopenharmony_ci
157f16e0440Sopenharmony_civoid BatteryThread::UpdateBatteryInfo(void* service) {}
158f16e0440Sopenharmony_ci
159f16e0440Sopenharmony_cibool BatteryThread::IsPowerSupplyEvent(const char* msg)
160f16e0440Sopenharmony_ci{
161f16e0440Sopenharmony_ci    while (*msg) {
162f16e0440Sopenharmony_ci        if (!strcmp(msg, POWER_SUPPLY.c_str())) {
163f16e0440Sopenharmony_ci            return true;
164f16e0440Sopenharmony_ci        }
165f16e0440Sopenharmony_ci        while (*msg++) {} // move to next
166f16e0440Sopenharmony_ci    }
167f16e0440Sopenharmony_ci
168f16e0440Sopenharmony_ci    return false;
169f16e0440Sopenharmony_ci}
170f16e0440Sopenharmony_ci
171f16e0440Sopenharmony_ciint32_t BatteryThread::LoopingThreadEntry(void* arg)
172f16e0440Sopenharmony_ci{
173f16e0440Sopenharmony_ci    int32_t nevents = 0;
174f16e0440Sopenharmony_ci    size_t size = callbacks_.size();
175f16e0440Sopenharmony_ci    struct epoll_event events[size];
176f16e0440Sopenharmony_ci
177f16e0440Sopenharmony_ci    while (true) {
178f16e0440Sopenharmony_ci        if (!nevents) {
179f16e0440Sopenharmony_ci            CycleMatters();
180f16e0440Sopenharmony_ci        }
181f16e0440Sopenharmony_ci
182f16e0440Sopenharmony_ci        HandleStates();
183f16e0440Sopenharmony_ci
184f16e0440Sopenharmony_ci        int32_t timeout = epollInterval_;
185f16e0440Sopenharmony_ci        int32_t waitTimeout = UpdateWaitInterval();
186f16e0440Sopenharmony_ci        if ((timeout < 0) || (waitTimeout > 0 && waitTimeout < timeout)) {
187f16e0440Sopenharmony_ci            timeout = waitTimeout;
188f16e0440Sopenharmony_ci        }
189f16e0440Sopenharmony_ci
190f16e0440Sopenharmony_ci        nevents = epoll_wait(epFd_, events, static_cast<int32_t>(size), timeout);
191f16e0440Sopenharmony_ci        if (nevents <= 0) {
192f16e0440Sopenharmony_ci            continue;
193f16e0440Sopenharmony_ci        }
194f16e0440Sopenharmony_ci
195f16e0440Sopenharmony_ci        for (int32_t n = 0; n < nevents; ++n) {
196f16e0440Sopenharmony_ci            if (events[n].data.ptr) {
197f16e0440Sopenharmony_ci                auto* func = const_cast<BatteryThread*>(this);
198f16e0440Sopenharmony_ci                (callbacks_.find(events[n].data.fd)->second)(func, arg);
199f16e0440Sopenharmony_ci            }
200f16e0440Sopenharmony_ci        }
201f16e0440Sopenharmony_ci    }
202f16e0440Sopenharmony_ci}
203f16e0440Sopenharmony_ci
204f16e0440Sopenharmony_civoid BatteryThread::StartThread(void* service)
205f16e0440Sopenharmony_ci{
206f16e0440Sopenharmony_ci    Init(service);
207f16e0440Sopenharmony_ci    Run(service);
208f16e0440Sopenharmony_ci}
209f16e0440Sopenharmony_ci
210f16e0440Sopenharmony_civoid BatteryThread::Run(void* service) {}
211f16e0440Sopenharmony_ci} // namespace PowerMgr
212f16e0440Sopenharmony_ci} // namespace OHOS
213