Understanding the Android Power Supply Subsystem and healthd Daemon
The article explains how Android’s Linux power‑supply subsystem abstracts battery and charger status via sysfs nodes, how drivers register properties and trigger uevents, and how the healthd daemon listens to those events, parses attributes, and forwards detailed power information to user space.
The article introduces the author’s experience as a kernel beginner who often knows "what" but not "why" when dealing with the power supply (psy) subsystem in Linux. It explains how properties (prop) are added, how sysfs nodes are created, and how user space reads these nodes to obtain power information.
Android Power Supply Framework
The power supply subsystem (psy) is an abstraction layer in the Linux kernel that aggregates power‑related status information for user space. It resides under /sys/class/power_supply/ and includes devices such as batteries and chargers (e.g., battery.c , charger.c ). Drivers update psy nodes when hardware events occur, and the HAL reads these nodes.
Power Supply Subsystem Overview
The psy subsystem builds on the device‑driver model, using class, device, kobject, sysfs, and uevent mechanisms. Each power supply device appears as a directory under /sys/class/power_supply/ , with individual attributes represented as files (kobjects).
Key Structures
The main definitions are in include/linux/power_supply.h . The most important structure is psy_desc , which describes a power supply’s properties, set/get callbacks, and write permissions. The struct power_supply represents a concrete power device (battery, AC, USB) and is typically registered via devm_power_supply_register after defining its psy_desc .
Relevant Interface Functions
Core logic resides in psy_core.c (handling state changes) and psy_sysfs.c (exposing sysfs nodes). The pivotal function power_supply_changed triggers the changed_work workqueue, which sends kernel notifiers and uevents.
Call Flow
The workqueue power_supply_changed_work processes hardware state changes. By adding trace prints to a driver’s get_property function, one can follow the call chain from the interrupt to the uevent broadcast via kobject_uevent_env and netlink_broadcast . The broadcast string format is action_string@devpath , where action is the kobject action and devpath identifies the psy device.
healthd Overview
Because uevents only convey a simple string, Android introduces the healthd daemon to translate these events into detailed power information for user space. healthd listens to kernel uevents using epoll_wait , parses the netlink payload, and updates a HealthInfo structure. The update flow involves BatteryMonitor::updateValues , which reads psy attributes and notifies the system via the Binder interface ( BinderHealth::OnHealthInfoChanged ).
The relevant source paths are /hardware/interfaces/health/ and /system/core/healthd/ . healthd’s main loop continuously calls epoll_wait to receive uevents, filters those originating from the psy subsystem, and then aggregates attribute values.
Summary
The power supply architecture efficiently leverages uevent and sysfs to expose hardware‑independent power data. healthd decouples kernel updates from user‑space consumption by using epoll‑based event listening and periodic attribute polling. Together, they provide a clear, extensible example for newcomers to kernel driver development and Android power management.
OPPO Kernel Craftsman
Sharing Linux kernel-related cutting-edge technology, technical articles, technical news, and curated tutorials
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.