基本概念及流程说明
Android自从到4.4之后就摈弃了臃肿的wake lock 机制,使用linux3.4之后加上的 wakeup_souce机制。到底wakeup_source 机制是怎样工作的?在讲述之前,先化小篇幅讲讲android 在wake lock 机制跟wakeup_source之间切换的取舍缘由。这部分有参考网上的相关资料。
android4.4 之前一直是基于linux 加入 wake_lock 来阻止系统休眠,每启动一个应用程序,应用程序都可以申请一个 wakelock 锁,并且注册到内核,只要是系统中有一个wake lock 的时候,系统就不能进入休眠。当early suspend 时候的最后一步回去检查“main”锁,main 锁是系统启动完毕自动加的一个锁;然后去检查其他的锁,如果没有锁存在,则自动进入休眠。总结来说休眠的过程就是检查“锁”有没被释放,一旦所有的锁被释放,那么内核就会自动进入休眠。说到这里,提一下,以前一些平板方案在没有电源管理的情况下做假休眠,也是使用获取 wakelock 锁来阻止内核进入休眠。
linux3.4 加入了 wakeup_source 机制,android4.4 也跟着抛弃了wake lock 机制,缘用内核的 wakeup_source(对上层接口不变,wake_lock 实现是基于wakeup_source 来实现的) ,wakeup_source 不带debug信息。
wakeup_source 使用了 autosleep机制,只要不存在任何 active wake_source ,系统自动休眠。
还有 android4.4 去除了 earlysuspend 机制,改为 fb event 机制,那么现在只有 suspend ,resume 与 runtime suspend ,runtime resume 了。
Wake up source 在内核的核心代码这里不进行分析,我们直接进入主题。从android休眠,唤醒按键讲起。Android power按键有这样一个动作:按一下,进入休眠;休眠后,按一下,唤醒;如果长按达到3秒,关机。首先看看休眠唤醒过程的内核打印信息:由于信息太多,只贴内核信息。Android的log这里没贴出来。
add device 7: /dev/input/event0
/dev/input/event0: 0001 0074 00000001
/dev/input/event0: 0000 0000 00000000
/dev/input/event0: 0001 0074 00000000
/dev/input/event0: 0000 0000 00000000
mma enable setting inactive
request_suspend_state: sleep (0->3) at208709693024 (1970-01-02 00:03:34.037270002 UTC)
PM: Syncing filesystems ... done.
PM: Preparing system for mem sleep
suspend: start 7 suspend...
suspend: finish 7 suspend after:0.2598667seconds...
Freezing user space processes ... (elapsed0.01 seconds) done.
Freezing remaining freezable tasks ...(elapsed 0.01 seconds) done.
PM: Entering mem sleep
Suspending console(s) (useno_console_suspend to debug)
USB Host suspend begins
ehci_fsl_drv_suspend, pm event
host suspend ends
udc suspend begins
USB Gadget suspend ends
USB Host suspend begins
ehci_fsl_drv_suspend, pm event
host suspend ends
add wake up source irq 101
add wake up source irq 99
add wake up source irq 103
add wake up source irq 51
PM: suspend of devices complete after18.157 msecs
PM: late suspend of devices complete after0.707 msecs
Disabling non-boot CPUs ...
CPU1: shutdown
CPU2: shutdown
CPU3: shutdown
首先有按键的input事件说起,当内核检查到power按键后,进入中断函数,中断上半部分:读取按键状态,定时器去抖,通过调度把后面的内容交给下半部分处理;然后在中断的下半部分里面通过 input_event 把键值上报给系统。系统怎样读取上报的按键事件,可以查看《Android层面上对sensor及event事件的处理》 ,当系统接收到上报的键值后,结合在kl文件里面的键值映射:
key 116 POWER WAKE
响应power事件:
关屏,退出相关进程并保存用户状态信息,清wake_lock 锁。当android把所有的wake_lock锁清理完毕后,linux内核会自动进入休眠。
Linux内核会会依次做以下几件事情:
1、冻结用户进程和内核态任务
2、调用设备的 suspend 函数,其顺序为加载驱动的顺序
3、休眠核心设备和使CPU进入休眠tail,冻结进程是把进行列表中所有的进程的状态设置为停止,并保存进程的上下文
4、开唤醒中断
5、关闭除了cpu0 之外的其他的cpu
做完以上的过程后,cpu进入深度休眠。预留了外部唤醒中断,当唤醒中断产生电平(高电平,或者低电平唤醒)的时候,cpu又会被从新唤醒。唤醒过程就是休眠的逆过程。