android 2.3 电源管理

来源:互联网 发布:java 关闭 一个 进程 编辑:程序博客网 时间:2024/05/01 23:42

原文出处不详, 如有冒犯敬请谅解.


1. 介绍
  这是一篇关于Android电源管理的文章, 适合应用程序开发人员和驱动开发人员和FrameWork开发人员阅读。

2. 前言

  Android系统出于节电的需要, 一般应用在用户一段时间无操作的情况下屏幕变暗, 然后进后休眠状态, 此时cpu处于挂起状态, 屏幕处于关闭状态。 用户只能在”设置->声音和显示”中设置所有应用默认的屏幕亮度和系统无操作多久进入睡眠的时间。  当然这种管理模式并不适合于所有的应用, 比如当看电影的时候总不希望系统隔一段时间就进入睡眠吧。所以Android系统为这种有特殊需求的应用提供了可以不遵守规矩的Api, 通过使用这种Api可以打破默认情况下的电源管理模式。

3.  应用程序开发相关  3.1.  Api的使用

     只需要熟悉android.os.PowerManager和android.os.PowerManager.WakeLock这两个类的Api就足够了, 当需要用到这些Api时, 需要在Manifest.xml添加如下权限:     <uses-permission android:name="android.permission.WAKE_LOCK" />     <uses-permission android:name="android.permission.DEVICE_POWER" />     很重要的一个概念就是WakeLock, 系统中定义了六种WakeLock, 常用的有4个:

 CPUScreenKeyboard LightPARTIAL_WAKE_LOCKonoffoffSCREEN_DIM_WAKE_LOCKondimoffSCREEN_BRIGHT_WAKE_LOCKononoffFULL_WAKE_LOCKononon

    对WakeLock有两种操作:获取和释放。获取后当系统需要睡眠时就会进入所获取的WakeLock代表的状态。 实例代码如下:

[java] view plaincopyprint?
  1. PowerManager mPm;  
  2. WakeLock mWakeLock;  
  3.   
  4. mWakeLock = mPm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "WhatEver");  
  5. mWakeLock.acquire();  
  6. //cpu on, screen dim, keyboard light off  
  7. //...  
  8.           
  9. mWakeLock.release();  

    如上面代码所示, 如果系统在获取锁后一段时间无操作就会进入SCREEN_DIM_WAKE_LOCK锁所对应的状态。

  另外还有两个比较特殊的锁:

l          ACQUIRE_CAUSES_WAKEUP:一旦有请求锁时强制打开Screen和keyboard light 
l          ON_AFTER_RELEASE:当lock被释放后,通过reset user activity timer使屏幕多亮一会儿

关于api更加详细的内容请参考官方文档。

  3.24.  注意事项
  l  使用WakeLock会增加系统功耗,所以原则上是只有必要的时候才用
  l  所有的锁必须成对的使用, 如申请了PARTIAL_WAKE_LOCK, 而没有及时释放,那系统就永远进不了Sleep模式,这会严重影响手持设备的待机时间。

4.   驱动程序开发相关
  值得注意的是,写Android的linux驱动时也要记得系统随时都可能suspend。有些驱动需要关心early suspend和later resume, 比如early suspend时framebuffer驱动的dma应该可以休息了。有些驱动则需要在某个过程中系统不能睡眠,比如usb gadget driver向pc传文件的过程中系统就不能睡眠,睡了就传不完了, 这就需要在这个过程前后获得而后释放锁。 有些驱动向某个设备发送命令过程中如果发生suspend, 等到唤醒的时候再接着发可能外设早已timeout,这时也需要锁。

驱动相关的wakelock接口如下, 在inclulde/linux/wakelock.h中定义:

[cpp] view plaincopyprint?
  1. void wake_lock_init(struct wake_lock *lock, int type, const char *name);  
  2. void wake_lock_destroy(struct wake_lock *lock);  
  3. void wake_lock(struct wake_lock *lock);  
  4. void wake_lock_timeout(struct wake_lock *lock, long timeout);  
  5. void wake_unlock(struct wake_lock *lock);  
  6. int  wake_lock_active(struct wake_lock *lock);  
  7. long has_wake_lock(int type);  

