受不了xxxx惡心人的行為,遂搬遷至博客園。 始發:2016-12-16 13:12:15 版本信息: Linux:3.10 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 device whenever 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,位於:
system/core/libsuspend
在初始化函數里面:
autosuspend_ops.h (system\core\libsuspend) struct autosuspend_ops { int (*enable)(void); int (*disable)(void); }; autosuspend.c (system\core\libsuspend) static int autosuspend_init(void) { if (autosuspend_inited) { return 0; } autosuspend_ops = autosuspend_earlysuspend_init(); if (autosuspend_ops) { goto out; } autosuspend_ops = autosuspend_autosleep_init(); if (autosuspend_ops) { goto out; } autosuspend_ops = autosuspend_wakeup_count_init(); if (autosuspend_ops) { goto out; } if (!autosuspend_ops) { ALOGE("failed to initialize autosuspend\n"); return -1; } out: autosuspend_inited = true; ALOGV("autosuspend initialized\n"); return 0; }
autosuspend_init()用於初始化autosuspend_ops結構體定義的enable和disable成員函數,autosuspend_ops的初始化有3個:
autosuspend_ops = autosuspend_earlysuspend_init(); autosuspend_ops = autosuspend_autosleep_init(); autosuspend_ops = autosuspend_wakeup_count_init();
按照順序依次執行,一旦某個執行成功,直接退出;autosuspend_ops即使初始化成功的值。
autosuspend_earlysuspend.c (system\core\libsuspend) struct autosuspend_ops *autosuspend_earlysuspend_init(void) { // #define EARLYSUSPEND_SYS_POWER_STATE "/sys/power/state" sPowerStatefd = open(EARLYSUSPEND_SYS_POWER_STATE, O_RDWR); // 向/sys/power/state文件寫入"on" ret = write(sPowerStatefd, "on", 2); // 寫入"on"的時候失敗,所以跳轉到err_write並退出被函數 if (ret < 0) { ALOGW("Error writing 'on' to %s: %s\n", EARLYSUSPEND_SYS_POWER_STATE, buf); goto err_write; } ALOGI("Selected early suspend\n"); start_earlysuspend_thread(); return &autosuspend_earlysuspend_ops; err_write: close(sPowerStatefd); return NULL; }
autosuspend_earlysuspend_init()初始化失敗,接着輪到autosuspend_autosleep_init():
autosuspend_autosleep.c (system\core\libsuspend) struct autosuspend_ops *autosuspend_autosleep_init(void) { int ret; char buf[80]; // #define SYS_POWER_AUTOSLEEP "/sys/power/autosleep" autosleep_fd = open(SYS_POWER_AUTOSLEEP, O_WRONLY); if (autosleep_fd < 0) { return NULL; } ALOGI("Selected autosleep\n"); autosuspend_autosleep_disable(); return &autosuspend_autosleep_ops; }
這里成功了!
autosuspend_autosleep.c (system\core\libsuspend) struct autosuspend_ops autosuspend_autosleep_ops = { .enable = autosuspend_autosleep_enable, .disable = autosuspend_autosleep_disable, }; static int autosuspend_autosleep_enable(void) { // static const char *sleep_state = "mem"; ret = write(autosleep_fd, sleep_state, strlen(sleep_state)); return 0; } static int autosuspend_autosleep_disable(void) { // static const char *on_state = "off"; ret = write(autosleep_fd, on_state, strlen(on_state)); return 0; }
所謂啟用autosleep,就是向"/sys/power/autosleep"文件寫入系統支持的休眠模式(從/sys/power/state文件讀取),比如這里的"mem"。一旦系統檢測到再沒有active的休眠鎖,就進入"mem"的休眠。
向"/sys/power/autosleep"文件寫入"off",禁止autosleep功能。
libsuspend.so向framework層提供enable、disable接口:
autosuspend.c (system\core\libsuspend) int autosuspend_enable(void) { ret = autosuspend_init(); if (autosuspend_enabled) { return 0; } ret = autosuspend_ops->enable(); autosuspend_enabled = true; return 0; } int autosuspend_disable(void) { ret = autosuspend_init(); if (!autosuspend_enabled) { return 0; } ret = autosuspend_ops->disable(); autosuspend_enabled = false; return 0; }
autosuspend_enable()、autosuspend_disable()的使用方:
com_android_server_power_PowerManagerService.cpp (frameworks\base\services\jni) static void nativeSetAutoSuspend(JNIEnv *env, jclass clazz, jboolean enable) { if (enable) { ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_enable() while turning screen off"); autosuspend_enable(); } else { ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_disable() while turning screen on"); autosuspend_disable(); } }
繼續跟蹤代碼我們知道,在屏幕點亮的時候,disable autosleep,屏幕暗下來后enable autosleep。
至此,autosleep在user空間的應用完成。