Android Healthd介绍
前言
为什么会有healthd这个进程?这个进程是用来干嘛的?这个进程是怎么做的?
简介
什么是healthd,百度一下应该就很清楚了,healthd是Android平台电量管理的一部分,在Android平台中电池电量数据是通过驱动节点的形式提供给用户空间层,所以上层要获得手机电池相关的硬件数据只需要去读取文件节点数据即可,其实healthd进程就是做的这么一个工作。负责读取值并把读取的结果通过通知给上层。
设备节点目录
power相关的文件节点是在目录/sys/class/power_supply/…
电池数据是在其中/sys/class/power_supply/battery/
在目录下ls看有哪些节点:
上图所示是高通平台提供的文件节点,包括了电池相关的数据。
代码实现
读取文件节点
在healthd中是如何读取文件节点的呢?我们知道healthd是通过init进程启动,在启动进入healthd进程中是通过如下代码读取文件节点数据
//system/core/healthd/BatteryMonitor.cpp
bool BatteryMonitor::update(void) {
bool logthis;
initBatteryProperties(&props);
......
healthd_mode_ops->battery_update(&props);
return props.chargerAcOnline | props.chargerUsbOnline |
props.chargerWirelessOnline;
}
healthd进程通过如上代码块读取设备文件节点数据并保存到props中.
进程分析
现在已经知道了healthd进程是在哪里读取信息的了,接下来就需要分析healthd进程的框架结构,省略init进程通过解析init.rc脚本启动healthd的过程,直接看healthd进程入口。
int main(int argc, char **argv) {
int ch;
int ret;
klog_set_level(KLOG_LEVEL);
healthd_mode_ops = &android_ops;//开机充电情况
if (!strcmp(basename(argv[0]), "charger")) {
healthd_mode_ops = &charger_ops;
} else {
while ((ch = getopt(argc, argv, "cr")) != -1) {
switch (ch) {
case 'c':
healthd_mode_ops = &charger_ops;//关机充电情况
break;
case 'r':
healthd_mode_ops = &recovery_ops;
break;
case '?':
default:
KLOG_ERROR(LOG_TAG, "Unrecognized healthd option: %c\n",
optopt);
exit(1);
}
}
}
ret = healthd_init();
if (ret) {
KLOG_ERROR("Initialization failed, exiting\n");
exit(2);
}
healthd_mainloop();
KLOG_ERROR("Main loop terminated, exiting\n");
return 3;
}
如上代码是healthd的入口,在开始的时候会判断是开机充电还是关机充电的状态,或者是recovery模式,接着初始化,然后进入一个无线循环。
这里以开机充电情况为线索进行分析
在healthd_init中主要是利用epoll监听了三个节点(fd),uevent_fd,wakealarm_fd,gBinderFd,注册相应的处理handler,然后在healthd_mainloop()中进行wait,等待事件发生并调用handler。
- uevent_fd : uevent事件,处理目录/sys/class/power_supply/ 的uevent事件
- wakealarm_fd :定时事件,定时对battery进行数据更新
- gBinderFd : binder调用相关事件,为何注册这个事件暂时不清楚。
在节点的事件处理中会调用BatteryMonitor.cpp中的update,在update中会有一句
healthd_mode_ops->battery_update(&props);用来notify batteryservice中注册的监听器。
这里主要简要介绍下healthd,更多的实现细节查看源码会了解更多。