示例代码如下:

[cpp] view plaincopyprint?
  1. #include <linux/earlysuspend.h>  
  2. #include <linux/module.h>  
  3.   
  4. struct wake_lock my_wake_lock;  
  5.   
  6. static int __init my_init(void)  
  7. {  
  8.     wake_lock_init(&my_wake_lock, WAKE_LOCK_SUSPEND, "mylock");  
  9.     wake_lock(&my_wake_lock);  
  10.     //we do not want to suspend here!  
  11.     wake_unlock(&my_wake_lock);  
  12.     return 0;  
  13. }  
  14.   
  15. static void  __exit my_exit(void)  
  16. {  
  17.     wake_lock_destroy(&my_wake_lock)  
  18. }  


early suspend和later resume是Android对linux内核的扩展机制, 当系统持有wakelock时,如果一段时间无用户操作, 就会进入early suspend状态, 所有驱动注册的early suspend回调函数会被调用。当用户开始操作设备时,所有驱动注册的later resume函数会被调用。 当系统中无wakelock时, 驱动注册的early suspend会先于suspend函数调用, 唤醒时later resume会再resume函数后调用。 early suspend机制给系统提供了一种折中的省电模式,让系统在不能睡眠的情况下各个驱动模块也能有机会调整工作模式。 驱动注册early suspend和later resume回调的代码如下: 

[cpp] view plaincopyprint?
  1. module_init(my_init);  
  2. module_exit(my_exit);  
  3.   
  4. #include <linux/earlysuspend.h>  
  5. #include <linux/module.h>  
  6.   
  7. static my_early_suspend(struct early_suspend *h)  
  8. {  
  9.   
  10. }  
  11.   
  12. static void my_late_resume(struct early_suspend *h)  
  13. {  
  14.   
  15. }  
  16.   
  17. static struct early_suspend my_early_suspend_desc = {  
  18.     .suspend = my_early_suspend,  
  19.     .resume = my_late_resume,  
  20. };  
  21.   
  22. static int __init my_init(void)  
  23. {  
  24.     register_early_suspend(&my_early_suspend_desc);  
  25.     return 0;  
  26. }  
  27.   
  28. static void  __exit my_exit(void)  
  29.   
  30. {  
  31.     unregister_early_suspend(&my_ early_suspend_desc);  
  32. }  
  33.   
  34. module_init(my_init);  
  35. module_exit(my_exit);  


另外,请慎重在驱动的suspend和resume函数中和内核线程(workqueue或tasklet)中操作wakelock。
5. FrameWork相关
  5.1. Linux内核的电源管理
    Linux内核的电源管理有两个阶段suspend和resume, 分别在设备睡眠和唤醒的时候进行,需要关心电源管理的驱动程序可以注册suspend和resume函数在睡眠和唤醒时执行。Linux内核提供给应用层的接口是/sys/power/state, 有如下命令:
l echo mem>/sys/power/state:睡眠,状态保存进ram
l echo on>/sys/power/state:唤醒
l echo standby>/sys/power/state
l echo disk>/sys/power/state:睡眠, 状态保存进disk
还有一些其他命令请查阅网上资料, 有的命令不一定支持。
5.2. Android对linux内核的修改
  Android linux内核的电源管理系统是基于Linux内核的电源管理系统的扩展,添加了锁的概念, 多出了两个阶段early suspend和later resume,在有锁的情况下进入的睡眠是partial lock状态, 只会执行注册的early suspend函数, 唤醒时只会执行注册的later resume函数。只有在无锁时进入睡眠才会真正suspend,注册的early suspend函数会在suspend函数前执行,注册的later resume函数会在resume函数后执行 。 关心电源管理的android驱动程序可以注册early suspend和later resume和suspend和resume函数在相应阶段执行。 Android linux内核提供给应用层得接口如下:
l /sys/power/state:只支持mem(睡眠)和on(唤醒)两个参数 
l /sys/power/power_lock: 写入锁的名字即获得锁
l /sys/power/power_unlock:写入锁的名字即解锁


0 0
原创粉丝点击