【Android休眠】之AutoSleep

[cpp]  view plain  copy
  1. Linux 3.10  
  2. Android 4.4  

一、autosleep诞生记

由于《【Android休眠】之Android休眠机制》提到的“Android的特别需求”,Android提出了“Opportunistic Suspend”:Rather than trying to put the various system components into a low-power state, opportunistic suspend works by simply suspending the entire devicewhenever it is determined that nothing interesting is going on。如此简单粗暴,所以 “Opportunistic Suspend”从提出后就有着争议。

然后,接下来的问题就是:休眠时机。“nothing interesting is going on”的判断标准是什么?
Android给出的解决方案是“wakelocks”,也叫“suspend blockers”,只要有休眠锁存在(被kernel或user空间持有),就说明“something interesting is going on”,系统就不能休眠。

接下来的另一个问题:怎么阻止系统进入休眠?
Android给出的解决方案是“Early Suspend”,在进入休眠的过程中会先进入Android的“Early Suspend”路径,然后根据“wakelocks”的存在与否决定是否让系统休眠。由与这种做法改变了Linux kernel原生的PM流程,所以kernel开发者拒绝把“wakelocks”机制合并到kernel的mainline。

随着Android市场份额越来越大,在2011年的一次kernel讨论会中,Linus明确表态:kernel应该考虑把“suspend blockers”合并到mainline中了。
于是,kernel开发者着手实现了kernel的“wakelocks”:
/sys/power/wake_lock:向该文件写入字串ABC,即创建了一个名字ABC的唤醒源并置状态为“active”。
/sys/power/wake_unlock:向该文件写入字串ABCABC唤醒源置状态为“deactive”。
当所有唤醒源状态都为“deactive”,系统自动进入休眠状态,实现该功能的即是“autosleep”。

“autosleep”在2012年并入kernel的mainline,kernel版本3.5。

二、autosleep在framework

我们说Android现在“Opportunistic Suspend”的实现是autosleep,怎么证明?
Android向上层提供了操作休眠相关的接口(即读写/sys/power/目录下文件),即libsuspend.so,位于:
[cpp]  view plain  copy
  1. system/core/libsuspend  

在初始化函数里面:
[cpp]  view plain  copy
  1. autosuspend_ops.h (system\core\libsuspend)  
  2. struct autosuspend_ops {  
  3.     int (*enable)(void);  
  4.     int (*disable)(void);  
  5. };  
  6.   
  7. autosuspend.c (system\core\libsuspend)  
  8. static int autosuspend_init(void)  
  9. {  
  10.     if (autosuspend_inited) {  
  11.         return 0;  
  12.     }  
  13.   
  14.     autosuspend_ops = autosuspend_earlysuspend_init();  
  15.     if (autosuspend_ops) {  
  16.         goto out;  
  17.     }  
  18.   
  19.     autosuspend_ops = autosuspend_autosleep_init();  
  20.     if (autosuspend_ops) {  
  21.         goto out;  
  22.     }  
  23.   
  24.     autosuspend_ops = autosuspend_wakeup_count_init();  
  25.     if (autosuspend_ops) {  
  26.         goto out;  
  27.     }  
  28.   
  29.     if (!autosuspend_ops) {  
  30.         ALOGE("failed to initialize autosuspend\n");  
  31.         return -1;  
  32.     }  
  33.   
  34. out:  
  35.     autosuspend_inited = true;  
  36.   
  37.     ALOGV("autosuspend initialized\n");  
  38.     return 0;  
  39. }  

autosuspend_init()用于初始化 autosuspend_ops结构体定义的enable和 disable成员函数, autosuspend_ops的初始化有3个:
[cpp]  view plain  copy
  1. autosuspend_ops = autosuspend_earlysuspend_init();  
  2. autosuspend_ops = autosuspend_autosleep_init();  
  3. autosuspend_ops = autosuspend_wakeup_count_init();  

