diff --git a/health/utils/libhealthloop/HealthLoop.cpp b/health/utils/libhealthloop/HealthLoop.cpp index d43c2d51ce..691d8966e6 100644 --- a/health/utils/libhealthloop/HealthLoop.cpp +++ b/health/utils/libhealthloop/HealthLoop.cpp @@ -43,6 +43,8 @@ namespace android { namespace hardware { namespace health { +static constexpr uint32_t kUeventMsgLen = 2048; + HealthLoop::HealthLoop() { InitHealthdConfig(&healthd_config_); awake_poll_interval_ = -1; @@ -61,14 +63,13 @@ int HealthLoop::RegisterEvent(int fd, BoundFunction func, EventWakeup wakeup) { EventHandler{this, fd, std::move(func)})) .get(); - struct epoll_event ev; - - ev.events = EPOLLIN; + struct epoll_event ev = { + .events = EPOLLIN, + .data.ptr = reinterpret_cast(event_handler), + }; if (wakeup == EVENT_WAKEUP_FD) ev.events |= EPOLLWAKEUP; - ev.data.ptr = reinterpret_cast(event_handler); - if (epoll_ctl(epollfd_, EPOLL_CTL_ADD, fd, &ev) == -1) { KLOG_ERROR(LOG_TAG, "epoll_ctl failed; errno=%d\n", errno); return -1; @@ -121,32 +122,39 @@ void HealthLoop::PeriodicChores() { ScheduleBatteryUpdate(); } -#define UEVENT_MSG_LEN 2048 -void HealthLoop::UeventEvent(uint32_t /*epevents*/) { - // No need to lock because uevent_fd_ is guaranteed to be initialized. - - char msg[UEVENT_MSG_LEN + 2]; - char* cp; - int n; - - n = uevent_kernel_multicast_recv(uevent_fd_, msg, UEVENT_MSG_LEN); - if (n <= 0) return; - if (n >= UEVENT_MSG_LEN) /* overflow -- discard */ - return; - - msg[n] = '\0'; - msg[n + 1] = '\0'; - cp = msg; - - while (*cp) { - if (!strcmp(cp, "SUBSYSTEM=power_supply")) { - ScheduleBatteryUpdate(); - break; +// Returns true if and only if the battery statistics should be updated. +bool HealthLoop::RecvUevents() { + bool update_stats = false; + for (;;) { + char msg[kUeventMsgLen + 2]; + int n = uevent_kernel_multicast_recv(uevent_fd_, msg, kUeventMsgLen); + if (n <= 0) return update_stats; + if (n >= kUeventMsgLen) { + // too long -- discard + continue; + } + if (update_stats) { + continue; } - /* advance to after the next \0 */ - while (*cp++) - ; + msg[n] = '\0'; + msg[n + 1] = '\0'; + for (char* cp = msg; *cp;) { + if (strcmp(cp, "SUBSYSTEM=power_supply") == 0) { + update_stats = true; + break; + } + + /* advance to after the next \0 */ + while (*cp++) { + } + } + } +} + +void HealthLoop::UeventEvent(uint32_t /*epevents*/) { + if (RecvUevents()) { + ScheduleBatteryUpdate(); } } @@ -183,9 +191,9 @@ void HealthLoop::UeventInit(void) { std::string error_msg = attach_result.error().message(); error_msg += ". This is expected in recovery mode and also for kernel versions before 5.10."; - KLOG_WARNING(LOG_TAG, "%s", error_msg.c_str()); + KLOG_WARNING(LOG_TAG, "%s\n", error_msg.c_str()); } else { - KLOG_INFO(LOG_TAG, "Successfully attached the BPF filter to the uevent socket"); + KLOG_INFO(LOG_TAG, "Successfully attached the BPF filter to the uevent socket\n"); } if (RegisterEvent(uevent_fd_, &HealthLoop::UeventEvent, EVENT_WAKEUP_FD)) diff --git a/health/utils/libhealthloop/include/health/HealthLoop.h b/health/utils/libhealthloop/include/health/HealthLoop.h index 1af7274729..43c38dca10 100644 --- a/health/utils/libhealthloop/include/health/HealthLoop.h +++ b/health/utils/libhealthloop/include/health/HealthLoop.h @@ -93,6 +93,7 @@ class HealthLoop { void WakeAlarmInit(); void WakeAlarmEvent(uint32_t); void UeventInit(); + bool RecvUevents(); void UeventEvent(uint32_t); void WakeAlarmSetInterval(int interval); void PeriodicChores();