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:向该文件写入字串ABC,即ABC唤醒源置状态为“deactive”。
当所有唤醒源状态都为“deactive”,系统自动进入休眠状态,实现该功能的即是“autosleep”。
“autosleep”在2012年并入kernel的mainline,kernel版本3.5。
二、autosleep在framework
我们说Android现在“Opportunistic Suspend”的实现是autosleep,怎么证明?
Android向上层提供了操作休眠相关的接口(即读写/sys/power/目录下文件),即libsuspend.so,位于:
1. system/core/libsuspend
在初始化函数里面:
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. "failed to initialize autosuspend\n");
31. return -1;
32. }
33.
34. out:
35. true;
36.
37. "autosuspend initialized\n");
38. return 0;
39. }
autosuspend_init()用于初始化
autosuspend_ops结构体定义的enable和 disable成员函数, autosuspend_ops的初始化有3个:
1. autosuspend_ops = autosuspend_earlysuspend_init();
2. autosuspend_ops = autosuspend_autosleep_init();
3. autosuspend_ops = autosuspend_wakeup_count_init();
按照顺序依次执行,一旦某个执行成功,直接退出;
autosuspend
_ops即使初始化成功的值。
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. "on", 2);
9. // 写入"on"的时候失败,所以跳转到err_write并退出被函数
10. if (ret < 0) {
11. "Error writing 'on' to %s: %s\n", EARLYSUSPEND_SYS_POWER_STATE, buf);
12. goto err_write;
13. }
14. "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():
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. "Selected autosleep\n");
13. autosuspend_autosleep_disable();
14. return &autosuspend_autosleep_ops;
15. }
这里成功了!
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接口:
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. 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. false;
22. return 0;
23. }
autosuspend_enable()、autosuspend_disable()的使用方:
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. "Excessive delay in autosuspend_enable() while turning screen off");
5. autosuspend_enable();
6. else {
7. "Excessive delay in autosuspend_disable() while turning screen on");
8. autosuspend_disable();
9. }
10. }
继续跟踪代码我们知道,在屏幕点亮的时候,disable autosleep,屏幕暗下来后
enable
至此,
autosleep在user空间的应用完成