Android 中电源状态切换_pillarbuaa的博客-程序员秘密

技术标签: Android 模块-power  

在 Android 的上层是使用 goToSleep() 这个函数让系统进入休眠的。但是这个命令为什么会让 Android 进入 Suspend Mode。
 
以前在做其他系统的时候, 一般都要自己手工去控制 apm_bios 这个设备的,比如使用 ioctl() 调用 apm_bios。所有的系统其原理都是差不多的。只是 Android 加入了一个封装, 使程序员可以更简单的操作, 可以不理会底层是如何操作的, 现在解析一个 goToSleep() 是如何工作的。
 
PowerManagerService.java 是 framework 层负责管理 PowerManager 的。goToSleep 就是在这个函数中定义的:
 
goToSleep()->
   goToSleepLocked()->
      setPowerState()->
          setScreenStateLocked()->
             Power.setScreenState(on);  // android_os_Power.cpp
 
goToSleep() 在 PowerManagerService.java 中经过一系列的处理之后, 最终会进入 android_os_Power.cpp 文件中的 setScreenState() 这个函数中。
 
看一下 setScreenState() 的实现:
 
// android_os_Power.cpp
static int
setScreenState(JNIEnv *env, jobject clazz, jboolean on)
{
    return set_screen_state(on);
}
而 set_screen_state() 在 power.c 文件中实现:
int
set_screen_state(int on)
{
    QEMU_FALLBACK(set_screen_state(on));
    LOGI("*** set_screen_state %d", on);
    initialize_fds();
    //LOGI("go_to_sleep eventTime=%lld now=%lld g_error=%s\n", eventTime,
      //      systemTime(), strerror(g_error));
    if (g_error) return g_error;
    char buf[32];
    int len;
    if(on)
        len = sprintf(buf, on_state);
    else
        len = sprintf(buf, off_state);
    len = write(g_fds[REQUEST_STATE], buf, len);
    if(len < 0) {
        LOGE("Failed setting last user activity: g_error=%d\n", g_error);
    }
    return 0;
}
可以发现, 其最终是通过 write(g_fds[REQUEST_STATE], buf, len); 令系统进入休眠的。
 
通过分析这个文件的代码, g_fds[REQUEST_STATE] = open("/sys/power/state", O_RDWR);
 
on_state = "wake", off_state = "standby", 也就是写 standby 到 /sys/power/state 就可以令系统进行休眠了。
 
/sys/power/state 的实现代码可以看 $(Kernel)/kernel/power/main.c 这个文件是怎么实现的。
 
所以,当文件系统起来的时候可以 echo standby > /sys/power/state 令系统进入休眠

 

 

 

1, Android中支持的电源状态:

        PM_SUSPEND_ON -- 设备处于全电源状态,也就是正常工作状态;

        PM_SUSPEND_MEM -- suspend to memory,设备进入睡眠状态,但所有的数据还保存在内存中,只有某些外部中断才可以唤醒设备。

       PM_SUSPEND_STANDBY  ----- 在大部分的Android设备中均不支持。

 

2, Early Suspend / Late Resume

         在Android中,增加了系统休眠的层次,把休眠划分为深度睡眠(sleep)和浅度睡眠(idle)。  

         因此当系统往 /sys/power/state 节点写入 mem (如在命令行 写入: echo mem > /sys/power/state) 将会使系统进入睡眠。参考HAL中:hardware/libhardware_legacy/power/power.c  :  set_screen_state   ------> write (on / mem )   to  /sys/power/state

         浅度睡眠 仅仅是关掉背光,fb, sensor,触摸屏等在关屏状态下不需要使用的设备,而整个CPU和大部分外设还是正常工作的。

                                                   

            深度睡眠sleep 与 浅度睡眠 idle 之间切换的过程如上所示。

 

