11.2.4 加载应用程序Activity
在创建应用程序进程时,指定了该进程的入口是ActivityThread的main方法,此时便进入启动应用程序Activity的第四个阶段:加载应用程序Activity。该阶段由五个步骤组成,接下来详细分析这部分工作。
1.ActivityThread.main
加载应用程序Activity阶段的第一步工作由ActivityThread.main完成,代码如下:
public static void main(String[]args){
SamplingProfilerIntegration.start();
CloseGuard.setEnabled(false);
//设置临时进程名为<pre-initialized>
Process.setArgV0("<pre-initialized>");
//准备UI主线程的消息循环
Looper.prepareMainLooper();
if(sMainThreadHandler==null){
sMainThreadHandler=new Handler();
}
//创建ActivityThread,并调用attach方法,传入的参数为false
ActivityThread thread=new ActivityThread();
thread.attach(false);//此时参数为false
AsyncTask.init();
//进入主线程消息循环
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
在ActivityThread.main方法中,首先设置临时进程名为pre-initialized,然后创建应用程序主线程ActivityThread,并调用其attach方法,最后进入主线程的消息循环。消息循环和异步处理的内容在第7章有过详细分析,这里不赘述。
2.ActivityThread.attach
加载应用程序Activity阶段的第二步工作由ActivityThread.attach完成,代码如下:
final ApplicationThread mAppThread=new ApplicationThread();
……
private void attach(boolean system){
sThreadLocal.set(this);
mSystemThread=system;//false
if(!system){
ViewRootImpl.addFirstDrawHandler(new Runnable(){
public void run(){
ensureJitEnabled();
}
});
//设置DDMS中显示的临时进程名
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
/*mAppThread是在创建ActivityThread的时候初始化的,其类型
为ApplicationThread。记录该应用程序,用于报告虚拟机错误/
RuntimeInit.setApplicationObject(mAppThread.asBinder());
//获取ActivityManagerService的代理对象,即ActivityManagerProxy
IActivityManager mgr=ActivityManagerNative.getDefault();
try{
//将应用进程attach到ActivityManagerService
mgr.attachApplication(mAppThread);
}catch(RemoteException ex){
//Ignore
}
}else{
……//参考ActivityManagerService启动过程setSystemProcess阶段
}
ViewRootImpl.addConfigCallback(new ComponentCallbacks2(){
public void onConfigurationChanged(Configuration newConfig){
……
}
public void onLowMemory(){
}
public void onTrimMemory(int level){
}
});
}
在第10章分析ActivityManagerService启动过程的setSystemProcess阶段时,已经分析过ActivityThread.attach,不过当时传入的参数为true,对应system进程的处理流程,此时传入的参数为false,对应应用程序进程的处理流程。ActivityThread.attach首先设置DDMS中显示的临时进程名为pre-initialized,然后调用ActivityManagerProxy.attachApplication方法,传入attach Application方法的参数mAppThread在创建ActivityThread时,初始化为ApplicationThread,该对象是一个Binder接口,ActivityManagerService便是通过ApplicationThread跨进程调度应用程序进程。
3.ActivityManagerService.attachApplication
加载应用程序Activity阶段的第三步是由ActivityManagerProxy.attachApplication方法通过Binder通信,进而调用ActivityManagerService的同名方法完成attach操作,这里直接分析ActivityManagerService.attachApplication方法,代码如下:
public final void attachApplication(IApplicationThread thread){
synchronized(this){
int callingPid=Binder.getCallingPid();
final long origId=Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
attachApplicationLocked取得调用者的PID,然后将请求转发给attachApplicationLocked方法处理,代码如下:
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid){
ProcessRecord app;
//传入的PID是Settings的PID,而MY_PID代表system_process
if(pid!=MY_PID&&pid>=0){
synchronized(mPidsSelfLocked){
//根据PID查找当前正在运行的应用程序对应的ProcessRecord
app=mPidsSelfLocked.get(pid);
}
}
……
/*应用程序在执行attach方法之前,都会在ActivityManagerService中
有对应的ProcessRecord,如果没有,说明出现问题,需要“杀死”该进程/
String processName=app.processName;
……//通过AppDeathRecipient监控进程退出
//将PID与ProcessRecord绑定
app.thread=thread;
//设置进程的OOM adj、线程组等信息
app.curAdj=app.setAdj=-100;
app.curSchedGroup=Process.THREAD_GROUP_DEFAULT;
app.setSchedGroup=Process.THREAD_GROUP_BG_NONINTERACTIVE;
app.forcingToForeground=null;
app.foregroundServices=false;
app.hasShownUi=false;
app.debugging=false;
//启动应用程序进程已完成,从消息队列中移除在调用attach方法之前设置的超时信息
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
//mProcessesReady在AMS.systemReady方法中已经被赋值为true
boolean normalMode=mProcessesReady||isAllowedWhileBooting(app.info);
//通过PackageManagerService获取该应用程序中定义的ContentProvider
List providers=normalMode?
generateApplicationProvidersLocked(app):null;
try{
……//省略debug、profile、trace、backup mode
ApplicationInfo appInfo=app.instrumentationInfo!=null
?app.instrumentationInfo:app.info;
app.compat=compatibilityInfoForPackageLocked(appInfo);
if(profileFd!=null){
profileFd=profileFd.dup();
}
thread.bindApplication(processName, appInfo, providers,
app.instrumentationClass,……
new Configuration(mConfiguration),app.compat,
getCommonServicesLocked(),
//Settings数据库的ContentObserver,观察数据库变化
mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app, false, true);//调整LRU列表和调度信息
app.lastRequestedGc=app.lastLowMemory=SystemClock.uptimeMillis();
}
……
boolean badApp=false;
boolean didSomething=false;
//取出栈顶的Activity准备运行
ActivityRecord hr=mMainStack.topRunningActivityLocked(null);
if(hr!=null&&normalMode){
if(hr.app==null&&app.uid==hr.info.applicationInfo.uid
&&processName.equals(hr.processName)){
try{
/*Headless设备没有GUI系统,不能启动Activity,否则
调用realStartActivityLocked启动Activity/
if(mHeadless){
}else if(mMainStack.realStartActivityLocked(hr, app, true, true)){
didSomething=true;
}
}catch(Exception e){
badApp=true;
}
}else{
mMainStack.ensureActivitiesVisibleLocked(hr, null, processName,0);
}
}
//执行因为等待进程创建而暂时挂起的Services
if(!badApp&&mPendingServices.size()>0){
ServiceRecord sr=null;
try{
for(int i=0;i<mPendingServices.size();i++){
sr=mPendingServices.get(i);
……
realStartServiceLocked(sr, app);
didSomething=true;
}
}catch(Exception e){
badApp=true;
}
}
//发送因为等待进程创建而暂时挂起的广播
if(!badApp&&isPendingBroadcastProcessLocked(pid)){
try{
didSomething=sendPendingBroadcastsLocked(app);
}catch(Exception e){
badApp=true;
}
}
……
if(!didSomething){
updateOomAdjLocked();//执行了以上启动组件的操作,需要调整OOM adj
}
return true;
}
ActivityManagerService接收到应用程序进程attach通知后,便知道启动应用程序进程的操作成功完成,会执行以下操作:
1)在mPidsSelfLocked中找到该应用进程信息,并进一步赋值。
2)在ActivityManagerService消息队列中删除启动应用程序时添加的PROC_START_TIMEOUT_MSG消息。
3)调用thread.bindApplication进入第四步操作,这里调用的是ApplicationThread.bindApplication方法。
4)调用realStartActivityLocked方法进入第五步操作,启动应用程序Activity。
5)启动因等待应用程序进程创建完毕而处于Pending状态的Services、BroadcastReceiver、BackupAgent(本章不分析这部分内容)。
6)如果执行了上述启动应用程序组件的操作,调用updateOomAdjLocked调整OOM adj(本章不分析这部分内容)。
4.ApplicationThread.bindApplication
加载应用程序Activity阶段的第四步操作由ApplicationThread.bindApplication完成,代码如下:
public final void bindApplication(String processName,……){
//参数services由getCommonServicesLocked方法获得
if(services!=null){//将Services缓存
ServiceManager.initServiceCache(services);
}
//将Settings数据库的ContentObserver存入ActivityThread.mCoreSettings
setCoreSettings(coreSettings);
AppBindData data=new AppBindData();
data.processName=processName;
data.appInfo=appInfo;
……
queueOrSendMessage(H.BIND_APPLICATION, data);
}
传入bindApplication方法的参数由getCommonServicesLocked方法获取,该方法将PackageManagerService、WindowManagerService、AlarmManagerServices三个系统服务存入ActivityManagerService.mAppBindArgs成员变量中,视为通用服务。
ApplicationThread. bindApplication将ActivityManagerService传入的数据封装到AppBindData中,然后将其通过BIND_APPLICATION消息发送给应用程序主线程的消息循环中,由ActivityThread的H.handleMessage处理。代码如下:
public final class ActivityThread{
final H mH=new H();
……
private class H extends Handler{
public void handleMessage(Message msg){
switch(msg.what){
……
case BIND_APPLICATION:
AppBindData data=(AppBindData)msg.obj;
handleBindApplication(data);
break;
……
}
H会根据传入的消息类型,匹配switch代码块的BIND_APPLICATION分支,获取AppBindData数据,进而调用handleBindApplication。
5.ActivityThread.handleBindApplication
加载应用程序Activity阶段的第五步是ActivityThread.handleBindApplication方法,代码如下:
private void handleBindApplication(AppBindData data){
……
Process.setArgV0(data.processName);//com.android.settings
android.ddm.DdmHandleAppName.setAppName(data.processName);
//硬件加速需要消耗较大内存,禁止persistent应用在低内存设备上使用硬件加速
if(data.persistent){
Display display=
WindowManagerImpl.getDefault().getDefaultDisplay();
if(!ActivityManager.isHighEndGfx(display)){
HardwareRenderer.disable(false);
}
}
……
//创建并初始化应用程序的Context
final ContextImpl appContext=new ContextImpl();
appContext.init(data.info, null, this);
//本例中cacheDir为/data/data/com.android.settings/cache
final File cacheDir=appContext.getCacheDir();
//临时文件
System.setProperty("java.io.tmpdir",cacheDir.getAbsolutePath());
setupGraphicsSupport(data.info, cacheDir);
……
if(data.instrumentationName!=null){//本例为null
……//对应AndroidManifest.xml的Instrumentation
}else{//AndroidManifest.xml未指定Instrumentation,创建默认值
mInstrumentation=new Instrumentation();
}
……
try{
//创建应用程序Application,对应AndroidManifest.xml的Application
Application app=data.info.makeApplication(
data.restrictedBackupMode, null);
//将第一个Application视为进程的初始Application
mInitialApplication=app;
//安装该应用程序的ContentProvider
if(!data.restrictedBackupMode){
List<ProviderInfo>providers=data.providers;
if(providers!=null){
installContentProviders(app, providers);
mH.sendEmptyMessageDelayed(H.ENABLE_JIT,10*1000);
}
}
try{
//调用Instrumentation的onCreate方法
mInstrumentation.onCreate(data.instrumentationArgs);
}
try{//调用Application的onCreate方法
mInstrumentation.callApplicationOnCreate(app);
}catch(Exception e){
}
}finally{
StrictMode.setThreadPolicy(savedPolicy);
}
}
ActivityThread. handleBindApplication方法的主要工作如下:
1)为应用程序设置进程名。
2)为低内存设备禁用硬件加速。
3)创建应用程序对应的Application,并设置该进程的初始Application。
4)安装Content Provider(可见Content Provider的创建先于其他组件)。
5)执行Instrumentation的onCreate方法。
6)执行Application的onCreate方法。
以上步骤执行完毕标志着启动应用程序Activity的加载应用程序阶段结束。