Android 电源管理-Healthd(1)
19 Sep 2014OS:Android 4.4.2
Android电源管理底层用的是Linux power supply框架。驱动部分不叙述。只看JAVA、JNI和CPP应用层。
从Android 4.4开始,Google专门提供了一个healthd来监控电源状态。它的路径在:system/core/healthd
,编译出来的文件为/sbin/healthd
。
看一下healthd.cpp
中的main函数:
int main(int argc, char **argv) {
int ch;
klog_set_level(KLOG_LEVEL);
while ((ch = getopt(argc, argv, "n")) != -1) {
switch (ch) {
case 'n':
nosvcmgr = true;
break;
case '?':
default:
KLOG_WARNING(LOG_TAG, "Unrecognized healthd option: %c\n", ch);
}
}
healthd_board_init(&healthd_config);
wakealarm_init();
uevent_init();
binder_init();
gBatteryMonitor = new BatteryMonitor();
gBatteryMonitor->init(&healthd_config, nosvcmgr);
healthd_mainloop();
return 0;
}
这里引人关注的是最后调用的healthd_mainloop(),仅凭函数名就能知道会进入一个无限循环,这样也就能达到监控电源状态的目的了。跟踪代码看一下这个函数的定义:
static void healthd_mainloop(void) {
struct epoll_event ev;
int epollfd;
int maxevents = 0;
epollfd = epoll_create(MAX_EPOLL_EVENTS);
if (epollfd == -1) {
KLOG_ERROR(LOG_TAG,
"healthd_mainloop: epoll_create failed; errno=%d\n",
errno);
return;
}
if (uevent_fd >= 0) {
ev.events = EPOLLIN | EPOLLWAKEUP;
ev.data.ptr = (void *)uevent_event;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, uevent_fd, &ev) == -1)
KLOG_ERROR(LOG_TAG,
"healthd_mainloop: epoll_ctl for uevent_fd failed; errno=%d\n",
errno);
else
maxevents++;
}
if (wakealarm_fd >= 0) {
ev.events = EPOLLIN | EPOLLWAKEUP;
ev.data.ptr = (void *)wakealarm_event;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, wakealarm_fd, &ev) == -1)
KLOG_ERROR(LOG_TAG,
"healthd_mainloop: epoll_ctl for wakealarm_fd failed; errno=%d\n",
errno);
else
maxevents++;
}
if (binder_fd >= 0) {
ev.events = EPOLLIN | EPOLLWAKEUP;
ev.data.ptr= (void *)binder_event;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, binder_fd, &ev) == -1)
KLOG_ERROR(LOG_TAG,
"healthd_mainloop: epoll_ctl for binder_fd failed; errno=%d\n",
errno);
else
maxevents++;
}
while (1) {
struct epoll_event events[maxevents];
int nevents;
IPCThreadState::self()->flushCommands();
nevents = epoll_wait(epollfd, events, maxevents, awake_poll_interval);
if (nevents == -1) {
if (errno == EINTR)
continue;
KLOG_ERROR(LOG_TAG, "healthd_mainloop: epoll_wait failed\n");
break;
}
for (int n = 0; n < nevents; ++n) {
if (events[n].data.ptr)
(*(void (*)())events[n].data.ptr)();
}
if (!nevents)
periodic_chores();
}
return;
}
果不其然,我们看到了while(1)。Android使用了linux epoll来侦听三个文件描述符的变化,分别是uevent_fd、wakealarm_fd和binder_fd。以uevent_fd为例,在这个描述符上关心的事件有EPOLLIN和EPOLLWAKEUP,当底层出现这两个事件的时候,会回调函数uevent_event(),看看这个函数会做些什么:
#define UEVENT_MSG_LEN 1024
static void uevent_event(void) {
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_SUBSYSTEM)) {
battery_update();
break;
}
/* advance to after the next \0 */
while (*cp++)
;
}
}
它会读取socket中的字符串,然后判断事件来源是否是由kernel的power_supply发出的,如果是,那就调用battery_update()更新电源状态。下面来看看battery_update()是如何更新电源状态的:
static void battery_update(void) {
// Fast wake interval when on charger (watch for overheat);
// slow wake interval when on battery (watch for drained battery).
int new_wake_interval = gBatteryMonitor->update() ?
healthd_config.periodic_chores_interval_fast :
healthd_config.periodic_chores_interval_slow;
if (new_wake_interval != wakealarm_wake_interval)
wakealarm_set_interval(new_wake_interval);
// During awake periods poll at fast rate. If wake alarm is set at fast
// rate then just use the alarm; if wake alarm is set at slow rate then
// poll at fast rate while awake and let alarm wake up at slow rate when
// asleep.
if (healthd_config.periodic_chores_interval_fast == -1)
awake_poll_interval = -1;
else
awake_poll_interval =
new_wake_interval == healthd_config.periodic_chores_interval_fast ?
-1 : healthd_config.periodic_chores_interval_fast * 1000;
}
这里的重点是gBatteryMonitor->update(),gBatteryMonitor的类型为BatteryMonitor。那接下来就把目光专注到system/core/healthd/BatteryMonitor.h
和system/core/healthd/BatteryMonitor.cpp
在BatteryMonitor.h中,我们看到了一个enum,它列出了Android所支持的电源类型:
enum PowerSupplyType {
ANDROID_POWER_SUPPLY_TYPE_UNKNOWN = 0,
ANDROID_POWER_SUPPLY_TYPE_AC,
ANDROID_POWER_SUPPLY_TYPE_USB,
ANDROID_POWER_SUPPLY_TYPE_WIRELESS,
ANDROID_POWER_SUPPLY_TYPE_BATTERY
};
可以看出Android当前支持的电源类型有4种:AC,USB,WIRELESS,BATTERY。在这里你可以增加你自己的电源类型,比如CAR(车载)… …
把目光聚焦到BatteryMonitor.cpp
,这里有获取电源状态的核心代码。但是在继续看代码之前,我们先来看一下power_supply电源驱动是如何管理系统中的不同电源类型的。
呃,太晚咯,明天还加班,待续好了 。。。