zoukankan      html  css  js  c++  java
  • 【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 (systemcorelibsuspend)
    struct autosuspend_ops {
        int (*enable)(void);
        int (*disable)(void);
    };
     
    autosuspend.c (systemcorelibsuspend)
    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
    ");
            return -1;
        }
     
    out:
        autosuspend_inited = true;
     
        ALOGV("autosuspend initialized
    ");
        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 (systemcorelibsuspend)
    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
    ", EARLYSUSPEND_SYS_POWER_STATE, buf);
    		goto err_write;
    	}
    	ALOGI("Selected early suspend
    ");
    	start_earlysuspend_thread();
    	return &autosuspend_earlysuspend_ops;
    
    	err_write:
    	close(sPowerStatefd);
    	return NULL;
    }
    

    autosuspend_earlysuspend_init()初始化失败,接着轮到autosuspend_autosleep_init():

    autosuspend_autosleep.c (systemcorelibsuspend)	
    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
    ");
        autosuspend_autosleep_disable();
        return &autosuspend_autosleep_ops;
    }
    

      

    这里成功了!

    autosuspend_autosleep.c (systemcorelibsuspend)	
    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 (systemcorelibsuspend)
    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 (frameworksaseservicesjni)
    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空间的应用完成。

  • 相关阅读:
    对象池使用时要注意几点
    Flash3D学习计划(一)——3D渲染的一般管线流程
    714. Best Time to Buy and Sell Stock with Transaction Fee
    712. Minimum ASCII Delete Sum for Two Strings
    647. Palindromic Substrings(马拉车算法)
    413. Arithmetic Slices
    877. Stone Game
    338. Counting Bits
    303. Range Sum Query
    198. House Robber
  • 原文地址:https://www.cnblogs.com/rockyching2009/p/13283821.html
Copyright © 2011-2022 走看看