11.2 启动应用程序Activity时在Server端的执行流程
启动应用程序Activity的请求从Client端传递给Server端的ActivityManagerService后,便进入启动应用七个阶段,本节以在Home桌面启动Settings应用程序为例,详细分析这个过程。
11.2.1 预启动
预启动阶段主要由6步组成,其简要流程如图11-3所示。
图 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方法在预启动阶段的工作,后续还会进入该方法执行更重要的工作。