转载地址:http://blog.csdn.net/wh_19910525/article/details/8287202

Wake Lock是一种锁的机制, 只要有人拿着这个锁,系统就无法进入休眠, 可以被用户态程序和内核获得. 这个锁可以是有超时的 或者 是没有超时的, 超时的锁会在时间过去以后自动解锁如果没有锁了或者超时了, 内核就会启动休眠的那套机制来进入休眠.

PowerManager.WakeLock 有加锁和解锁两种状态,加锁的方式有两种:

第一种是永久的锁住,这样的锁除非显式的放开,否则是不会解锁的,所以这种锁用起来要非常的小心。

第二种锁是超时锁,这种锁会在锁住后一段时间解锁。

在创建了 PowerManager.WakeLock 后,有两种机制,第一种是不计数锁机制,另一种是计数锁机制。可以通过 setReferenceCounted(boolean value) 来指定,一般默认为计数机制。这两种机制的区别在于,前者无论 acquire() 了多少次,只要通过一次 release()即可解锁。而后者正真解锁是在( --count == 0 )的时候,同样当 (count == 0) 的时候才会去申请加锁。所以 PowerManager.WakeLock 的计数机制并不是正真意义上的对每次请求进行申请/释放每一把锁,它只是对同一把锁被申请/释放的次数进行了统计,然后再去操作。

源码 位置:frameworks/base/core/java/android/os/PowerManager.java

++++++++++++++++++++++++

讲述 应用层 申请的锁 怎么传到kernel下面的,来理解  整个wakelock的框架。  比如android跑起来之后 在 /sys/power/wake_lock 下面的PowerManagerService 的生成过程。
     
1).应用程序申请锁
  Android 提供了现成 android.os.PowerManager 类 , 类中  提供newWakeLock(int flags, String tag)方法 来取得应用层的锁, 此函数的定义  frameworks/base/core/java/android/os/PowerManager.java
      应用程序 在申请wake_lock时 都会有调用以下 部分。
       实例:
        PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
        PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, “MyTag”);
        wl.acquire();//申请锁,这里会调用PowerManagerService里面acquireWakeLock()

***********************
        wl.release(); //释放锁,显示的释放锁,如果申请的锁不在此释放,系统就不会进入休眠。

======================================
2). frameworks层
/frameworks/base/services/java/com/android/server/PowerManagerService.java这个类是来管理 所有的应用程序 申请的wakelock。比如音视、频播放器、camera等申请的wakelock 都是通过这个类来 管理的。
static final String PARTIAL_NAME ="PowerManagerService"
nativeAcquireWakeLock(PARTIAL_WAKE_LOCK_ID, PARTIAL_NAME);
上面 这个函数调用Power类 里面的 acquireWakeLock(),此时的PARTIAL_NAME作为参数传递到底层去。

public static native void nativeAcquireWakeLock(int lock, String id);
注:在PowerManagerService 类中没有实现nativeAcquireWakeLock,其实现体在 frameworks/base/core/jni/android_os_Power.cpp中,所以nativeAcquireWakeLock()方法时会调用JNI下的实现方法

3).JNI层的实现
     路径:frameworks/base/core/jni/android_os_Power.cpp //
    static void acquireWakeLock(JNIEnv *env, jobject clazz,  jint lock, jstring idObj)
  {
    **************
      const char *id = env->GetStringUTFChars(idObj, NULL);
      acquire_wake_lock(lock, id);
      env->ReleaseStringUTFChars(idObj, id);
  }
     注:在acquireWakeLock()中调用了 路径下hardware/libhardware_legacy/power/power.c下面的acquire_wake_lock(lock, id)

4).与kernel层的交互
在power.c下的acquire_wake_lock(lock, id)函数如下:
int acquire_wake_lock(int lock, const char* id)
{   
**************
     return write(fd, id, strlen(id));
}
注: fd就是文件描述符,在此 表示”/sys/power/wake_lock”  id就是从PowerManagerService类中传下来的参数即:PARTIAL_NAME = "PowerManagerService"  到此 就是通过 文件系统 来与kernel层 交互的地方。

+++++++++++++++++++++++++++++++++++++++++++++++++++++

PowerManager类被应用程序调用,控制电源设备状态切换:

PowerManager类对外有三个接口函数:

1、void goToSleep(long time); //强制设备进入Sleep状态

Note:在应用层调用该函数, 应用需要 在 源码下编译,用系统签名,否则 调用 此函数 出错;

  2、newWakeLock(int flags, String tag);//取得相应层次的锁

flags参数说明:

    PARTIAL_WAKE_LOCK :保持CPU 运转,屏幕和键盘灯是关闭的。

    SCREEN_DIM_WAKE_LOCK :保持CPU 运转,允许保持屏幕显示但有可能是灰的,关闭键盘灯

    SCREEN_BRIGHT_WAKE_LOCK :保持CPU 运转,保持屏幕高亮显示,关闭键盘灯

    FULL_WAKE_LOCK :保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度

ACQUIRE_CAUSES_WAKEUP: 一旦有请求锁时,强制打开Screen和keyboard light

ON_AFTER_RELEASE: 在释放锁时reset activity timer

Note:

如果申请了partial wakelock,那么即使按Power键,系统也不会进Sleep,如Music播放时

如果申请了其它的wakelocks,按Power键,系统还是会进Sleep

3、void userActivity(long when, boolean noChangeLights);//User activity事件发生,设备会被切换到Full on的状态,同时Reset Screen off timer.