3,  Android的 Wake Lock

          Android系统提供了两种类型的锁:

                   WAKE_LOCK_SUSPEND  --  阻止系统进入suspend状态;

                   WAKE_LOCK_IDLE  --  阻止系统进入idle状态;

                   wake lock 可以设置超时释放,在持有wake lock一个固定时间之后自动释放。一般应用在系统正在处理一些事情的时候,防止系统进入深度睡眠而干扰了正在处理的任务; 尤其是在做了硬件唤醒的,当唤醒之后要处理一些响应,为了防止系统马上再次进入休眠,在设置一个超时锁。

          如系统能否进入深度睡眠,当系统处在idle时,会不断判断是否还有WAKE_LOCK_SUSPEND

        

4,  电源状态切换的调试:

           /sys/power/state

          /sys/power/wake_lock

          /sys/power/wake_unlock

          1)  cat  /sys/power/state -----查看系统状态,  echo mem > /sys/power/state    ---- 将系统设置为进入休眠

          2) echo "name"    > /sys/power/wake_lock ----- 申请一个锁

                 cat /sys/power/wake_lock -----查看系统的wake lock 情况

                 wake_unlock 同样。

 

         3)  echo 15 > /sys/module/wakelock/parameters/debug_mask   ------------

               这样wakelock的驱动会把每次的wakelock操作都打印在console上,对于调试为什么suspend不下去这类的问题很有用。如下所示:

               [ 1062.912297] wake_lock: mmc_delayed_work, stop expire timer
               [ 1062.922395] wake_unlock: mmc_delayed_work, start expire timer, 990
               [ 1062.931174] wake_lock: event0-79, start expire timer, 989
               [ 1062.933710] wake_lock: event0-79, start expire timer, 989
               [ 1062.939081] wake_lock: event0-79, start expire timer, 989
               [ 1062.961143] wake_lock: event0-79, start expire timer, 986

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/pillarbuaa/article/details/9032205

智能推荐

随机生成指定长度的数字+字符的密码_andai5096的博客-程序员秘密

/// &lt;summary&gt; /// 生成随机数的种子 /// &lt;/summary&gt; /// &lt;returns&gt;&lt;/returns&gt; private static int getNewSeed() { byte[] rndBytes = new byte[4];...

struts2 strus.xml中result类型及含义_hua156607544的博客-程序员秘密

struts2 strus.xml中result类型及含义一个提交到服务器的处理通常可以分为两个阶段,第一个阶段查询服务器状态(查询或者更新数据库),第二个阶段选择一个合适的结果页面其返回给用户(这里要讲的Result的内容)。Struts2提供了对不同种类返回结果的支持,常见的有JSP,FreeMarker,Velocity等。Struts2支持的不同类型的返回结果为:名字说...

python异常(概念、捕获、传递、抛出)_weixin_30600503的博客-程序员秘密

异常目标异常的概念捕获异常异常的传递抛出异常01. 异常的概念程序在运行时,如果Python 解释器遇到到一个错误,会停止程序的执行,并且提示一些错误信息,这就是异常程序停止执行并且提示错误信息这个动作,我们通常称之为:抛出(raise)异常程序开发时,很难将所有的特殊情况都处理的面面俱到,通过异常捕获可以针对突发事件...

Socket异步通信——使用SocketAsyncEventArgs_weixin_33964094的博客-程序员秘密

  上一次的博文说错了东西,幸好有园友指出。才把错误改正过来,顺便也把利用SocketAsyncEventArgs进行Socket异步通信这方面的知识整理一下。      之前看了网上的代码,每进行一次异步操作都new 一个SocketAsyncEventArgs对象,然后网友评论太浪费资源了,于是就误以为用BeginXXX进行Socket异步通信会更优,幸好有园友指出我的误区,再看了这篇文章...

Linux C中readdir()函数:读取目录函数_丶Apache的博客-程序员秘密_linux readdir

