10.6 第四阶段:调用systemReady方法
ActivityManagerService第四阶段工作由systemReady方法完成。该方法接收一个Runnable参数,该参数由ServerThread提供。systemReady方法内容很多,这里分成5部分分析。
10.6.1 发送ACTION_PRE_BOOT_COMPLETED广播
systemReady第一部分工作是发送ACTION_PRE_BOOT_COMPLETED广播,代码如下:
public void systemReady(final Runnable goingCallback){
synchronized(this){
//mSystemReady默认为false, systemReady执行后赋值为true
if(mSystemReady){
if(goingCallback!=null)goingCallback.run();
return;
}
//mDidUpdate和mWaitingUpdate默认为false,执行systemReady赋值为true
if(!mDidUpdate){
if(mWaitingUpdate){
return;
}
//ACTION_PRE_BOOT_COMPLETED
Intent intent=new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
List<ResolveInfo>ris=null;
try{
/通过PackageManager查询匹配ACTION_PRE_BOOT_COMPLETED的广播接收者/
ris=AppGlobals.getPackageManager().queryIntentReceivers
(intent, null,0,0);
}catch(RemoteException e){
}
if(ris!=null){
……//从ris中过滤掉非系统级广播接收者
intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
/*从data/system/called_pre_boots.dat文件中读取,上次
启动时已经处理过ACTION_PRE_BOOT_COMPLETED广播的组件/
ArrayList<ComponentName>lastDoneReceivers=
readLastDonePreBootReceivers();
//存储未处理ACTION_PRE_BOOT_COMPLETED广播的组件
final ArrayList<ComponentName>doneReceivers=
new ArrayList<ComponentName>();
……//从ris中删除已处理过ACTION_PRE_BOOT_COMPLETED广播的组件
for(int i=0;i<ris.size();i++){
ActivityInfo ai=ris.get(i).activityInfo;
ComponentName comp=new ComponentName(ai.packageName, ai.name);
doneReceivers.add(comp);
intent.setComponent(comp);
IIntentReceiver finisher=null;
if(i==ris.size()-1){//取出最后一个广播接收者
finisher=new IIntentReceiver.Stub(){
public void performReceive(Intent intent,
……//将mDidUpdate赋值为true
……//显示“即将完成启动。”
……//将doneReceivers写入called_pre_boots.dat
……//执行systemReady(goingCallback)
};
}
/*发送广播,并为最后一个广播接收者指定finisher回调接
口,当最后一个广播接收者处理完毕后,执行该回调函数/
broadcastIntentLocked(null, null, intent, null,
finisher,0,null, null, null, true,
false, MY_PID, Process.SYSTEM_UID,
0/UserId zero/);
if(finisher!=null){//处理到最后一个广播接收者
mWaitingUpdate=true;//说明此时处在等待升级状态
}
}
}//到此if(ris!=null)代码块结束
if(mWaitingUpdate){
return;
}
mDidUpdate=true;//mDidUpdate赋值为true
}
mSystemReady=true;//此时mSystemReady赋值为true
//main方法执行时,调用startRunning方法将mStartRunning赋值为true
if(!mStartRunning){
return;
}
}
systemReady第一部分工作是发送ACTION_PRE_BOOT_COMPLETED广播,可以将该部分视为预启动完毕阶段。目前接收该广播有三个模块。
CalendarProvider:com. android.providers.calendar.CalendarUpgradeReceiver
ContactsProvider:com. android.providers.contacts.ContactsUpgradeReceiver
MediaProvider:com. android.providers.media.MediaUpgradeReceiver
这三个广播接收者的主要作用是在启动阶段对数据库做一些预处理工作,例如创建数据库或者更新数据库版本。因为启动阶段并没有其他应用程序使用这些Content Provider,此时进行预处理工作是很恰当的。ACTION_PRE_BOOT_COMPLETED广播只被处理一次,处理过该广播的模块会在启动阶段存入data/system/called_pre_boots.dat文件中,因此第二次启动时,这些模块不需要再次接收处理该广播。
如果没有可以处理ACTION_PRE_BOOT_COMPLETED广播的广播接收者,此时直接将mSystemReady赋值为true,然后进入第二部分处理工作。