PowerManager和WakeLock的操作步骤

  1. PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);通过 Context.getSystemService().方法获取PowerManager实例。
  2. 然后通过PowerManager的newWakeLock ((int flags, String  tag)来生成WakeLock实例。int Flags指示要获取哪种WakeLock,不同的Lock对cpu 、屏幕、键盘灯有不同影响。
  3. 获取WakeLock实例后通过acquire()获取相应的锁,然后进行其他操作,最后使用release()释放(释放是必须的)。
 

Note:

1. 在使用以上函数的应用程序中,必须在其Manifest.xml文件中加入下面的权限:

    <uses-permission android:name="android.permission.WAKE_LOCK" />

<uses-permission android:name="android.permission.DEVICE_POWER" />

2. 所有的锁必须成对的使用, 如果申请了而没有及时释放,会造成系统故障。如申请了partial wakelock,而没有及时释放, 那系统就永远进不了Sleep模式.

Android 电源管理 -- wakelock机制的更多相关文章

  1. Android电源管理-休眠简要分析

    一.开篇 1.Linux 描述的电源状态 - On(on)                                                 S0 -  Working - Standb ...

  2. Android电源管理基础知识整理

    前言 待机.睡眠与休眠的区别? Android开发者官网当中提到"idle states",该如何理解,这个状态会对设备及我们的程序造成何种影响? 进入Doze模式中的idle状态 ...

  3. android(五)----使用WakeLock使Android应用程序保持后台唤醒

    在使用一些产品列如微信.QQ之类的,如果有新消息来时,手机屏幕即使在锁屏状态下也会亮起并提示声音,这时用户就知道有新消息来临了. 但是,一般情况下手机锁屏后,Android系统为了省电以及减少CPU消 ...

  4. Android:PowerManager类 电源管理

    PowerManager类用于对设备电源状态进行管理:PowerManager.WakeLock类用于保持设备常亮:Android中通过各种Lock锁对电源进行控制,需要注意的是加锁和解锁必须成对出现 ...

  5. Android权限管理之Permission权限机制及使用

    前言: 最近突然喜欢上一句诗:"宠辱不惊,看庭前花开花落:去留无意,望天空云卷云舒." 哈哈~,这个和今天的主题无关,最近只要不学习总觉得生活中少了点什么,所以想着围绕着最近面试过 ...

  6. android之WakeLock机制浅析

    转自:http://blog.sina.com.cn/s/blog_4ad7c2540101n2k2.html 应用程序耗电的实质,是所启用的硬件在消耗电量.  手机的耗电单元 CPU: 应用处理器( ...

  7. Android内存管理机制之一:low memory killer

    转载自http://www.miui.com/thread-29268-1-1.html 准备写这个专题之前,心里是有点忐忑的.首先Android内存管理机制相当复杂,想要讲清楚比较困难:其次对于绝大 ...

  8. linux驱动程序之电源管理之标准linux休眠与唤醒机制分析(一)

    1. Based on linux2.6.32,  only for mem(SDR) 2. 有兴趣请先参考阅读: 电源管理方案APM和ACPI比较.doc Linux系统的休眠与唤醒简介.doc 3 ...

  9. 【朝花夕拾】Android性能篇之(六)Android进程管理机制

    前言        Android系统与其他操作系统有个很不一样的地方,就是其他操作系统尽可能移除不再活动的进程,从而尽可能保证多的内存空间,而Android系统却是反其道而行之,尽可能保留进程.An ...

随机推荐

  1. 一个架构合理的UITableView应该是如何的?

    原文: http://www.chentoo.com/?p=200 iOS 开发中,UITableView 应该是最经常使用到的了.完毕一个UITableView应该实现他的DataSource和De ...

  2. JDBC操作,执行数据库更新操作

    目标: 使用Connection对象取得Statement实例 使用Statement进行数据增删改. Statement接口 要对数据库操作,要使用Statement完成.此接口可以使用Connec ...

  3. js Array.prototype.join.call(arguments,",") 理解

    prototype 属性使您有能力向对象添加属性和方法. join() 方法:把数组的所有元素放入一个字符串.元素通过指定的分隔符进行分隔. call() 方法可以用来代替另一个对象调用一个方法. A ...

  4. yum安装Apache,Mysql,PHP

    用yum安装Apache,Mysql,PHP.  用yum安装Apache,Mysql,PHP. 2.1安装Apache yum install httpd httpd-devel 安装完成后,用/e ...

  5. atitit.jndi的架构与原理以及资源配置and单元测试实践

    atitit.jndi的架构与原理以及资源配置and单元测试实践 1. jndi架构 1 2. jndi实现原理 3 3. jndi资源配置 3 3.1. resin  <database> ...

  6. [docker]一些经常或不经常用到的镜像启动方法-一些常用的docker启动方式

    一些经常或不经常用到的镜像启动方法 设置容器的TZ另一种办法 参考: https://github.com/spujadas/elk-docker/blob/master/start.sh ## ov ...

  7. Tool bar

    Toolbar ADJFToolBar;Button ADJFBackButton; ADJFToolBar = (Toolbar) findViewById(R.id.ADJFToolBar); / ...

  8. [待解决]ColumnPrefixFilter 不能过滤出全部满足条件的,

    Scan scan = new Scan(); ColumnPrefixFilter columnPrefixFilter = new hbase(main)::> scan 't4' ROW ...

  9. esp8266必备知识

    gpio定义 RX和TX为D9和D10

  10. U盘工作原理(转)

    u盘工作原理 一. U盘基本工作原理 通用串行总线(Universal serial Bus)是一种快速灵活的接口, 当一个USB设备插入主机时,由于USB设备硬件本身的原因,它会使USB总线的数据信 ...