头文件:#include &amp;lt;sys/types.h&amp;gt;   #include &amp;lt;dirent.h&amp;gt;函数原型:struct dirent * readdir(DIR * dir);函数功能:readdir()返回参数dir 目录流的下个目录进入点。结构dirent 定义如下:             struct dirent             {      ...

两个线程之间的同步(生产者与消费者问题)性能优化_彼岸述道的博客-程序员秘密

计算机中很经典的生产者与消费者的问题,生产者要等到产品消耗完之后才能进行生产,消费者都要等到产品生产完成之后才能消费,也就是说,生产者要等到消费者消费完产品之后才能进行生产,消费者要等到生产者生产完产品之后才能进行消费。 生产者与消费者之间的关系: 生产者>>判断产品是否为空>>空>>生产产品 生产者>>判断产品是否为空>>不空>>不生产产品 消费者>>判断产品是否为空>>空>>不消费产产品

随便推点

郭天祥的10天学会51单片机_第十节_小乖乖_学技术的博客-程序员秘密_十天学会51单片机郭天祥

要多练,多练C语言程序,练习C语言程序编程思路,可以把别人的程序改改,找些电路焊接调试AD985可以产生方波,三角波,正弦波低通滤波器是通过低频阻止高频,作用是滤除杂波液晶显示单片机状态运算放大器放大波形积分器将方波积分成三角波AD985里面有比较器可以将正弦波变成方波AD985是5伏的,单片机是3伏的,两者之间要有个电压转换器数码管不仅可以用锁存器来驱动,也可以用三极管来驱动一个函数用来刷新秒,分,时键盘调节用三个键:功能键(秒的光标在闪烁,此时可以调节时间,分和小

asp.net GridView手写事件,包括取主键、取值、更新、选择、删除_weixin_30307267的博客-程序员秘密

图片是本网站后台的友情链接管理页面:前两者的代码比较固定,一般都是:代码如下复制代码protected void gvFriendLink_RowEditing(object sender, GridViewEditEventArgs e){ gvFriendLink.EditIndex = e.NewEditIndex; ...

yarn : 无法加载文件 C:\Users\Administrator\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本_gblfy的博客-程序员秘密

2、若要在本地计算机上运行您编写的未签名脚本和来自其他用户的签名脚本,请使用以下命令将计算机上的 执行策略更改为 RemoteSigned执行:set-ExecutionPolicy RemoteSigned3、查看执行策略:get-ExecutionPolicy关闭命令窗口 即可...

mvc dao层、service层 到底怎么写?_码不动代码的板鸭的博客-程序员秘密_dao层和service层怎么写

首先解释面上意思,service是业务层,dao是数据访问层。呵呵,这个问题我曾经也有过,记得以前刚学编程的时候,都是在service里直接调用dao,service里面就new一个dao类对象,调用,其他有意义的事没做,也不明白有这个有什么用,参加工作久了以后就会知道,业务才是工作中的重中之重。我们都知道,标准主流现在的编程方式都是采用MVC综合设计模式,MVC本身不属于设计模式的一种,

Android WEBVIEW中调用<a href>的问题!!!不是js的方法_xyr玩很6的博客-程序员秘密

mWebView.setWebViewClient(new WebViewClient(){ @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { handler.proceed(); } @Override

Zbar+ROS+opencv二维码识别与定位研究(一)_su扬帆启航的博客-程序员秘密_ros 二维码定位

1.本文利用二维码的边缘信息,对其进行定位,经检验在3-4m以内有良好的定位效果2.主要步骤:原图像大小调整,提高运算效率;转化为灰度图;高斯平滑滤波;求得水平和垂直方向灰度图像的梯度差,使用Sobel算子;开运算,消除亮度较高的细小区域,先腐蚀后膨胀;均值滤波,消除高频噪声;二值化;膨胀,根据核的大小,有可能需要6次膨胀操作;通过findContours找到条形码区域的矩形边界...

推荐文章

热门文章

相关标签