Android7.0 PowerManagerService(2) WakeLock的使用及流程

作为移动终端,电量是一种稀缺资源,需要尽可能的节省。于是,Android系统在空闲时,会主动进入到休眠状态。
我们知道整个Android系统中运行着很多个进程,因此必须有一种机制能够知道每个进程是否正在进行重要的工作,只有这样Android系统才能对整个终端当前的状态做出判断。

显然我们不能启动一个进程,去主动监管其它所有进程的工作状态,这样CPU开销太大,反而加剧了电量的消耗。为此Android引入了基于WakeLock的电量管理机制,而PMS就是专门负责管理WakeLock的进程。

个人觉得WakeLock机制的思想,有点类似于早期通信领域局域网中的令牌环机制。当局域网中有设备需要发送数据时,需要申请令牌(Token),申请到令牌才能发送数据;设备发送完数据后,再释放掉令牌。

与此相似,Android设备中运行的进程需要使用电量资源时,也需要向PMS申请一个WakeLock;当工作完成后,就释放掉申请的WakeLock。PMS通过判断当前是否还有进程持有WakeLock,就能得出系统是否空闲的结论。

从这里也可以看出,当我们写一个永不停止工作的线程,但不申请WakeLock时,系统仍然可以休眠。在休眠时,CPU不会再耗费资源去调度该线程,于是“永不停止工作”被打上了引号。

接下来,我们就来看看PMS中的WakeLock。

一、创建WakeLock
我们以RIL.java为例,看看一般情况下,PMS以外的其它进程如何使用WakeLock。
在RIL.java的构造函数中:

public RIL(Context context, int preferredNetworkType,
        int cdmaSubscription, Integer instanceId) {
    .............
    PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
    //获取WakeLock,第一个参数决定了WakeLock的等级和flag
    mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, RILJ_LOG_TAG);

    //默认WakeLocked会ReferenceCounted,即一次申请对应一次释放
    //设为false后,一次释放就可以对应所有的申请
    mWakeLock.setReferenceCounted(false);
    ...........
    //RIL.java中自己维护了WakeLockCount
    mWakeLockCount = 0;
    ...........
}

从上面的代码,可以看出调用PowerManager的newWakeLock函数,可以创建出WakeLock。

我们看看newWakeLock函数定义:

public WakeLock newWakeLock(int levelAndFlags, String tag) {
    //检查参数有效性,即levelAndFlags必须对应于PowerManager中定义的WakeLock级别和flag,tag不能为空
    validateWakeLockParameters(levelAndFlags, tag);

    //此WakeLock为PowerManager定义的内部类
    return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName());
}

1、WakeLock Level
newWakeLock中的第一个参数对应于WakeLock的级别和标志位构成的位图。
目前,在PowerManger中一共为WakeLock定义了7种level。

/**
* Wake lock level: Ensures that the CPU is running; the screen and keyboard
* backlight will be allowed to go off.
* 
* If the user presses the power button, then the screen will be turned off
* but the CPU will be kept on until all partial wake locks have been released.
* /
public static final int PARTIAL_WAKE_LOCK = 0x00000001;

/**
* Wake lock level: Ensures that the screen is on (but may be dimmed);
* the keyboard backlight will be allowed to go off.
*
* If the user presses the power button, then the SCREEN_DIM_WAKE_LOCK will be
* implicitly released by the system, causing both the screen and the CPU to be turned off.
*/
@Deprecated
public static final int SCREEN_DIM_WAKE_LOCK = 0x00000006;

/**
* Wake lock level: Ensures that the screen is on at full brightness;
* the keyboard backlight will be allowed to go off.
*
*If the user presses the power button, then the SCREEN_BRIGHT_WAKE_LOCK will be
* implicitly released by the system, causing both the screen and the CPU to be turned off.
*/
@Deprecated
public static final int SCREEN_BRIGHT_WAKE_LOCK = 0x0000000a;

/**
* Wake lock level: Ensures that the screen and keyboard backlight are on at
* full brightness.
*
*If the user presses the power button, then the FULL_WAKE_LOCK will be
* implicitly released by the system, causing both the screen and the CPU to be turned off.
*/
@Deprecated
public static final int FULL_WAKE_LOCK = 0x0000001a;

/**
* Wake lock level: Turns the screen off when the proximity sensor activates.
* If the proximity sensor detects that an object is nearby, the screen turns off
* immediately.  Shortly after the object moves away, the screen turns on again.
*
* A proximity wake lock does not prevent the device from falling asleep
* unlike link FULL_WAKE_LOCK, SCREEN_BRIGHT_WAKE_LOCK and SCREEN_DIM_WAKE_LOCK.
* If there is no user activity and no other wake locks are held, then the device will fall asleep (and lock) as usual.
* However, the device will not fall asleep while the screen has been turned off
* by the proximity sensor because it effectively counts as ongoing user activity.
*
* Cannot be used with ACQUIRE_CAUSES_WAKEUP (WakeLock的flag).
*/
//例如拨号,打通后接听电话,屏幕变黑
public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 0x00000020;

/**
* Wake lock level: Put the screen in a low power state and allow the CPU to suspend
* if no other wake locks are held.
* 
* This is used by the dream manager to implement doze mode.  It currently
* has no effect unless the power manager is in the dozing state.
* /
public static final int DOZE_WAKE_LOCK = 0x00000040;

/**
* Wake lock level: Keep the device awake enough to allow drawing to occur.
*
* This is used by the window manager to allow applications to draw while the
* system is dozing.  It currently has no effect unless the power manager is in
* the dozing state.
* /
public static final int DRAW_WAKE_LOCK = 0x00000080;

从上面的代码注释可以看出,WakeLock主要用于控制CPU、屏幕和键盘三大部分(当然,现在的Anroid中基本没有键盘了)。
对于PARTIAL_WAKE_LOCK、SCREEN_DIM_WAKE_LOCK、SCREEN_BRIGHT_WAKE_LOCK和FULL_WAKE_LOCK而言,不考虑Power键的话,随着等级的提高,权限也相应增大,即持有高等级的锁,能够激活的部分越多;如果考虑Power键的话,PARTIAL_WAKE_LOCK可以保证CPU不休眠,反而是权限最大的。

PROXIMITY_SCREEN_OFF_WAKE_LOCK、DOZE_WAKE_LOCK和DRAW_WAKE_LOCK都是和具体场景相关的锁。

2、WakeLock Flag
PowerManager定义的WakeLock Flag很多,无法一一列举,就看一下比较常用的:


                
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值