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空间的应用完成。

  • 相关阅读:
    css-使不同大小的图片在固定大小的容器中居中
    js-数组中查找特定元素并返回所有该元素的索引
    js-权威指南学习笔记5
    js-权威指南学习笔记4
    js-权威指南学习笔记3
    JavaScript中的类型转换
    js-权威指南学习笔记2
    通过维基API实现维基百科查询功能
    【代码笔记】iOS-FMDBDemo
    【代码笔记】iOS-自定义switch
  • 原文地址:https://www.cnblogs.com/rockyching2009/p/13283821.html
Copyright © 2011-2022 走看看