PowerManager的用法分析

来源:互联网 发布:微电影网络发行 编辑:程序博客网 时间:2024/05/22 09:04

在分析PMS的工作原理之前,我们先来分析下PowerManager的用法

[java] view plain copy
print?
  1. PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);  
  2.   PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");  
  3.   wl.acquire();  
  4.     ..screen will stay on during this section..  
  5.       wl.release()  

从以上代码中我们可以看出WakeLock用法的关键点

1.new 一个WakeLock对象,同时传入该WakeLock的类型的Flag标志

2.在使用之前调用wakeLock.aquire()获取锁

3.在使用之后调用wakeLock.release()释放锁

WakeLock是Android系统提供给应用程序获取电力资源的方法,只要有应用还在使用WakeLock,系统就不会进入休眠状态。

系统中已经定义看一些wakeLock类型,wakeLock一般只会影响cpu,屏幕和键盘灯三大模块

1. PARTIAL_WAKE_LOCK :cpu一直保持运行,允许屏幕和键盘灯熄灭

2. SCREEN_DIM_WAKE_LOCK :cpu保持运行,屏幕变暗,允许键盘灯熄灭

3. SCREEN_BRIGHT_WAKE_LOCK :cpu保持运行,屏幕亮屏,允许键盘灯熄灭

4. FULL_WAKE_LOCK : cpu保持运行,屏幕和键盘灯点亮

除了以上的4中wakeLock外,还有两种附件的wakeLock类型,这两种类型需要和以上4中组合使用,但是partial wakelock比较特殊,附件wakelock不影响他的状态

1. ACQUIRE_CAUSES_WAKEUP : 和其他wakeLock组合使用,表示申请wakeLock的同时是否唤醒屏幕

2. ON_AFTER_RELEASE :和其他wakeLock组合使用,释放wakeLock后不会立即熄灭屏幕,延迟一段时间在熄灭,和用户体验有关

我们知道PowerManager和PowerManagerService之间的关系,PowerManagerService作为服务端,而PowerManager则为客户端的代理,他们之间通过binder进行进程间通信。

wakeLock.aquire分析

aquire()方法最终调用PMS的aquireWakeLock()方法,该方法中检查并申请相关的权限,最终由aquireWakeLockInternal()方法来处理。

[java] view plain copy
print?
  1. private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,  
  2.             WorkSource ws, String historyTag, int uid, int pid) {  
  3.         synchronized (mLock) {  
  4.             WakeLock wakeLock;  
  5.             //查找wakelock是否存在  
  6.             int index = findWakeLockIndexLocked(lock);  
  7.             boolean notifyAcquire;  
  8.             if (index >= 0) {  
  9.                 //存在,从列表中获取该wakeLock  
  10.                 wakeLock = mWakeLocks.get(index);  
  11.                 //wakelock属性发生了变化,在更新该属性  
  12.                 if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid)) {  
  13.                     notifyWakeLockChangingLocked(wakeLock, flags, tag, packageName,  
  14.                             uid, pid, ws, historyTag);  
  15.                     wakeLock.updateProperties(flags, tag, packageName, ws, historyTag, uid, pid);  
  16.                 }  
  17.                 notifyAcquire = false;  
  18.             } else {  
  19.                 //不存在,创建一个新的wakelock  
  20.                 wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid);  
  21.                 try {  
  22.                     lock.linkToDeath(wakeLock, 0);  
  23.                 } catch (RemoteException ex) {  
  24.                     throw new IllegalArgumentException("Wake lock is already dead.");  
  25.                 }  
  26.                 //添加到wakelock列表  
  27.                 mWakeLocks.add(wakeLock);  
  28.                 //根据Doze模式的白名单更新wakelock的disabled变量  
  29.                 setWakeLockDisabledStateLocked(wakeLock);  
  30.                 notifyAcquire = true;  
  31.             }  
  32.             //查看wakeLock是否有ACQUIRE_CAUSES_WAKEUP标志,有的话唤醒屏幕  
  33.             applyWakeLockFlagsOnAcquireLocked(wakeLock, uid);  
  34.             mDirty |= DIRTY_WAKE_LOCKS;  
  35.             //更新电源信息  
  36.             updatePowerStateLocked();  
  37.             if (notifyAcquire) {  
  38.                 //通知wakeLock发生变化  
  39.                 //电量统计服务做相关统计  
  40.                 notifyWakeLockAcquiredLocked(wakeLock);  
  41.             }  
  42.         }  
  43.     }  

Aquire方法的具体流程


AAA



WakeLock.release方法

同样该方法最终调用PMS的releaseWakeLock方法,该方法检查和申请权限,最终由releaseWakeLockInternal()方法处理

该方法中首先判断wakeLock是否存在,若存在,则获取对应的wakeLock对象,从wakeLock列表中移除

下面是release方法流程图

BBBB



wakeup方法

强制将设备从Sleep状态唤醒,比如按Power键点亮屏幕

该方法最终调用PMS的wakeUpInternal()方法

[html] view plain copy
print?
  1. private void wakeUpInternal(long eventTime, String reason, int uid, String opPackageName,  
  2.             int opUid) {  
  3.         synchronized (mLock) {  
  4.             if (wakeUpNoUpdateLocked(eventTime, reason, uid, opPackageName, opUid)) {  
  5.                 updatePowerStateLocked();  
  6.             }  
  7.         }  
  8.     }  

该方法根据wakeUpNoUpdateLocked方法进行判断,如果为true

则调用更新电源状态信息

PMS类中有很多***NoUpdateLocked()方法,这些方法都有一些共性,就是更新状态,不负责体的执行,因为具体的执行逻辑都是在updatePowerStateLocked方法中。

那么我们在来看下wakeUpNoUpdateLocked方法的实现

[java] view plain copy
print?
  1. private boolean wakeUpNoUpdateLocked(long eventTime, String reason, int reasonUid,  
  2.            String opPackageName, int opUid) {  
  3.   
  4.        系统没有启动完成或者没有准备好,事件的时间不正确,当前已经是AWAKE  
  5.        不处理  
  6.        if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE  
  7.                || !mBootCompleted || !mSystemReady) {  
  8.            return false;  
  9.        }  
  10.        try {  
  11.            更新mLastWakeTime时间  
  12.            mLastWakeTime = eventTime;  
  13.            //修改当前的状态mWakefulness为WAKEFULNESS_AWAKE  
  14.            setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);  
  15.            通知发生了变化  
  16.            mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid);  
  17.            触发一次用户活动  
  18.            userActivityNoUpdateLocked(  
  19.                    eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, reasonUid);  
  20.        }  
  21.        return true;  
  22.    }  

PowerManager的基本用法分析完成,下面我们来具体分析下PMS服务的工作原理



阅读全文
0 0