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的加载应用程序阶段结束。