按照顺序依次执行,一旦某个执行成功,直接退出; autosuspend _ops即使初始化成功的值。
[cpp]  view plain  copy
  1. autosuspend_earlysuspend.c (system\core\libsuspend)  
  2. struct autosuspend_ops *autosuspend_earlysuspend_init(void)  
  3. {  
  4.     // #define EARLYSUSPEND_SYS_POWER_STATE "/sys/power/state"  
  5.     sPowerStatefd = open(EARLYSUSPEND_SYS_POWER_STATE, O_RDWR);  
  6.   
  7.     // 向/sys/power/state文件写入"on"  
  8.     ret = write(sPowerStatefd, "on", 2);  
  9.     // 写入"on"的时候失败,所以跳转到err_write并退出被函数  
  10.     if (ret < 0) {  
  11.         ALOGW("Error writing 'on' to %s: %s\n", EARLYSUSPEND_SYS_POWER_STATE, buf);  
  12.         goto err_write;  
  13.     }  
  14.     ALOGI("Selected early suspend\n");  
  15.     start_earlysuspend_thread();  
  16.     return &autosuspend_earlysuspend_ops;  
  17.       
  18. err_write:  
  19.     close(sPowerStatefd);  
  20.     return NULL;  
  21. }  

autosuspend_earlysuspend_init()初始化失败,接着轮到 autosuspend_autosleep_init():
[cpp]  view plain  copy
  1. autosuspend_autosleep.c (system\core\libsuspend)      
  2. struct autosuspend_ops *autosuspend_autosleep_init(void)  
  3. {  
  4.     int ret;  
  5.     char buf[80];  
  6.     // #define SYS_POWER_AUTOSLEEP "/sys/power/autosleep"  
  7.     autosleep_fd = open(SYS_POWER_AUTOSLEEP, O_WRONLY);  
  8.     if (autosleep_fd < 0) {  
  9.         return NULL;  
  10.     }  
  11.   
  12.     ALOGI("Selected autosleep\n");  
  13.     autosuspend_autosleep_disable();  
  14.     return &autosuspend_autosleep_ops;  
  15. }  

这里成功了!


[cpp]  view plain  copy
  1. autosuspend_autosleep.c (system\core\libsuspend)      
  2. struct autosuspend_ops autosuspend_autosleep_ops = {  
  3.         .enable = autosuspend_autosleep_enable,  
  4.         .disable = autosuspend_autosleep_disable,  
  5. };  
  6.   
  7. static int autosuspend_autosleep_enable(void)  
  8. {  
  9.     // static const char *sleep_state = "mem";  
  10.     ret = write(autosleep_fd, sleep_state, strlen(sleep_state));  
  11.     return 0;  
  12. }  
  13.   
  14. static int autosuspend_autosleep_disable(void)  
  15. {  
  16.     // static const char *on_state = "off";  
  17.     ret = write(autosleep_fd, on_state, strlen(on_state));  
  18.     return 0;  
  19. }  

所谓启用autosleep,就是向"/sys/power/autosleep"文件写入系统支持的休眠模式(从/sys/power/state文件读取),比如这里的"mem"。一旦系统检测到再没有active的休眠锁,就进入"mem"的休眠。
"/sys/power/autosleep"文件写入"off",禁止autosleep功能。

libsuspend.so向framework层提供enable、disable接口: 
[cpp]  view plain  copy
  1. autosuspend.c (system\core\libsuspend)  
  2. int autosuspend_enable(void)  
  3. {  
  4.     ret = autosuspend_init();  
  5.     if (autosuspend_enabled) {  
  6.         return 0;  
  7.     }  
  8.     ret = autosuspend_ops->enable();  
  9.   
  10.     autosuspend_enabled = true;  
  11.     return 0;  
  12. }  
  13.   
  14. int autosuspend_disable(void)  
  15. {  
  16.     ret = autosuspend_init();  
  17.     if (!autosuspend_enabled) {  
  18.         return 0;  
  19.     }  
  20.     ret = autosuspend_ops->disable();  
  21.     autosuspend_enabled = false;  
  22.     return 0;  
  23. }  

autosuspend_enable()、autosuspend_disable()的使用方:
[cpp]  view plain  copy
  1. com_android_server_power_PowerManagerService.cpp (frameworks\base\services\jni)  
  2. static void nativeSetAutoSuspend(JNIEnv *env, jclass clazz, jboolean enable) {  
  3.     if (enable) {  
  4.         ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_enable() while turning screen off");  
  5.         autosuspend_enable();  
  6.     } else {  
  7.         ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_disable() while turning screen on");  
  8.         autosuspend_disable();  
  9.     }  
  10. }  

继续跟踪代码我们知道,在屏幕点亮的时候,disable autosleep,屏幕暗下来后 enable autosleep。
至此, autosleep在user空间的应用完成
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值