11.2 启动应用程序Activity时在Server端的执行流程

启动应用程序Activity的请求从Client端传递给Server端的ActivityManagerService后,便进入启动应用七个阶段,本节以在Home桌面启动Settings应用程序为例,详细分析这个过程。

11.2.1 预启动

预启动阶段主要由6步组成,其简要流程如图11-3所示。

11.2 启动应用程序Activity时在Server端的执行流程 - 图1

图 11-3 预启动阶段的6个步骤

接下来详细分析该阶段的内容。

1.ActivityManagerService.startActivity

预启动阶段的第一步工作由ActivityManagerService.startActivity完成,其主要工作是获取Client端的UID,以及判断Client端是否有权限启动应用程序Activity,然后调用ActivityStack.startActivityMayWait方法执行第二步工作。代码如下:


public final int startActivity(IApplicationThread caller,

Intent intent, String resolvedType, IBinder resultTo,

String resultWho, int requestCode, int startFlags,

String profileFile,……){

//判断caller进程是否有权限启动Activity,对于sandboxed processes会抛出SecurityException

//本例的caller表示Launcher,能够通过安全检查

enforceNotIsolatedCaller("startActivity");

int userId=0;

//本例的Category为android.intent.category.LAUNCHER

if(intent.getCategories()!=null&&

intent.getCategories().contains(Intent.CATEGORY_HOME)){

userId=mCurrentUserId;

}else{//Launcher也是Application故其UID大于FIRST_APPLICATION_UID

if(Binder.getCallingUid()<Process.FIRST_APPLICATION_UID){

userId=0;

}else{

userId=Binder.getOrigCallingUser();

}

}

return mMainStack.startActivityMayWait(caller,-1,intent,

resolvedType, resultTo, resultWho, requestCode, startFlags,

profileFile, profileFd, null, null, options, userId);

}


ActivityManagerService. startActivity方法将启动Activity的请求转发给ActivityStack.startActivityMayWait方法,传入该方法的主要参数如下。

1)caller:标识调用startActivity的进程,其类型为ApplicationThreadProxy。

2)Intent:标识要启动的组件,其包含的信息如下。

Action:android. intent.action.MAIN.

Categories:android. intent.category.LAUNCHER.

Component:要启动的Activity组件,值为com.android.settings/.Settings。

Flag:启动标记为0x102000000,即FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_FORWARD_RESULT。

3)resultTo:标识接受返回结果的一方,是一个ActivityRecord的Binder引用。本例中代表的是Launcher,其主要内容如下。

ActivityRecord{com. android.launcher/com.android.launcher2.Launcher}.

requestcode为-1。

resolvedType:标识Intent数据的MIME类型,此处为null。

2.ActivityStack.startActivityMayWait

预启动阶段的第二步是ActivityStack.startActivityMayWait,其作用是查询系统中与Intent匹配的Activity。调用startActivityLocked启动该Activity。代码如下:


final int startActivityMayWait(IApplicationThread caller, int callingUid,

Intent intent, String resolvedType, IBinder resultTo,

String resultWho, int requestCode, int startFlags,……){

……

//传入的Intent包含Component信息,此时componentSpecified将赋值为true

boolean componentSpecified=intent.getComponent()!=null;

//后续步骤需要修改客户端传入的Intent,这里重新封装,防止修改原始Intent

intent=new Intent(intent);

/*查询与该Intent匹配的Activity, resolveActivity需要调用

*PackageManagerService方法获取该Activity的信息。本例启动的是

*Settings,这里查询的自然是Settings的信息。其内容主要包含:

*launchmode:2

*processName:com.android.settings

*activityname:com.android.settings.Settings

taskAffinity:com.android.setting/

ActivityInfo aInfo=resolveActivity(intent, resolvedType, startFlags,

profileFile, profileFd, userId);

/*isSingleton用于判断要启动的Activity是否属于persistent或者system

进程,Settings既没有设置FLAG_PERSISTENT标记,也不属于system进程/

if(aInfo!=null&&mService.isSingleton(aInfo.processName,

aInfo.applicationInfo)){

userId=0;

}

aInfo=mService.getActivityInfoForUser(aInfo, userId);//运行时信息

synchronized(mService){

//用于区分调用端是否来自于应用程序

int callingPid;

if(callingUid>=0){

callingPid=-1;

}else if(caller==null){

/*启动Launcher或者用am start启动一个应用程序的

时候,caller便为null。此时需要记录调用方的PID和UID/

callingPid=Binder.getCallingPid();

callingUid=Binder.getCallingUid();

}else{

callingPid=callingUid=-1;

}

//是否需要更改Configuration信息,此处为false

mConfigWillChange=config!=null

&&mService.mConfiguration.diff(config)!=0;

final long origId=Binder.clearCallingIdentity();

/*FLAG_CANT_SAVE_STATE由AndroidManifest.xml的Application标签指定,该

*标签并未对SDK开放。系统中只有development/samples/HeavyWeight这一个

*示例应用使用到,配置为:

<application android:cantSaveState="true">/

if(mMainStack&&aInfo!=null&&(aInfo.applicationInfo.flags&

ApplicationInfo.FLAG_CANT_SAVE_STATE)!=0){

……

}

//将请求转发给startActivityLocked(caller,……)

int res=startActivityLocked(caller, intent, resolvedType,

aInfo, resultTo, resultWho, requestCode,……);

//更新Configuration信息,但此时mConfigWillChange为false,不执行这步

if(mConfigWillChange&&mMainStack){

……

}

Binder.restoreCallingIdentity(origId);

/*此例传入的outResult为null,不执行这步。只有调用ActivityManagerService

*的startActivityAndWait方法时,传入的outResult参数不为null,但startActivityAndWait

方法只在通过am start-W启动Activity的时候用到。-W的意思是wait/

if(outResult!=null){

……

}

return res;

}

}


startActivityMayWait方法的主要工作如下:

调用resovleActivity方法经由PackageManagerService查询系统中是否存在处理指定Intent的Activity,即找到Settings。resovleActivity属于PackageManagerService的范畴,这里不赘述。

根据caller判断启动Activity的客户端是应用程序还是其他进程(如adb shell)。

处理FLAG_CANT_SAVE_STATE标记,该标记目前只在示例程序中使用。

调用ActivityStack.startActivityLocked执行预启动阶段的第三步工作。

处理Configuration需要改变的情况,对于启动Settings应用,则不需要改变。

处理wait状态。正常启动应用程序不需要执行这个步骤,此例中startActivityMayWait其实是startActivity"Not"Wait。

当通过am start-W启动Activity时,需要处理wait状态,am start命令格式如下:


am start:start an Activity.Options are:

-D:enable debugging

-W:wait for launch to complete

—start-profiler<FILE>:start profiler and send results to<FILE>

-P<FILE>:like above, but profiling stops when app goes idle

-R:repeat the activity launch<COUNT>times.Prior to each repeat,

the top activity will be finished.

-S:force stop the target app before starting the activity

—opengl-trace:enable tracing of OpenGL functions


startActivityMayWait启动Activity的工作放在startActivityLocked方法中完成,该方法有两个重载方法,这里用到的是startActivityLocked(IApplicationThread caller,……),接下来分析该方法。

3.ActivityStack.startActivityLocked(IApplicationThread caller,……)

预启动阶段的第三步是ActivityStack.startActivityLocked,首先进行各种启动前的检查,检查通过后创建目标Activity的ActivityRecord,并将启动请求转发给startActivityUnchecked Locked处理。代码如下:


final int startActivityLocked(IApplicationThread caller,……){

int err=ActivityManager.START_SUCCESS;

ProcessRecord callerApp=null;

if(caller!=null){

/*获取caller的ProcessRecord,这里即Launcher对应的进程信息。

*ProcessRecord维护一个activities的列表,用于存储运行在该进程的

*Activity的ActivityRecord,比如com.android.launcher2.Launcher。

*应用程序本身都在ActivityManagerService的管理范围中,对于由应用程序

*发起的startActivity,都可以在ActivityManagerService中找到其对应的

ProcessRecord,这样可以确保调用方的权限匹配正确/

callerApp=mService.getRecordForAppLocked(caller);

if(callerApp!=null){

callingPid=callerApp.pid;//Launcher的PID

callingUid=callerApp.info.uid;//Launcher的UID

}else{

err=ActivityManager.START_PERMISSION_DENIED;

}

}

……

ActivityRecord sourceRecord=null;

ActivityRecord resultRecord=null;

if(resultTo!=null){//传入的resultTo参数代表Launcher

int index=indexOfTokenLocked(resultTo);

if(index>=0){//此时mHistory中只有Launcher, index为0

//取出Launcher的ActivityRecord

sourceRecord=mHistory.get(index);

/*传入的requestCode为-1,即不需要返回结果。对于需要返回结果的情况,发起

*startActivity的一方便是接收返回结果的一方(只要其状态不是finishing)。只有

*调用startActivityForResult时,传入的参数requestCode>=0才会接收返回

结果,详情请参阅SDK对于该方法的解释/

if(requestCode>=0&&!sourceRecord.finishing){

resultRecord=sourceRecord;

}

}

}

//获取Intent存储的启动标记(flag),处理FLAG_ACTIVITY_FORWARD_RESULT标记

int launchFlags=intent.getFlags();

if((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT)!=0

&&sourceRecord!=null){

……//本例中未设置FLAG_ACTIVITY_FORWARD_RESULT启动标记

}

……

if(err!=ActivityManager.START_SUCCESS){

/*指定了接收启动结果的Activity,通过sendActivityResultLocked

将错误结果返回,该错误结果为RESULT_CANCELED/

if(resultRecord!=null){

sendActivityResultLocked(-1,

resultRecord, resultWho, requestCode,

Activity.RESULT_CANCELED, null);

}

mDismissKeyguardOnNextActivity=false;

ActivityOptions.abort(options);

return err;

}

/*检查是否有启动Activity的权限,这里startAnyPerm不满足

条件,但componentPerm满足条件。因此权限检查过关/

final int startAnyPerm=mService.checkPermission(

START_ANY_ACTIVITY, callingPid, callingUid);

final int componentPerm=mService.checkComponentPermission(

aInfo.permission, callingPid, callingUid,

aInfo.applicationInfo.uid, aInfo.exported);

if(startAnyPerm!=PERMISSION_GRANTED&&

componentPerm!=PERMISSION_GRANTED)

{

……//RESULT_CANCELED

}

if(mMainStack){

if(mService.mController!=null){//没有设置IActivityCotroller

……//IActivityCotroller是ActivityManagerService的监听器

……//可以决定是否启动当前请求启动的Activity

}

}

//为将要启动的Activity创建ActivityRecord

//这里便是Settings的ActivityRecord

ActivityRecord r=new ActivityRecord(mService, this,……);

if(outActivity!=null){//null

outActivity[0]=r;

}

if(mMainStack){

/*mResumeActivity代表当前处于resume状态的Activity,即当前正在显示的

*Activity。因为是从Launcher启动Settings,此时Settings还未启动,这

里的mResumeActivity依然是Launcher/

if(mResumedActivity==null

||mResumedActivity.info.applicationInfo.uid!=callingUid){

/*如果没有当前正在显示的Activity,有理由怀疑发起startActivity的进程

*此时是否能够切换Activity。这种情况通常发生在startActivity发起方

进入pause/stop/destroy方法时,此时要暂停切换Activity/

if(!mService.checkAppSwitchAllowedLocked(callingPid,

callingUid,"Activity start")){

PendingActivityLaunch pal=new PendingActivityLaunch();

pal.r=r;

pal.sourceRecord=sourceRecord;

pal.startFlags=startFlags;

//如果没有权限,则将启动请求存入mPendingActivityLaunches后返回

mService.mPendingActivityLaunches.add(pal);

mDismissKeyguardOnNextActivity=false;

ActivityOptions.abort(options);

return ActivityManager.START_SWITCHES_CANCELED;

}

}

if(mService.mDidAppSwitch){//mDidAppSwitch为true

mService.mAppSwitchesAllowedTime=0;

}else{

mService.mDidAppSwitch=true;

}

/*启动mPendingActivityLaunches中存储的待启动Activity,

内部调用了startActivityUncheckedLocked/

mService.doPendingActivityLaunchesLocked(false);

}

//将请求转发给startActivityUncheckedLocked

err=startActivityUncheckedLocked(r, sourceRecord,

startFlags, true, options);

……

return err;

}


startActivityLocked(IApplicationThread caller,……)的工作可以归纳如下。

1)各种检查:检查调用方的权限、检查调用方是否需要返回结果、检查FLAG_ACTIVITY_FORWARD_RESULT标记、检查Intent是否正确、检查目标Activity是否存在、检查是否有startActivity权限、检查当前能否切换Activity。

2)检查通过后,创建目标Activity的ActivityRecord。

3)将请求转发给startActivityUncheckedLocked方法,进入预启动阶段的第四步。此时处于mPendingActivityLaunches列表中的待启动Activity将被优先处理。

由此可见,startActivityUncheckedLocked方法签名中Unchecked的意思是:经过这么多检查(check),终于不需要检查(uncheck)了。

接下来分析ActivityStack.startActivityUncheckedLocked方法。

4.ActivityStack.startActivityUncheckedLocked

预启动阶段的第四步是ActivityStack.startActivityUncheckedLocked,主要工作如下:

1)根据启动标记和启动模式,判断是否需要在新的Task中运行目标Activity。

2)判断是否有可复用的Task或者Activity。

3)将复用或新建的TaskRecord与ActivityRecord关联。

4)在ActivityManagerService中更新Task数量。

5)调用startActivityLocked方法进入预启动阶段的第五步。

源码异常复杂,下面分成五个阶段分别分析。

(1)确定待启动Activity是否需要运行新的Task

startActivityUncheckedLocked第一阶段的主要工作是确定待启动Activity是否需要运行新的Task,代码如下:


final int startActivityUncheckedLocked(ActivityRecord r,

ActivityRecord sourceRecord, int startFlags, boolean doResume,

Bundle options){

//从上步中创建的ActivityRecord取出相关信息

final Intent intent=r.intent;

final int callingUid=r.launchedFromUid;//Launcher的UID

final int userId=r.userId;//0

int launchFlags=intent.getFlags();//启动标记

//未设置FLAG_ACTIVITY_NO_USER_ACTION启动标记,mUserLeaving为true

mUserLeaving=(launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION)==0;

if(!doResume){//doResume设置是否立刻启动,传入的参数为true

r.delayedResume=true;

}

//未设置FLAG_ACTIVITY_PREVIOUS_IS_TOP启动标记,notTop为null

ActivityRecord notTop=

(launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)!=0?

r:null;

//未设置START_FLAG_ONLY_IF_NEEDED启动标记,不满足该条件该分支

if((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED)!=0){

……

}

if(sourceRecord==null){//不是由Activity发出的启动请求,本例不满足该分支

if((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK)==0){

//需要在新Task中启动

launchFlags|=Intent.FLAG_ACTIVITY_NEW_TASK;

}

}else if(sourceRecord.launchMode==ActivityInfo.LAUNCH_SINGLE_INSTANCE){

//本例Launcher的启动模式是singleTask,不匹配该分支

launchFlags|=Intent.FLAG_ACTIVITY_NEW_TASK;

}else if(r.launchMode==ActivityInfo.LAUNCH_SINGLE_INSTANCE

||r.launchMode==ActivityInfo.LAUNCH_SINGLE_TASK){//匹配该条件

launchFlags|=Intent.FLAG_ACTIVITY_NEW_TASK;

}

//本例resultTo为null,不接收返回结果,不满足该分支

if(r.resultTo!=null&&

(launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK)!=0){

//resultTo非null和FLAG_ACTIVITY_NEW_TASK不能共存

//返回RESULT_CANCELED,清空resultTo

sendActivityResultLocked(-1,r.resultTo, r.resultWho,

r.requestCode, Activity.RESULT_CANCELED, null);

r.resultTo=null;

}

……


startActivityUncheckedLocked第一阶段的工作主要根据启动标记(flag)和启动模式(Launch Mode)确定待启动Activity是否需要运行于新的Task。如果需要运行于新的Task并且指定了resultTo,即startActivityForResult方法的参数requestCode>=0,此时直接向caller返回RESULT_CANCELED,而不返回真正的启动结果。

需要在新的Task中运行Activity的条件有以下3种:

sourceRecord为null,即不是由Activity发出的启动请求,例如启动Launcher或者通过adb start启动指定Activity。本例中sourceRecord为Launcher。

sourceRecord的启动模式为singleInstance。

要启动的目标Activity的启动模式为singleInstance或者singleTask。

满足上述3个条件时,需要在Activity的启动标记中加入FLAG_ACTIVITY_NEW_TASK。在本例中,在Client端已经设置启动标记FLAG_ACTIVITY_NEW_TASK,因此Settings需要运行于新的Task。

这里涉及启动标记FLAG_ACTIVITY_NO_USER_ACTION,它与Activity的生命周期有关,具体的关系如下:

用于判断是否是用户行为导致Activity切换。例如当用户按Home键时,当前Activity切换到后台,此时会回调当前Activity生命周期的onUserLeaveHint方法;但如果是来电导致当前Activity切换到后台,则不会回调当前Activity生命周期的onUserLeaveHint方法。若在启动Activity的Intent中设置了FLAG_ACTIVITY_NO_USER_ACTION标记,则表明当前启动行为是非用户行为,这样被切换到后台的Activity便不会回调onUserLeaveHint方法。

Launcher在AndroidManifest.xml中配置的启动模式是singleTask,代码如下:


<activity

android:name="com.android.launcher2.Launcher"

android:launchMode="singleTask"

android:clearTaskOnLaunch="true"

……>

……

</activity>


Settings在AndroidManifest.xml中配置的启动模式是singleTask,代码如下:


<activity android:name="Settings"

android:label="@string/settings_label_launcher"

android:taskAffinity="com.android.settings"

android:launchMode="singleTask">

……

</activity>


关于Task和启动模式的内容,可参考以下Android官方开发者网站:

http://developer. android.com/guide/components/tasks-and-back-stack.html

http://developer. android.com/guide/topics/manifest/activity-element.html

http://developer. android.com/guide/practices/ui_guidelines/activity_task_design.html

(2)检查是否有可复用的Task或者Activity

startActivityUncheckedLocked第二阶段的主要工作是检查是否有可复用的Task或者Activity,如果发现有,则直接切换到该Task。代码如下:


final int startActivityUncheckedLocked(ActivityRecord r,

ActivityRecord sourceRecord, int startFlags, boolean doResume,

Bundle options){

……//省略第一阶段

boolean addingToTask=false;

boolean movedHome=false;

TaskRecord reuseTask=null;

//根据第一阶段的分析,满足该分支条件

if(((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK)!=0&&

(launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK)==0)

||r.launchMode==ActivityInfo.LAUNCH_SINGLE_TASK

||r.launchMode==ActivityInfo.LAUNCH_SINGLE_INSTANCE){

if(r.resultTo==null){//本例满足该分支

//查找是否有可复用的Task及其Activity

ActivityRecord taskTop=r.launchMode!=ActivityInfo.LAUNCH_SINGLE_INSTANCE

?findTaskLocked(intent, r.info)

:findActivityLocked(intent, r.info);

if(taskTop!=null){//本例中taskTop为null,无法复用

……

}

}

}


当满足以下任何一个条件,需要判断是否有可复用的Task:

1)在启动标记中设置了FLAG_ACTIVITY_NEW_TASK且未设置FLAG_ACTIVITY_MULTIPLE_TASK:


launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK)!=0&&

(launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK)==0


2)要启动的目标Activity的启动模式为singleTask:


r.launchMode==ActivityInfo.LAUNCH_SINGLE_TASK


3)要启动的目标Activity的启动模式为singleInstance:


ActivityInfo.LAUNCH_SINGLE_INSTANCE


Task是否可复用还与resultTo有关,即resultTo必须为null。

可复用Task的匹配原则如下:

原则1当要启动的目标Activity的启动模式非singleInstance时,遵循findTaskLocked方法的匹配规则。规则如下:

遍历mHistory中的ActivityRecord,查看该ActivityRecord所属Task的affinity是否与要启动的目标Activity的affinity相同,如果有则返回该ActivityRecord。

遍历mHistory中的ActivityRecord,查看该ActivityRecord所属Task的Intent是否与要启动的目标Activity有相同的Component,如果有则返回该ActivityRecord。

遍历mHistory中的ActivityRecord,查看该ActivityRecord所属Task的affinityIntent是否与要启动的目标Activity有相同的Component,如果有则返回该ActivityRecord。

原则2当要启动的目标Activity的启动模式为singleInstance时,遵循findActivityLocked方法的匹配规则。规则如下:

遍历mHistory中的ActivityRecord,查看该ActivityRecord所属Task的Intent是否与要启动的目标Activity有相同的Component,如果有则返回该ActivityRecord。

(3)查找是否有可复用的Activity

startActivityUncheckedLocked第三阶段的主要工作是查找是否有可复用的Activity,如果有,则调用resumeTopActivityLocked方法Resume该Activity。代码如下:


final int startActivityUncheckedLocked(ActivityRecord r,

ActivityRecord sourceRecord, int startFlags, boolean doResume,

Bundle options){

……//省略前两个阶段

if(r.packageName!=null){//本例packageName为com.android.settings

/*如果要启动的目标Activity与当前栈顶正在显示的Activity相同,需要

检查该Activity是否只需要启动一次。本例top为Launcher/

ActivityRecord top=topRunningNonDelayedActivityLocked(notTop);

if(top!=null&&r.resultTo==null){//满足

//前者是Launcher,后者为Settings,不满足下面的条件

if(top.realActivity.equals(r.realActivity)&&top.userId==r.userId){

if(top.app!=null&&top.app.thread!=null){

if((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP)!=0

||r.launchMode==ActivityInfo.LAUNCH_SINGLE_TOP

||r.launchMode==ActivityInfo.LAUNCH_SINGLE_TASK){

if(doResume){//直接恢复栈顶的Activity

resumeTopActivityLocked(null);

}

……

}

}else{

if(r.resultTo!=null){

sendActivityResultLocked(-1,r.resultTo, r.resultWho, r.requestCode,

Activity.RESULT_CANCELED, null);

}

ActivityOptions.abort(options);

return ActivityManager.START_CLASS_NOT_FOUND;

}


(4)关联TaskRecord与ActivityRecord

startActivityUncheckedLocked第四阶段的主要工作是将TaskRecord与ActivityRecord关联,同时在ActivityManagerService中需要记录当前Task的数量。代码如下:


final int startActivityUncheckedLocked(ActivityRecord r,

ActivityRecord sourceRecord, int startFlags, boolean doResume,

Bundle options){

//省略前三个阶段

boolean newTask=false;

boolean keepCurTransition=false;

//根据第三阶段的分析可知,满足该分支

if(r.resultTo==null&&!addingToTask

&&(launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK)!=0){

if(reuseTask==null){//满足

mService.mCurTask++;//在ActivityManagerService中记录Task数量

if(mService.mCurTask<=0){

mService.mCurTask=1;

}

/*创建TaskRecord表示一个Task,并将新创建的TaskRecord与

ActivityRecord关联,即每个Activity会存储其所处的Task/

r.setTask(new TaskRecord(mService.mCurTask, r.info, intent),null, true);

}else{

r.setTask(reuseTask, reuseTask, true);//复用已有Task

}

newTask=true;//标记创建了新的Task

if(!movedHome){

moveHomeToFrontFromLaunchLocked(launchFlags);

}

}

……//省略不满足本例条件的分支


(5)调用startActivityLocked方法

startActivityUncheckedLocked第五阶段的主要工作是,以第四阶段创建的ActivityRecord和TaskRecord为参数,调用startActivityLocked方法进入预启动阶段的第五步。代码如下:


final int startActivityUncheckedLocked(ActivityRecord r,

ActivityRecord sourceRecord, int startFlags, boolean doResume,

Bundle options){

//权限控制

mService.grantUriPermissionFromIntentLocked(callingUid,

r.packageName, intent, r.getUriPermissionsLocked());

//以ActivityRecord和TaskRecord为参数调用startActivityLocked

startActivityLocked(r, newTask, doResume, keepCurTransition, options);

return ActivityManager.START_SUCCESS;

}


5.ActivityStack.startActivityLocked(ActivityRecord r,……)

startActivityLocked(ActivityRecord r,……)是预启动阶段的第五步,它有一个重载函数,即startActivityLocked(IApplicationThread caller,……)在预启动阶段的第三步已经分析过。接下来分析startActivityLocked(ActivityRecord r,……),代码如下:


private final void startActivityLocked(ActivityRecord r, boolean newTask,

boolean doResume, boolean keepCurTransition, Bundle options){

//此时的mHistory中只有Launcher这一个ActivityRecord,因此NH等于1

final int NH=mHistory.size();

int addPos=-1;

/*不需要创建新的Task运行当前请求启动的Activity,本例不满足该分支。既然

不需要创建新Task,就需要找到已有Task并在该Task中启动Activity/

if(!newTask){

boolean startIt=true;

//从栈顶开始遍历非finishing状态的Activity

for(int i=NH-1;i>=0;i—){

ActivityRecord p=mHistory.get(i);

if(p.finishing){

continue;

}

//找到栈中第一个与当前请求启动的Activity(r)同属一个Task的Activity(p)

if(p.task==r.task){

addPos=i+1;//当前请求启动的Activity插入p之后的位置

/*p此时未必位于栈顶与用户交互,即可能处于后台,此时也不能立刻启动r。

只有p处于前台时,startIt赋值为false,此时才能将r加入mHistory中/

if(!startIt){

mHistory.add(addPos, r);

/*将inHistory赋值为true,表示已加入mHistory

中,并将Task中的activity计数加1/

r.putInHistory();

/*通过WindowManagerService为ActivityRecord创建

AppWindowToken,该对象对应于Activity的窗口/

mService.mWindowManager.addAppToken(addPos, r.appToken,

r.task.taskId, r.info.screenOrientation, r.fullscreen);

if(VALIDATE_TOKENS){

validateAppTokensLocked();

}

ActivityOptions.abort(options);

return;

}

break;

}

if(p.fullscreen){//只有p处在前台时,startIt赋值为false

startIt=false;

}

}

}

//将当前请求启动的Activity的位置设为栈顶,以便可以立刻与用户交互

if(addPos<0){

addPos=NH;

}

//当前请求启动的Activity如果不在栈顶,不执行onUserLeaving回调方法

if(addPos<NH){//不满足

mUserLeaving=false;

}

/*本例将Settings对应的ActivityRecord加入到mHistory,此时

mHistory中包含Launcher和Settings两个ActivityRecord/

mHistory.add(addPos, r);

/*将inHistory赋值为true,表示已加入mHistory中,并将task.numActivities

加1,标志向该Task中添加了一个Activity,此时该值为1/

r.putInHistory();

//将frontOfTask赋值为true,表示是该Task的第一个Activity

r.frontOfTask=newTask;

if(NH>0){//本例中,NH为1,满足条件

……//调用prepareAppTransition方法准备Activity切换动画

if(doResume){//满足该分支

resumeTopActivityLocked(null);

}

}


ActivityStack. startActivityLocked(ActivityRecord r,……)的主要工作是,将要启动的ActivityRecord添加到mHistory的适当位置,更新Task中Activity的计数,准备Activity的切换动画,调用resumeTopActivityLocked进入预启动阶段的第六步。

6.ActivityStack.resumeTopActivityLocked

预启动阶段的第六步是ActivityStack.resumeTopActivityLocked,主要工作是查找当前栈顶是否有需要显示的Activity。如果没有,则启动Home桌面(默认为Launcher)并返回;如果有需要显示的Activity,接着查找当前是否有需要暂停的Activity,如果有,则调用startPausingLocked将其暂停。代码如下:


final boolean resumeTopActivityLocked(ActivityRecord prev){

return resumeTopActivityLocked(prev, null);

}

//本例中两个参数均为null

final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options){

//取出第一个非finishing状态的activity,本例中即Settings

ActivityRecord next=topRunningActivityLocked(null);

//记录并重置mUserLeaving

final boolean userLeaving=mUserLeaving;//本例为true

mUserLeaving=false;

//没有满足条件的Activity,则启动Launcher,即Home桌面

if(next==null){//不满足

if(mMainStack){

ActivityOptions.abort(options);

return mService.startHomeActivityLocked(0);

}

}

next.delayedResume=false;

/*如果前端显示的Activity就是当前要启动的Activity,则直接返回。此时

前端显示的仍然是Launcher,且处于Resume状态,要启动的是Settings/

if(mResumedActivity==next&&next.state==ActivityState.RESUMED){

//只执行pending状态的切换动画,然后返回

mService.mWindowManager.executeAppTransition();

mNoAnimActivities.clear();

ActivityOptions.abort(options);

return false;

}

……

//如果当前有正在暂停的Activity,则直接返回

if(mPausingActivity!=null){//本例为null

return false;

}

/启动目标Activity前,需要首先暂停当前显示的Activity。本例中,当前显示的仍然为Launcher/

if(mResumedActivity!=null){

startPausingLocked(userLeaving, false);//本例中首先暂停

return true;//到这里就结束了,下面很多流程暂时不执行了

}

……//后续还会进入该方法以下流程

}


上述只是ActivityStack.resumeTopActivityLocked方法在预启动阶段的工作,后续还会进入该方法执行更重要的工作。