5.3 PMS WakeLock分析
WakeLock是Android提供给应用程序获取电力资源的唯一方法。只要还有地方在使用WakeLock,系统就不会进入休眠状态。
WakeLock的一般使用方法如下:
PowerManager pm=(PowerManager)getSystemService(Context.POWER_SERVICE);
//①创建一个WakeLock,注意它的参数
PowerManager.WakeLock wl=pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK,
"My Tag");
wl.acquire();//②获取该锁
……//完成其他工作
wl.release();//③释放该锁
以上代码中共列出3个关键点,本章将分析前两个(在此基础上,读者可自行分析release函数)。
这3个函数都由PMS的Binder客户端的PowerManager使用,所以将本次分析划分为客户端和服务端两大部分。
5.3.1 WakeLock客户端分析
1.newWakeLock分析
通过PowerManager(以后简称PM)的newWakeLock将创建一个WakeLock,代码如下:
[—>PowerManager.java:newWakeLock]
public WakeLock newWakeLock(int flags, String tag)
{
//tag不能为null,否则抛出异常
return new WakeLock(flags, tag);//WakeLock为PM的内部类,第一个参数flags很关键
}
WakeLock的第一个参数flags很关键,它用于控制CPU/Screen/Keyboard的休眠状态。flags的可选值如表5-3所示。
由表5-3可知:
WakeLock只控制CPU、屏幕和键盘三大部分。
表中最后两项是附加标志,和前面的其他WAKE_LOCK标志组合使用。注意,PARTIAL_WAKE_LOCK比较特殊,附加标志不能影响它。
PARTIAL_WAKE_LOCK不受电源键控制,即按电源键不能使PARTIAL_WAKE_LOCK系统进入休眠状态(屏幕可以关闭,但CPU不会休眠)。了解了上述知识后,再来看如下代码:
[—>PowerManager.java:WakeLock]
WakeLock(int flags, String tag)
{
//检查flags参数是否非法
mFlags=flags;
mTag=tag;
//创建一个Binder对象,除了做Token外,PMS需要监视客户端的生死状况,否则有可能导致
//WakeLock不能被释放
mToken=new Binder();
}
客户端创建了WakeLock后,需要调用acquire以确保电力资源供应正常。下面对acquire代码进行分析。
2.acquire分析
这部分的代码如下:
[—>PowerManager.java:WakeLock.acquire]
public void acquire()
{
synchronized(mToken){
acquireLocked();//调用acquireLocked函数
}
}
//acquireLoced函数
private void acquireLocked(){
if(!mRefCounted||mCount++==0){
mHandler.removeCallbacks(mReleaser);//引用计数控制
try{
//调用PMS的acquirewakeLock,注意这里传递的参数,其中mWorkSource为空
mService.acquireWakeLock(mFlags, mToken, mTag, mWorkSource);
}……
mHeld=true;
}
}
上边代码中调用PMS的acquireWakeLock函数与PMS交互,该函数最后一个参数为WorkSource类。这个类从Android 2.2开始就存在,但一直没有明确的作用,下面是关于它的一段说明。
/**见WorkSoure.java
*Describes the source of some work that may be done by someone else.
*Currently the public representation of what a work source is is not
*defined;this is an opaque container.
*/
由以上注释可知,WorkSource本意用来描述某些任务的Source。传递此Source给其他人,这些人就可以执行该Source对应的工作。目前使用WorkSource的地方仅是ContentService中的SyncManager。读者暂时可不理会WorkSource。
客户端的功能比较简单,和PMS仅通过acquireWakeLock函数交互。下面来分析服务端的工作。