现在的位置: 首页 > 综合 > 正文

Andriod PM suspend&resume

2012年05月20日 ⁄ 综合 ⁄ 共 3350字 ⁄ 字号 评论关闭


源出处:http://www.61ic.com/Mobile/Android/201102/29414.html


Android 的电源管理还是比较简单的 主要就是通过锁和定时器来切换系统的状态 , 使系统的功耗降至最低 , 整个系统的电源管理架构图如下 :
(
 
注该图来自 Steve Guo)

 

 


1 、初始化 suspend 和 resume 函数

static struct platform_driver mxcbl_driver = {

       .probe = mxcbl_probe,

       .remove = mxcbl_remove,

       .suspend = mxcbl_suspend,

       .resume = mxcbl_resume,

       .driver = {

                 .name = "mxc_mc13892_bl",

                 },

};

2 、系统 Suspend 和 resume 的函数流程

取一个例子

加入 suspend 和 resume

mxc_board_init-->mxc_init_bl()-->platform_device_register()-->platform_device_add()-->device_add()-->device_pm_add()--> ,最终加入到了 dpm_list 的链表中,在其中的 dpm_suspend 和 dpm_suspend 中通过遍历这个链表来进行查看哪个 device 中包含 suspend 和 resume 项。

 

系统唤醒和休眠

Kernel 层 [ 针对 Android
Linux2.6.28
 
内核 ]:

其主要代码在下列位置 :

Drivers/base /main.c

kernel/power /main.c

kernel/power/wakelock.c

kernel/power/earlysuspend.c

其对 Kernel 提供的接口函数有

EXPORT_SYMBOL(wake_lock_init); // 初始化 Suspend lock, 在使用前必须做初始化

EXPORT_SYMBOL(wake_lock); // 申请 lock, 必须调用相应的 unlock 来释放它

static DEFINE_TIMER(expire_timer, expire_wake_locks, 0, 0);// 定时时间到,加入到 suspend 队列中;

EXPORT_SYMBOL(wake_unlock); // 释放 lock

EXPORT_SYMBOL_GPL(device_power_up);// 打开特殊的设备

EXPORT_SYMBOL_GPL(device_power_down);// 关闭特殊设备

EXPORT_SYMBOL_GPL(device_resume);// 重新存储设备的状态;

EXPORT_SYMBOL_GPL(device_suspend);: 保存系统状态,并结束掉系统中的设备;

EXPORT_SYMBOL(register_early_suspend); // 注册 early suspend 的驱动

EXPORT_SYMBOL(unregister_early_suspend); // 取消已经注册的 early suspend 的驱动

 

函数的流程如下所示:

应用程序通过对 state_store 的写入操作可以使系统进行休眠的状态。 pm_states 包括 PM_SUSPEND_ON , PM_SUSPEND_STANDBY , PM_SUSPEND_M 满足个状态。当状态位 PM_SUSPEND_ON 的状态的时候,调用 request_suspend_state() ;当满足休眠的状态的时候,调用 queue_work(suspend_work_queue,&early_suspend_work), 调用了 early_suspend ,然后在其中通过 wake_unlock() 启动了 expire_timer 定时器,当定时时间到了,则执行 expire_wake_locks ,将 suspend_work 加入到队列中,分析到这里就可以知道了 early_suspend_work 和 suspend_work 这两个队列的先后顺序了, suspend 调用了 pm_suspend ,通过判断当前的状态,选择 enter_state() ,在 enter_state 中,经过了 suspend_prepare , suspend_test 和 suspend_device_and_enter() ,在 suspend_device_and_enter 中调用了 device_suspend 来保存状态和结束系统的设备,到了 dpm_suspend 中结束所有的 device 。到了这里,我们就又可以看见在初始化的时候所看到的队列 dpm_list 

 

Android 的电源管理主要是通过 Wake lock 来实现的 , 在最底层主要是通过如下队列来实现其管理 :

LIST_HEAD(dpm_list);

 

 

系统正常开机后进入到 AWAKE 状态 , Backlight 会从最亮慢慢调节到用户设定的亮度 , 系统 screen
off timer(settings->sound & display-> Display settings -> Screen timeout)
 
开始计时 , 在计时时间到之前 , 如果有任何的 activity 事件发生 , 如 Touch
click, keyboard pressed
 
等事件 则将 Reset screen off timer, 系统保持在 AWAKE 状态 如果有应用程序在这段时间内申请了 Full
wake lock,
 
那么系统也将保持在 AWAKE 状态 除非用户按下 power
key. 
在 AWAKE 状态下如果电池电量低或者是用 AC 供电 screen
off timer
 
时间到并且选中 Keep screen on while pluged in 选项 ,backlight 会被强制调节到 DIM 的状态 .

如果 Screen off timer 时间到并且没有 Full wake lock 或者用户按了 power
key,
 
那么系统状态将被切换到 NOTIFICATION, 并且调用所有已经注册的 g_early_suspend_handlers 函数 通常会把 LCD 和 Backlight 驱动注册成 early
suspend
 
类型 , 如有需要也可以把别的驱动注册成 early suspend, 这样就会在第一阶段被关闭 接下来系统会判断是否有 partial
wake lock acquired, 
如果有则等待其释放 在等待的过程中如果有 user activity 事件发生 , 系统则马上回到 AWAKE 状态 ;如果没有 partial
wake lock acquired, 
则系统会马上调用函数 pm_suspend 关闭其它相关的驱动 让 CPU 进入休眠状态 .

系统在 Sleep 状态时如果检测到任何一个 Wakeup source, 则 CPU 会从 Sleep 状态被唤醒 , 并且调用相关的驱动的 resume 函数 , 接下来马上调用前期注册的 early
suspend
 
驱动的 resume 函数 , 最后系统状态回到 AWAKE 状态 . 这里有个问题就是所有注册过 early
suspend
 
的函数在进 Suspend 的第一阶段被调用可以理解 , 但是在 resume 的时候 ,
Linux
 
会先调用所有驱动的 resume 函数 , 而此时再调用前期注册的 early
suspend
 
驱动的 resume 函数有什么意义呢 ?个人觉得 android 的这个 early
suspend
 
和 late resume 函数应该结合 Linux 下面的 suspend 和 resume 一起使用 , 而不是单独的使用一个队列来进行管理 .

抱歉!评论已关闭.