1. 程式人生 > 實用技巧 >【Android休眠】之AutoSleep

【Android休眠】之AutoSleep

受不了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,螢幕暗下來後enableautosleep。
至此,autosleep在user空間的應用完成。