**PowerManagerService.java::acquireWakeLock**
~~~
public void acquireWakeLock(int flags, IBinderlock, String tag, WorkSource ws) {
intuid = Binder.getCallingUid();
intpid = Binder.getCallingPid();
if(uid != Process.myUid()) {
mContext.enforceCallingOrSelfPermission(//检查WAKE_LOCK权限
android.Manifest.permission.WAKE_LOCK,null);
}
if(ws != null) {
//如果ws不为空,需要检查调用进程是否有UPDATE_DEVICE_STATS的权限
enforceWakeSourcePermission(uid, pid);
}
longident = Binder.clearCallingIdentity();
try{
synchronized (mLocks) {调用acquireWakeLockLocked函数
acquireWakeLockLocked(flags, lock, uid, pid, tag, ws);
}
} ......
}
~~~
接下来分析acquireWakeLockLocked函数。由于此段代码较长,宜分段来看。
1. acquireWakeLockLocked分析之一
开始分析之前,有必要先介绍另外一个数据结构,它为PowerManagerService的内部类,名字也为WakeLock。其定义如下:
**PowerManagerService.java**
~~~
class WakeLock implements IBinder.DeathRecipient
~~~
PMS的WakeLock实现了DeathRecipient接口。根据前面Binder系统的知识可知,当Binder服务端死亡后,Binder系统会向注册了讣告接收的Binder客户端发送讣告通知,因此客户端可以做一些资源清理工作。在本例中,PM.WakeLock是Binder服务端,而PMS.WakeLock是Binder客户端。假如PM.WakeLock所在进程在release唤醒锁(即WakeLock)之前死亡,PMS.WakeLock的binderDied函数则会被调用,这样,PMS也能及时进行释放(release)工作。对于系统的重要资源来说,采用这种安全保护措施尤其必要。
回到acquireWakeLockLocked函数,先看第一段代码:
**PowerManagerService.java::acquireWakeLockLocked**
~~~
public void acquireWakeLockLocked(int flags,IBinder lock, int uid,
int pid, Stringtag,WorkSource ws) {
......
//mLocks是一个ArrayList,保存PMS.WakeLock对象
int index= mLocks.getIndex(lock);
WakeLockwl;
booleannewlock;
booleandiffsource;
WorkSourceoldsource;
if (index< 0) {
//创建一个PMS.WakeLock对象,保存客户端acquire传来的参数
wl = new WakeLock(flags, lock, tag, uid, pid);
switch(wl.flags & LOCK_MASK)
{ //将flags转换成对应的minState
casePowerManager.FULL_WAKE_LOCK:
if(mUseSoftwareAutoBrightness) {
wl.minState = SCREEN_BRIGHT;
}else {
wl.minState = (mKeyboardVisible ? ALL_BRIGHT: SCREEN_BUTTON_BRIGHT);
}
break;
casePowerManager.SCREEN_BRIGHT_WAKE_LOCK:
wl.minState = SCREEN_BRIGHT;
break;
casePowerManager.SCREEN_DIM_WAKE_LOCK:
wl.minState = SCREEN_DIM;
break;
case PowerManager.PARTIAL_WAKE_LOCK:
//PROXIMITY_SCREEN_OFF_WAKE_LOCK在SDK中并未输出,原因是有部分手机并没有接近
//传感器
casePowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
break;
default:
return;
}
mLocks.addLock(wl);//将PMS.WakeLock对象保存到mLocks中
if (ws!= null) {
wl.ws = new WorkSource(ws);
}
newlock= true; //设置几个参数信息,newlock表示新创建了一个PMS.WakeLock对象
diffsource = false;
oldsource = null;
}else{
//如果之前保存有PMS.WakeLock,则要判断新传入的WorkSource和之前保存的WorkSource
//是否一样。此处不讨论这种情况
......
}
~~~
在上面代码中,很重要一部分是将前面flags信息转成PMS.WakeLock的成员变量minState,下面是对转换关系的总结。
- FULL_WAKE_LOCK:当启用mUseSoftwareAutoBrightness时,minState为SCREEN_BRIGHT(表示屏幕全亮),否则为ALL_BRIGHT(屏幕、键盘、按键全亮。注意,只有在打开键盘时才能选择此项)或SCREEN_BUTTON_BRIGHT(屏幕、按键全亮)。
- SCREEN_BRIGHT_WAKE_LOCK:minState为SCREEN_BRIGHT,表示屏幕全亮。
- SCREEN_DIM_WAKE_LOCK:minState为SCREEN_DIM,表示屏幕Dim。
- 对PARTIAL_WAKE_LOCK和PROXIMITY_SCREEN_OFF_WAKE_LOCK情况不做处理。
该做的准备工作都做了,下面来看第二阶段的工作是什么。
2. acquireWakeLockLocked分析之二
代码如下:
~~~
//isScreenLock用于判断flags是否和屏幕有关,除PARTIAL_WAKE_LOCK外,其他WAKE_LOCK
//都和屏幕有关
if (isScreenLock(flags)) {
if ((flags& LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
mProximityWakeLockCount++;//引用计数控制
if(mProximityWakeLockCount == 1) {
enableProximityLockLocked();//使能Proximity传感器
}
} else {
if((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
......//ACQUIRE_CAUSES_WAKEUP标志处理
} else {
//①gatherState返回一个状态,稍后分析该函数
mWakeLockState = (mUserState | mWakeLockState) &mLocks.gatherState();
}
//②设置电源状态,
setPowerState(mWakeLockState | mUserState);
}
}
~~~
以上代码列出了两个关键函数,一个是gatherState,另外一个是setPowerState,下面来分析它们。
(1) gatherState分析
gatherState函数的代码如下:
**PowerManagerService.java::gatherState**
~~~
int gatherState()
{
intresult = 0;
int N =this.size();
for (inti=0; i<N; i++) {
WakeLock wl = this.get(i);
if(wl.activated)
if(isScreenLock(wl.flags))
result |= wl.minState;//对系统中所有活跃PMS.WakeLock的状态进行或操作
}
returnresult;
}
~~~
由以上代码可知,gatherState将统计当前系统内部活跃WakeLock的minState。这里为什么要“使用”或“操作”呢?举个例子,假如WakeLock A的minState为SCREEN_DIM,而WakeLock B的minState为SCREEN_BRIGHT,二者共同作用,最终的屏幕状态显然应该是SCREEN_BRIGHT。
提示读者也可参考PowerManagerService中SCREEN_DIM等变量的定义。
下面来看setPowerState,本章前面曾两次对该函数避而不谈,现在该见识见识它了。
(2) setPowerState分析
setPowerState用于设置电源状态,先来看其在代码中的调用:
setPowerState(mWakeLockState | mUserState);
在以上代码中除了mWakeLockState外,还有一个mUserState。根据前面对gatherState函数的介绍可知,mWakeLockState的值来源于系统当前活跃WakeLock的minState。那么mUserState代表什么呢?
mUserState代表用户触发事件导致的电源状态。例如,按Home键后,将该值设置为SCREEN_BUTTON_BRIGHT(假设手机没有键盘)。很显然,此时系统的电源状态应该是mUserState和mWakeLockState的组合。
>[info] **提示 **“一个小小的变量背后代表了一个很重要的case”,读者能体会到吗?
下面来看setPowerState的代码,这段代码较长,也适合分段来看。第一段代码如下:
**PowerManagerService.java::setPowerState**
~~~
private void setPowerState(int state)
{//调用另外一个同名函数
setPowerState(state, false,WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT);
}
//setPowerState
private void setPowerState(int newState, booleannoChangeLights, int reason)
{
synchronized (mLocks) {
int err;
if (noChangeLights)//在这种情况中,noChangeLights为false
newState = (newState & ~LIGHTS_MASK) | (mPowerState &LIGHTS_MASK);
if(mProximitySensorActive)//如果打开了接近感应器,就不需要在这里点亮屏幕了
newState = (newState & ~SCREEN_BRIGHT);
if(batteryIsLow())//判断是否处于低电状态
newState |= BATTERY_LOW_BIT;
else
newState &= ~BATTERY_LOW_BIT;
......
//如果还没启动完成,则需要将newState置为ALL_BRIGHT。细心的读者有没有发现,在手机开机过程中
//键盘、屏幕、按键等都会全部点亮一会儿呢?
if(!mBootCompleted && !mUseSoftwareAutoBrightness)
newState |= ALL_BRIGHT;
booleanoldScreenOn = (mPowerState & SCREEN_ON_BIT) != 0;
boolean newScreenOn = (newState &SCREEN_ON_BIT) != 0;
finalboolean stateChanged = mPowerState != newState;
~~~
第一段代码主要用于得到一些状态值,例如在新状态下屏幕是否需要点亮(newScreenOn)等。再来看第二段代码,它将根据第一段的状态值完成对应的工作。
**PowerManagerService::setPowerState**
~~~
if(oldScreenOn != newScreenOn) {
if(newScreenOn) {
if(mStillNeedSleepNotification) {
//对sendNotificationLocked函数的分析见后文
sendNotificationLocked(false,
WindowManagerPolicy.OFF_BECAUSE_OF_USER);
}// mStillNeedSleepNotification判断
booleanreallyTurnScreenOn = true;
if(mPreventScreenOn)// mPreventScreenOn是何方神圣?
reallyTurnScreenOn= false;
if(reallyTurnScreenOn) {
err = setScreenStateLocked(true);//点亮屏幕
......//通知mBatteryStats做电量统计
mBatteryStats.noteScreenBrightness(getPreferredBrightness());
mBatteryStats.noteScreenOn();
} else {//reallyTurnScreenOn为false
setScreenStateLocked(false);//关闭屏幕
err =0;
}
if (err == 0) {
sendNotificationLocked(true, -1);
if(stateChanged)
updateLightsLocked(newState, 0);//点亮按键灯或者键盘灯
mPowerState |= SCREEN_ON_BIT;
}
}
~~~
以上代码看起来比较简单,就是根据情况点亮或关闭屏幕。事实果真的如此吗?的还记得前面所说“一个小小的变量背后代表一个很重要的case”这句话吗?是的,这里也有一个很重要的case,由mPreventScreenOn表达。这是什么意思呢?
PMS提供了一个函数叫preventScreenOn,该函数(在SDK中未公开)使应用程序可以阻止屏幕点亮。为什么会有这种操作呢?难道是因为该应用很丑,以至于不想让别人看见?根据该函数的解释,在两个应用之间进行切换时(尤其是正在启动一个Activity却又接到来电通知时),很容易出现闪屏现象,会严重影响用户体验。因此提供了此函数,由应用来调用并处理它。
* * * * *
**注意**:闪屏的问题似乎解决了,但事情还没完,这个解决方案还引入了另外一个问题:假设应用忘记重新使屏幕点亮,手机岂不是一直就黑屏了?为此,在代码中增加了一段处理逻辑,即如果5秒钟后应用还没有使屏幕点亮,PMS将自己设置mPreventScreenOn为false。
* * * * *
Google怎么会写这种代码?还好,代码开发者也意识到这是一个很难看的方法,只是目前还没有一个比较完美的解决方案而已。
继续看setPowerState最后的代码:
~~~
else {//newScreenOn为false的情况
......//更新键盘灯、按键灯的状态
//从mHandler中移除mAutoBrightnessTask,这和光传感器有关。此处不讨论
mHandler.removeCallbacks(mAutoBrightnessTask);
mBatteryStats.noteScreenOff();//通知BatteryStatsService,屏幕已关
mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);
updateNativePowerStateLocked();
}
}//if(oldScreenOn != newScreenOn)判断结束
else if(stateChanged) {//屏幕的状态不变,但是light的状态有可能变化,所以
updateLightsLocked(newState, 0);//单独更新light的状态
}
mPowerState= (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);
updateNativePowerStateLocked();
}//setPowerState完毕
~~~
setPowerState函数是在PMS中真正设置屏幕及Light状态的地方,其内部将通过Power类与这些硬件交互。相关内容见5.3.3节。
(3) sendNotificationLocked函数分析
sendNotificationLocked函数用于触发SCREEN_ON/OFF广播的发送,来看以下代码:
**PowerManagerService.java::sendNotificationLocked**
~~~
private void sendNotificationLocked(boolean on,int why) {
......
if (!on) {
mStillNeedSleepNotification = false;
}
int index= 0;
while(mBroadcastQueue[index] != -1) {
index++;
}
// mBroadcastQueue和mBroadcastWhy均定义为int数组,成员个数为3,它们有什么作用呢
mBroadcastQueue[index] = on ? 1 : 0;
mBroadcastWhy[index] = why;
/* mBroadcastQueue数组一共有3个元素,根据代码中的注释,其作用如下:
当取得的index为2时,即0,1元素已经有值,由于屏幕ON/OFF请求是配对的,所以在这种情况
下只需要处理最后一次的请求。例如0元素为ON,1元素为OFF,2元素为ON,则可以去掉0,
1的请求,而直接处理2的请求,即屏幕ON。对于那种频繁按Power键的操作,通过这种方式可以
节省一次切换操作
*/
if (index== 2) {
if (!on&& mBroadcastWhy[0] > why) mBroadcastWhy[0] = why;
//处理index为2的情况,见上文的说明
mBroadcastQueue[0] = on ? 1 : 0;
mBroadcastQueue[1] = -1;
mBroadcastQueue[2] = -1;
mBroadcastWakeLock.release();
index =0;
}
/*
如果index为1,on为false,即屏幕发出关闭请求,则无需处理。根据注释中的说明,
在此种情况,屏幕已经处于OFF状态,所以无需处理。为什么在此种情况下屏幕已经关闭了呢?
*/
if (index== 1 && !on) {
mBroadcastQueue[0] = -1;
mBroadcastQueue[1] = -1;
index = -1;
mBroadcastWakeLock.release();
}
if(mSkippedScreenOn) {
updateLightsLocked(mPowerState, SCREEN_ON_BIT);
}
//如果index不为负数,则抛送mNotificationTask给mHandler处理
if (index>= 0) {
mBroadcastWakeLock.acquire();
mHandler.post(mNotificationTask);
}
}
~~~
sendNotificationLocked函数相当诡异,主要是mBroadcastQueue数组的使用让人感到困惑。其目的在于减少不必要的屏幕切换和广播发送,但是为什么index为1时,屏幕处于OFF状态呢?下面来分析mNotificationTask,希望它能回答这个问题。
**PowerManagerService.java::mNotificationTask**
~~~
private Runnable mNotificationTask = newRunnable()
{
publicvoid run()
{
while(true) {//此处是一个while循环
intvalue;
int why;
WindowManagerPolicy policy;
synchronized (mLocks) {
value =mBroadcastQueue[0];//取mBroadcastQueue第一个元素
why= mBroadcastWhy[0];
for(int i=0; i<2; i++) {//将后面的元素往前挪一位
mBroadcastQueue[i] = mBroadcastQueue[i+1];
mBroadcastWhy[i] = mBroadcastWhy[i+1];
}
policy = getPolicyLocked();//policy指向PhoneWindowManager
if(value == 1 && !mPreparingForScreenOn) {
mPreparingForScreenOn = true;
mBroadcastWakeLock.acquire();
}
}// synchronized结束
if(value == 1) {//value为1,表示发出屏幕ON请求
mScreenOnStart = SystemClock.uptimeMillis();
//和WindowManagerService交互,和锁屏界面有关
//mScreenOnListener为回调通知对象
policy.screenTurningOn(mScreenOnListener);
ActivityManagerNative.getDefault().wakingUp();//和AMS交互
if (mContext != null &&ActivityManagerNative.isSystemReady()) {
//发送SCREEN_ON广播
mContext.sendOrderedBroadcast(mScreenOnIntent,null,
mScreenOnBroadcastDone, mHandler, 0, null, null);
}......
}elseif (value == 0) {
mScreenOffStart = SystemClock.uptimeMillis();
policy.screenTurnedOff(why);//通知WindowManagerService
ActivityManagerNative.getDefault().goingToSleep();//和AMS交互
if(mContext != null && ActivityManagerNative.isSystemReady()) {
//发送屏幕OFF广播
mContext.sendOrderedBroadcast(mScreenOffIntent, null,
mScreenOffBroadcastDone, mHandler, 0, null,null);
}
}elsebreak;
}
};
~~~
mNotificationTask比较复杂,但是它对mBroadcastQueue的处理比较有意思,每次取出第一个元素值后,将后续元素往前挪一位。这种处理方式能解决之前提出的那个问题吗?
说实话,目前笔者也没找到能解释index为1时,屏幕一定处于OFF的证据。如果有哪位读者找到证据,不妨分享一下。
另外,mNotificationTask和ActivityManagerService及WindowManagerService都有交互。因为这两个服务内部也使用了WakeLock,所以需要通知它们释放WakeLock,否则会导致不必要的电力资源消耗。具体内容只能留待以后分析相关服务时再来讨论了。
(4) acquireWakeLocked第二阶段工作总结
acquireWakeLocked第二阶段工作是处理和屏幕相关的WAKE_LOCK方面的工作(isScreenLock返回为true的情况)。其中一个重要的函数就是setPowerState,该函数将根据不同的状态设置屏幕光、键盘灯等硬件设备。注意,和硬件交互相关的工作是通过Power类提供的接口完成的。
3. acquireWakeLocked分析之三
acquireWakeLocked处理WAKE_LOCK为PARTIAL_WAKE_LOCK的情况。来看以下代码:
**PowerManagerService.java::acquiredWakeLockLocked**
~~~
else if ((flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK){
if(newlock) {
mPartialCount++;
}
//获取kernel层的PARTIAL_WAKE_LOCK,该函数后续再分析
Power.acquireWakeLock(Power.PARTIAL_WAKE_LOCK,PARTIAL_NAME);
}//else if判断结束
if(diffsource) {
noteStopWakeLocked(wl, oldsource);
}
if(newlock || diffsource) {
noteStartWakeLocked(wl, ws);//通知BatteryStatsService做电量统计
}
~~~
当客户端使用PARTIAL_WAKE_LOCK时,PMS会调用Power.acquireWakeLock申请一个内核的WakeLock。
4. acquireWakeLock总结
acquireWakeLock有三个阶段的工作,总结如下:
- 如果对应的WakeLock不存在,则创建一个WakeLock对象,同时将WAKE_LOCK标志转换成对应的minState;否则,从mLocks中查找对应的WakeLock对象,然后更新其中的信息。
- 当WAKE_LOCK标志和屏幕有关时,需要做相应的处理,例如点亮屏幕、打开按键灯等。实际上这些工作不仅影响电源管理,还会影响到用户感受,所以其中还穿插了一些和用户体验有关的处理逻辑(如上面注释的mPreventScreenOn变量)。
- 当WAKE_LOCK和PARTIAL_WAKE_LOCK有关时,仅简单调用Power的acquireWakeLock即可,其中涉及和Linux Kernel电源管理系统的交互。
- 前言
- 第1章 搭建Android源码工作环境
- 1.1 Android系统架构
- 1.2 搭建开发环境
- 1.2.1 下载源码
- 1.2.2 编译源码
- 1.2.3 利用Eclipse调试system_process
- 1.3 本章小结
- 第2章 深入理解Java Binder和MessageQueue
- 2.1 概述
- 2.2 Java层中的Binder架构分析
- 2.2.1 Binder架构总览
- 2.2.2 初始化Java层Binder框架
- 2.2.3 addService实例分析
- 2.2.4 Java层Binder架构总结
- 2.3 心系两界的MessageQueue
- 2.3.1 MessageQueue的创建
- 2.3.2 提取消息
- 2.3.3 nativePollOnce函数分析
- 2.3.4 MessageQueue总结
- 2.4 本章小结
- 第3章 深入理解SystemServer
- 3.1 概述
- 3.2 SystemServer分析
- 3.2.1 main函数分析
- 3.2.2 Service群英会
- 3.3 EntropyService分析
- 3.4 DropBoxManagerService分析
- 3.4.1 DBMS构造函数分析
- 3.4.2 dropbox日志文件的添加
- 3.4.3 DBMS和settings数据库
- 3.5 DiskStatsService和DeviceStorageMonitorService分析
- 3.5.1 DiskStatsService分析
- 3.5.2 DeviceStorageManagerService分析
- 3.6 SamplingProfilerService分析
- 3.6.1 SamplingProfilerService构造函数分析
- 3.6.2 SamplingProfilerIntegration分析
- 3.7 ClipboardService分析
- 3.7.1 复制数据到剪贴板
- 3.7.2 从剪切板粘贴数据
- 3.7.3 CBS中的权限管理
- 3.8 本章小结
- 第4章 深入理解PackageManagerService
- 4.1 概述
- 4.2 初识PackageManagerService
- 4.3 PKMS的main函数分析
- 4.3.1 构造函数分析之前期准备工作
- 4.3.2 构造函数分析之扫描Package
- 4.3.3 构造函数分析之扫尾工作
- 4.3.4 PKMS构造函数总结
- 4.4 APK Installation分析
- 4.4.1 adb install分析
- 4.4.2 pm分析
- 4.4.3 installPackageWithVerification函数分析
- 4.4.4 APK 安装流程总结
- 4.4.5 Verification介绍
- 4.5 queryIntentActivities分析
- 4.5.1 Intent及IntentFilter介绍
- 4.5.2 Activity信息的管理
- 4.5.3 Intent 匹配查询分析
- 4.5.4 queryIntentActivities总结
- 4.6 installd及UserManager介绍
- 4.6.1 installd介绍
- 4.6.2 UserManager介绍
- 4.7 本章学习指导
- 4.8 本章小结
- 第5章 深入理解PowerManagerService
- 5.1 概述
- 5.2 初识PowerManagerService
- 5.2.1 PMS构造函数分析
- 5.2.2 init分析
- 5.2.3 systemReady分析
- 5.2.4 BootComplete处理
- 5.2.5 初识PowerManagerService总结
- 5.3 PMS WakeLock分析
- 5.3.1 WakeLock客户端分析
- 5.3.2 PMS acquireWakeLock分析
- 5.3.3 Power类及LightService类介绍
- 5.3.4 WakeLock总结
- 5.4 userActivity及Power按键处理分析
- 5.4.1 userActivity分析
- 5.4.2 Power按键处理分析
- 5.5 BatteryService及BatteryStatsService分析
- 5.5.1 BatteryService分析
- 5.5.2 BatteryStatsService分析
- 5.5.3 BatteryService及BatteryStatsService总结
- 5.6 本章学习指导
- 5.7 本章小结
- 第6章 深入理解ActivityManagerService
- 6.1 概述
- 6.2 初识ActivityManagerService
- 6.2.1 ActivityManagerService的main函数分析
- 6.2.2 AMS的 setSystemProcess分析
- 6.2.3 AMS的 installSystemProviders函数分析
- 6.2.4 AMS的 systemReady分析
- 6.2.5 初识ActivityManagerService总结
- 6.3 startActivity分析
- 6.3.1 从am说起
- 6.3.2 AMS的startActivityAndWait函数分析
- 6.3.3 startActivityLocked分析
- 6.4 Broadcast和BroadcastReceiver分析
- 6.4.1 registerReceiver流程分析
- 6.4.2 sendBroadcast流程分析
- 6.4.3 BROADCAST_INTENT_MSG消息处理函数
- 6.4.4 应用进程处理广播分析
- 6.4.5 广播处理总结
- 6.5 startService之按图索骥
- 6.5.1 Service知识介绍
- 6.5.2 startService流程图
- 6.6 AMS中的进程管理
- 6.6.1 Linux进程管理介绍
- 6.6.2 关于Android中的进程管理的介绍
- 6.6.3 AMS进程管理函数分析
- 6.6.4 AMS进程管理总结
- 6.7 App的 Crash处理
- 6.7.1 应用进程的Crash处理
- 6.7.2 AMS的handleApplicationCrash分析
- 6.7.3 AppDeathRecipient binderDied分析
- 6.7.4 App的Crash处理总结
- 6.8 本章学习指导
- 6.9 本章小结
- 第7章 深入理解ContentProvider
- 7.1 概述
- 7.2 MediaProvider的启动及创建
- 7.2.1 Context的getContentResolver函数分析
- 7.2.2 MediaStore.Image.Media的query函数分析
- 7.2.3 MediaProvider的启动及创建总结
- 7.3 SQLite创建数据库分析
- 7.3.1 SQLite及SQLiteDatabase家族
- 7.3.2 MediaProvider创建数据库分析
- 7.3.3 SQLiteDatabase创建数据库的分析总结
- 7.4 Cursor 的query函数的实现分析
- 7.4.1 提取query关键点
- 7.4.2 MediaProvider 的query分析
- 7.4.3 query关键点分析
- 7.4.4 Cursor query实现分析总结
- 7.5 Cursor close函数实现分析
- 7.5.1 客户端close的分析
- 7.5.2 服务端close的分析
- 7.5.3 finalize函数分析
- 7.5.4 Cursor close函数总结
- 7.6 ContentResolver openAssetFileDescriptor函数分析
- 7.6.1 openAssetFileDescriptor之客户端调用分析
- 7.6.2 ContentProvider的 openTypedAssetFile函数分析
- 7.6.3 跨进程传递文件描述符的探讨
- 7.6.4 openAssetFileDescriptor函数分析总结
- 7.7 本章学习指导
- 7.8 本章小结
- 第8章 深入理解ContentService和AccountManagerService
- 8.1 概述
- 8.2 数据更新通知机制分析
- 8.2.1 初识ContentService
- 8.2.2 ContentResovler 的registerContentObserver分析
- 8.2.3 ContentResolver的 notifyChange分析
- 8.2.4 数据更新通知机制总结和深入探讨
- 8.3 AccountManagerService分析
- 8.3.1 初识AccountManagerService
- 8.3.2 AccountManager addAccount分析
- 8.3.3 AccountManagerService的分析总结
- 8.4 数据同步管理SyncManager分析
- 8.4.1 初识SyncManager
- 8.4.2 ContentResolver 的requestSync分析
- 8.4.3 数据同步管理SyncManager分析总结
- 8.5 本章学习指导
- 8.6 本章小结