Android四大组件之Activity(四)—— 启动模式(launchMode) + Pause上一个Activity

1、使用的是Android 7.1.2的源代码:

https://pan.baidu.com/s/1XcVD68cC_2wKtm8jJkdNQA
przv

2、感谢IT先森的系列博客:

Android应用进程创建流程大揭秘
Android四大组件之bindService源码实现详解
Android四大组件之Activity启动流程源码实现详解概要
Activity启动流程(一)发起端进程请求启动目标Activity
Activity启动流程(二)system_server进程处理启动Activity请求
Activity启动流程(三)-Activity Task调度算法复盘分析
Activity启动流程(四)-Pause前台显示Activity,Resume目标Activity
Activity启动流程(五)请求并创建目标Activity进程
Activity启动流程(六)注册目标Activity进程到system_server进程以及创建目标Activity进程Application
Activity启动流程(七)初始化目标Activity并执行相关生命周期流程

疑问:
设置启动模式? ActivityStack栈管理,根据启动模式来判断是否启动栈
在ActivityStarter.startActivityUnChecked方法中进行处理

说实话,startActivityUnChecked函数中对栈处理的这部分内容我没看懂,就是了解了对于栈处理的内容在该函数中。

相关伪代码:

======system_server进程端======
AMS解析Intent	  
	AMS.startActivity(...)
	 ActivityStarter.startActivityMayWait(...)
	   ResolveInfo rInfo = ASS.resolveIntent(...)//收集Intent所指向的Activity信息, 当存在多个可供选择的Activity,则直接向用户弹出resolveActivity
	     IPackageManager.Stub.resolveIntent(...)//通过PKMS实体查询
		   PMS.resolveIntent(...)
			 PMS.queryIntentActivitiesInternal(...)
			 PMS.chooseBestActivity(...)
	   ActivityInfo aInfo = ASS.resolveActivity(...) //根据获取的rInfo信息重新组装intent和设置启动的参数信息
	   ActivityStarter.startActivityLocked(...)
		  ActivityRecord r = new ActivityRecord(callerApp,intent,aInfo,mSupervisor,...)
			appToken = new Token(this, _intent);
			  设置state为INITIALIZING
		  ActivityStarter.startActivityUnchecked(...) 
           //包括两方面内容:
           //1、AMS对于Activity比较复杂的部分即Task任务栈和Stack的处理,其中会把目标Activity放置到栈顶端
           //2、resumed相关操作 
           // 目标Activity所属Stack栈存在Resume状态的Activity时会执行其onPause方法,否则执行的就是其它Stack栈中的了
           // 错误说法:启动一个Activity的时候最先被执行的是栈顶的Activity的onPause方法       
    	  ActivityStackSupervisor.resumeFocusedStackTopActivityLocked
    			ActivityStack.resumeTopActivityUncheckedLocked
    				ActivityStack.resumeTopActivityInnerLocked
    					ActivityStack.startPausingLocked
    						ApplicationThreadProxy.schedulePauseActivity


======发起端进程处理schedulePauseActivity======
   ActivityThread.ApplicationThread.schedulePauseActivity
        ActivityThread.H.handleMessage(case PAUSE_ACTIVITY)
             ActivityThread.handlePauseActivity //1.指定前台Activity的onPause();2.通过AMP回调activityPaused()通知AMS
             	ActivityThread.performPauseActivity
              		ActivityThread.performPauseActivityIfNeeded
              			Instrumentation.callActivityOnPause
              				Activity.performPause
              					Activity.onPause()
                ActivityManagerNative.getDefault().activityPaused(token);


======system_server进程端======
    AMS.activityPaused
    	ActivityStack.activityPausedLocked
    		ActivityStack.completePauseLocked
    		   ActivityStackSupervisor.resumeFocusedStackTopActivityLocked  //又调用了resumeFocusedStackTopActivityLocked
    				ActivityStack.resumeTopActivityUncheckedLocked
    					ActivityStack.resumeTopActivityInnerLocked
    						ActivityStackSupervisor.startSpecificActivityLocked
    							AMS.startProcessLocked
    								AMS.startProcessLocked
    									AMS.newProcessRecordLocked

一、启动模式(launchMode)

Activity在 AndroidManifest.xml 文件中定义Activity时,可以通过launchMode属性来指定这个Activity应该如何与任务进行关联,取值有如下四种,不同的启动模式在启动 Activity时会执行不同的逻辑,系统会按不同的启动模式将Activity存放到不同的 Activity 栈中:

  • standard(默认的启动模式):
    LAUNCH_MULTIPLE,每次启动新Activity,都会创建新的Activity
  • singleTop:
    LAUNCH_SINGLE_TOP,当启动新Activity,如果在栈顶存在相同的Activity,则不会创建新的Activity,其余情况同上。
    比如我们使用一款视频APP观看短视频,视频播放页面同时还推荐了类似视频
    当我们点击了推荐视频,事件顺序大概是:打开视频播放页面 -> 点击推荐视频 -> 复用当前页面播放推荐视频,同时刷新推荐列表
    即栈顶对象可复用,没必要新建一个实例。
  • singleTask:
    LAUNCH_SINGLE_TASK,当启动新Activity,在栈中存在相同的Activity(可以是不在栈顶),则不会创建新的Activity,而是移除该Activity之上的所有Activity,其余情况同上。
    比如我们使用一款购物APP购买商品,Activity打开顺序大概是:商品页面 - 下单页面 - 支付页面 - 交易完成界面
    显然,我们完成时,需要返回商品页面,没必要返回支付页面,因为订单已经结束,因此我们需要在回到商品页面时销毁下单和支付页面
    即Activity顶部的任务已过期,没必要再保留。
  • singleInstance:
    LAUNCH_SINGLE_INSTANCE,单例模式,每个Task栈只有一个Activity,其余情况同上
    在一个新栈中创建该Activity的实例,并让多个应用共享该栈中的该Activity实例。一旦该模式的Activity实例已经存在于某个栈中,任何应用再激活该Activity时都会重用该栈中的实例( 会调用实例的 onNewIntent() )。其效果相当于多个应用共享一个应用,不管谁激活该 Activity 都会进入同一个应用中。使用场景如闹铃提醒,将闹铃提醒与闹铃设置分离。singleInstance不要用于中间页面,如果用于中间页面,跳转会有问题,比如:A -> B (singleInstance) -> C,完全退出后,在此启动,首先打开的是B。
//[ActivityInfo.java]
public class ActivityInfo extends ComponentInfo
        implements Parcelable {
     
    ...
    public static final int LAUNCH_MULTIPLE = 0;
    public static final int LAUNCH_SINGLE_TOP = 1;
    public static final int LAUNCH_SINGLE_TASK = 2;
    public static final int LAUNCH_SINGLE_INSTANCE = 3;
	...
}

二、启动的Flag值

  • FLAG_ACTIVITY_NEW_TASK,将Activity放入一个新启动的Task,注意属性task:affinity
  • FLAG_ACTIVITY_CLEAR_TASK,启动Activity时,将目标Activity关联的Task清除,再启动该Task,将该Activity放入该Task,也就是说,这个新启动的activity变为了这个空Task的根activity.所有老的activity都结束掉。该flags跟FLAG_ACTIVITY_NEW_TASK配合使用
  • FLAG_ACTIVITY_CLEAR_TOP,启动非栈顶Activity时,先清除该Activity之上的Activity。例如Task已有A、B、C三个Activity,启动A,则清除B,C。类似于SingleTop
  • FLAG_ACTIVITY_PREVIOUS_IS_TOP,A->B->C,若B启动C时用了这个标志位,那在启动时,B并不会被当作栈顶的Activity,而是用A做栈顶来启动C,此过程中B充当一个跳转页面,典型的场景是在应用选择页面。如果在文本中点击一个网址要跳转到浏览器,而系统中又装了不止一个浏览器应用,此时会弹出应用选择页面。在应用选择页面选择某一款浏览器启动时,就会用到这个Flag。
  • START_FLAG_ONLY_IF_NEEDED,该flag表示只有在需要的时候才启动目标Activity。也就是说如果调用者和被启动的是一个,那么就没有必要去进行重复的步骤了

Android Intent的FLAG标志详解:https://www.jianshu.com/p/537aa221eec4

Activity的flag常用值:

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

Android上进行多任务处理:
点击Home键,长按Home键或通过其它方式可以看到当前启动的任务。每个任务都具有自己的Activity堆栈。用户返回主屏幕并选择启动任务A的应用,现在,任务A进入前台,其堆栈中的所有三个Activity都完好如初,堆栈顶部的Activity恢复运行。此时,用户仍可通过以下方式切换到任务B:①转到主屏幕并选择启动该任务的应用图标 ②从最近的应用中选择该应用的任务。

了解任务和返回堆栈:
https://developer.android.google.cn/guide/components/activities/tasks-and-back-stack

疑问:使用intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)的话,回到主屏幕,显示的还是只有主程序这一个Task啊?
答:因为没有使用 android:taskAffinity

三、AMS对Activity的4种启动模式的处理方式

1、ActivityStarter.startActivityLocked

final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
TaskRecord inTask)

  • ActivityInfo中包含各种的activity信息,都是声明在AndroidManifest.xml文件中的,比较重要的包括launchMode、theme、screenOrientation等。
  • ResolveInfo是一个容器类,里面包含了ActivityInfo、ServiceInfo、ProviderInfo等成员变量来表示四大组件的信息。activity和broadcast信息都是用ActivityInfo来表示的。
  • IBinder resultTo是 发起端Activity的ActivityRecord对象中的Token,其Binder实体在AMS中,这个值是在Activity.startActivity中赋值传递过来的,具体:Activity中的mToken
  • inTask 指定待启动的Activity的任务栈,此处为null
    Android四大组件之Activity(四)—— 启动模式(launchMode) + Pause上一个Activity_第1张图片

startActivityLocked方法的主要逻辑如下:

  • 进一步对发起端的进程做一些权限检查,然后接着确定 sourceRecord 和 resultRecord 的值
  • 接着通过 上述确认的参数构建关于目标Activity的 ActivityRecord (经过复杂的判定,只是创建了一个ActivityRecord)
  • 创建 ActivityRecord 之后,也有一些处理,包括 AppSwitch,优先启动之前被阻塞的 Activity,然后进入下一阶段 startActivityUnchecked(…) ,从该方法名看出该做的检查已经做完了,剩下的函数调用就不需要进行额外的检查了(Unchecked),在分析Android源码中经常会看到类似的命名规则。
  • 调用startActivityUnchecked(),开展后续的Activity启动

2、ActivityStarter.startActivityUnchecked

负责调度ActivityRecord和TaskRecord、resumed相关操作

该方法的具体作用:

  • 初始化Activity启动状态
  • 计算launchFlag
  • 计算调用者的ActivityStack
  • 检查是否存在复用的TaskRecord
  • 对于存在复用的TaskRecord则进行相应的ActivityStack、TaskRecord的移动 (有难度)
  • 计算当前启动Activity所属的TaskRecord
  • 把当前启动的Activity放到所属TaskRecord的栈顶

大致代码:

ActivityStarter.startActivityUnchecked()
    setInitialState()  //给要启动的ActivityRecord(mStartActivity)等赋值ActivityRecord mStartActivity = r;
    computeLaunchingTaskFlags()  //根据launchMode和 Intent 中的 FLAG_ACTIVITY_NEW_TASK 等 flag 综合计算 Activity 的启动模式,结果保存在mLaunchFlags 中,计算的过程不仅要考虑目标 activity 的 launchMode ,也要考虑原来 Activity 的 launchMode 和 Intent 中所带着的 Flag
    computeSourceStack()  //根据发起方ActivityRecord:mSourceRecord来找到源任务栈:mSourceTask
    getReusableIntentActivity()  //查找可重用的Activity,只对启动模式LAUNCH_SINGLE_INSTANCE和LAUNCH_SINGLE_TASK或者FLAG_ACTIVITY_NEW_TASK不为0的Activity才有用,对于standard的activity,该方法永远返回null。
   
    //if(mReusedActivity != null)
    performClearTaskForReuseLocked() //遍历TaskRecord对象实例中的ActivityRecord列表,然后根据一定的规则清除可复用的activity上面的activity
    
    //经过上面步骤后,不管是否进行了栈顶数据的清除,接下来就要将我们可以复用的Activity所在的TaskRecord移动到其所在的ActivityStack的顶部
    
    setTargetStackAndMoveToFrontIfNeeded() //将复用ActivityRecord所属的TaskRecord和ActivityStack移动到顶端,必要时会进行task的清理工作
    	ActivityStack.moveTaskToFrontLocked()
    setTaskFromIntentActivity()
    ...
    //在同一个应用中从Activity A启动 Activity B不会走此分支
	if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
     
         ··· ···
    }else if(mSourceRecord != null){
     
        // 不是新建task的,重用原activity的task
            final int result = setTaskFromSourceRecord();
			/*****************************************************************************/	
				//这里小伙们就不要关注排版问题了,主要是为了演示整个流程,各位就将就一下 
			    private int setTaskFromSourceRecord() {
     
					//获取启动Activity的任务栈
			        final TaskRecord sourceTask = mSourceRecord.task;
			        //此时的发起端Actiivty所在的TaskRecord就是处于sourceStack栈顶,所以sourceStack.topTask就是要启动的Activity所在的栈
			        //如果目标Activity不允许在屏幕上显示或者源任务栈和目标任务不在同一个栈
			        final boolean moveStackAllowed = sourceTask.stack.topTask() != sourceTask;
					//获取当前要启动activity所属的ActivityStack栈
			        if (moveStackAllowed) {
     //不会进入此分支						
						...
			        }
					
					//目标ActivityStack为空
			        if (mTargetStack == null) {
     
			            mTargetStack = sourceTask.stack;//进入此分支
			        } else if (mTargetStack != sourceTask.stack) {
     
			        	//把启动方的任务栈绑定到目标ActivityStack上
						...
			        }
			        if (mDoResume) {
     
			            mTargetStack.moveToFront("sourceStackToFront");
			        }
			
					//获取目标ActivityStack的顶部task
			        final TaskRecord topTask = mTargetStack.topTask();
			        if (topTask != sourceTask && !mAvoidMoveToFront) {
     //不会走入此分支
						
			        }
			
					//如果目标activity还没有加入到栈中,而且启动标志设置了CLEAR_TOP,那么我们将Activity添加到已经存在的任务栈中,并调用clear方法清空对应的activity
			        if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
     //很明显不会进入此分支
						...
			        } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
     //不会进入此分支
						...
			        }
			        mStartActivity.setTask(sourceTask, null);//设置目标Activity B的Task为A Activity所属的Task

			        return START_SUCCESS;
			    }				
			/*****************************************************************************/						            
            if (result != START_SUCCESS) {
     
                return result;
            }
        } else if (mInTask != null) {
     //启动时指定了目标栈(mInTask),ActivityRecord绑定到mInTask,此场景下不会进入此分支
			...
        } else {
     //不会进入此分支,忽略
			..,
        }		
		...
		/*把当前启动的Activity加入TaskRecord以及绑定WindowManagerService*/
        mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);	
		/*****************************************************************************/	
			//这里小伙们就不要关注排版问题了,主要是为了演示整个流程,各位就将就一下  
		    final void startActivityLocked(	ActivityRecord r, //此时的r为目标Activity
		    								boolean newTask, //newTask表示是否要创建Task,为true
		    								boolean keepCurTransition,
		            						ActivityOptions options) 
		   {
     
		        TaskRecord rTask = r.task;
		        final int taskId = rTask.taskId;
				
		        if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
     //不会进入此分支
					...
		        }
		        TaskRecord task = null;
		        if (!newTask) {
     //newTask为false会走入此分支
					...
		        }
		
				...
		
		        task = r.task;
		
				//将Activity移动到Stack的顶端 ====== 重点
		        task.addActivityToTop(r);
		        task.setFrontOfTask();
		
		        r.putInHistory();
		        if (!isHomeStack() || numActivities() > 0) {
     //会进入此分支,此时的ActivityStack不是HomeStack
					//这个地方很重要
		            addConfigOverride(r, task);
		        } else {
     //不会进入此分支
					...
		        }
		        ...
		    }	
    }
   
    ···
  
    if (mDoResume) {
     
            if (!mLaunchTaskBehind) {
     
			/*
			  *设置当前focused,因为经过以上几步,启动的activity已经转移到
			  *栈顶端,这时候设置AMS当前focused的Activity
			  *另外调用这个函数也会有ActivityStack、Task栈的移动,即调用各自栈把当
			  *前正在启动的Activity所属的Task、ActivityStack移动到栈顶
			  */
                mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
            }
            final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
            if (!mTargetStack.isFocusable()//当前的目标Stack被设置成了焦点所以不会走此分支
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {
     
                    ...
            } else {
     
            	//开始resume,详见 ======8========
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
        } else {
     
            mTargetStack.addRecentActivityLocked(mStartActivity);
        }

    return START_SUCCESS;
        ...

其中,computeLaunchingTaskFlags():根据发起端/目的端的launchMode和以及Intent中的携带的FLAG_ACTIVITY_NEW_TASK等flag综合计算activity的启动模式或者说调整启动目标Activiyt的启动模式。

在Activity Task调度算法复盘分析中分析了三种情况:

从Launcher桌面第一次启动应用时的任务调度情况

任务调度时会创建新task,并将新的ActivityRecord加入这个新的task,然后将task放入合适的Stack的栈顶

应用内Activity跳转时的任务调度情况

任务调度时会将新的ActivityRecord加入已有的task,然后将该ActivityRecord移动到Task顶端,然后将task放入合适的Stack的栈顶

然后按Home键,再打开应用程序时的调度情况:

任务调度时会先找到已有的相关task,并显示栈顶的Activity

3、ActivityStarter.resumeFocusedStackTopActivityLocked(system_server进程)

Activity A 启动 Activity B的正常生命周期调度:

---> Activity A onCreate
---> Activity A onStart 
---> Activity A onResume
---> Activity A onPause
---> Activity B onCreate
---> Activity B onStart
---> Activity B onResume
---> Activty  A onStop

3.1、ActivityStarter.startActivityUnchecked

//[ActivityStarter.java]
    private int startActivityUnchecked(final ActivityRecord r, //r是指本次的将要启动的Activity
    									ActivityRecord sourceRecord, //sourceRecord是指发起调用者
            							IVoiceInteractionSession voiceSession, 
            							IVoiceInteractor voiceInteractor,
            							int startFlags,  //startFlags取值为0
            							boolean doResume, //doResume的值为true
            							ActivityOptions options, 
            							TaskRecord inTask) {
     
         ...
        if (mDoResume) {
     
            if (!mLaunchTaskBehind) {
     
			/*
			  * 设置当前focused,因为经过以上几步,启动的activity已经转移到
			  * 栈顶端,这时候设置AMS当前focused的Activity
			  * 另外调用这个函数也会有ActivityStack、Task栈的移动,即调用各自栈把当
			  * 前正在启动的Activity所属的Task、ActivityStack移动到栈顶
			  */
                mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
            }
            final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked(); //目标Activity
            if (!mTargetStack.isFocusable()//当前的目标Stack被设置成了焦点所以不会走此分支
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {
     
                    ...
            } else {
     
            	//开始resume
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
        } else {
     
            mTargetStack.addRecentActivityLocked(mStartActivity);
        }

  return START_SUCCESS;
        ...
}

3.2、ActivityStackSupervisor.resumeFocusedStackTopActivityLocked

//[ActivityStackSupervisor.java]
    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, 
            ActivityRecord target, //(1).由3.1传递过来的值为Activity B; (2).由5.2传递过来的值为Activity A
            ActivityOptions targetOptions) {
     
        if (targetStack != null && isFocusedStack(targetStack)) {
     
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
		...
    }

3.3、ActivityStack.resumeTopActivityUncheckedLocked

//[ActivityStack.java]
    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
     
        if (mStackSupervisor.inResumeTopActivity) {
     
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
     
			...
            result = resumeTopActivityInnerLocked(prev, options);//prev:目标Activity的相关信息 options:额外附加信息
        } finally {
     
            mStackSupervisor.inResumeTopActivity = false;
        }
        return result;
    }

3.4、ActivityStack.resumeTopActivityInnerLocked:准备Pause前一个Resumed的Activity,即Activity A

//[ActivityStack.java]
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
     


        if (!mService.mBooting && !mService.mBooted) {
     
        	// 如果系统还未启动完毕,那AMS还不能正常工作,所以也不能显示Activity,主要是为防止没有开机启动完成
            return false;
        }
		//此处忽略
        ActivityRecord parent = mActivityContainer.mParentActivity;
		...

		// 当前ActivityStack中可能存在一些正处于Intializing状态的ActivityRecord,
	    // 如果这些ActivityRecord不是位于栈顶,而且正在执行窗口启动动画,
	    // 那么,就需要取消这些Activity的启动动画。
        mStackSupervisor.cancelInitializingActivities();


        /*
	        找到第一个没有finishing的栈顶activity,通常指向了要启动的Activity目标组件
	        此场景下prev和next都是同一个,都指向了Activity B
        */
        final ActivityRecord next = topRunningActivityLocked();


        //这个变量是表示是否回调Activity中的onUserLeaveHint和onUserInteraction函数
        final boolean userLeaving = mStackSupervisor.mUserLeaving;
        mStackSupervisor.mUserLeaving = false;

        final TaskRecord prevTask = prev != null ? prev.task : null;
        if (next == null) {
     //这个表示如果当前ActivityStack不存在待启动的Activity,那么会启动Launcher桌面
            final String reason = "noMoreActivities";
            final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack()
                    ? HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();

			// 当前AS不是全屏显示,则需要将焦点切换到下一个待显示的AS
            if (!mFullscreen && adjustFocusToNextFocusableStackLocked(returnTaskType, reason)) {
     
                return mStackSupervisor.resumeFocusedStackTopActivityLocked(
                        mStackSupervisor.getFocusedStack(), prev, null);
            }

            
            ActivityOptions.abort(options);

			// 默认情况下,Stack都是占据全屏的,所以,当前Stack如果没有要显示的Activity,则会要求显示桌面
            return isOnHomeDisplay() &&
                    mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason);
        }

        next.delayedResume = false;


        //检查要启动的Activity 组件是否等于当前被激活的 Activity 组件,如果等于
        //并且处于 RESUMED 状态,直接返回,我们前面演示的启动情况很显然不满足条件
        if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
                    mStackSupervisor.allResumedActivitiesComplete()) {
     
             //当前正在显示的Activity正好就是下一个待显示的Activity,
            // 那么,就中断对目标ActivityRecord的调度
            mWindowManager.executeAppTransition();
            mNoAnimActivities.clear();
            ActivityOptions.abort(options);
            return false;
        }

        final TaskRecord nextTask = next.task;
         /*这个是对上一个resumed的Activity的相关处理
		 * 由于我们是第一次启动B Activity,所以不可能处于finish跳过此处
		 */
        if (prevTask != null && prevTask.stack == this &&
                prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
     
			...
        }

        // 系统进入休眠状态,当前Stack的栈顶Activity已经处于Paused状态
        // 那么,中断待显示Activity的相关调度(有点拗口,学习源码就是这么枯燥的事情)
        if (mService.isSleepingOrShuttingDownLocked()
                && mLastPausedActivity == next
                && mStackSupervisor.allPausedActivitiesComplete()) {
     
            mWindowManager.executeAppTransition();
            mNoAnimActivities.clear();
            ActivityOptions.abort(options);
            return false;
        }

		...

		/*
			在ASS中存在很多的数据结构,用来统一管理ActivityRecord的状态
	    	譬如mStoppingActivities记录了当前所有处于Stopping状态的ActivityRecord
	    	mGoingToSleepActivities记录了当前所有要进入休眠状态的ActivityRecord
	    	在某些场景下,待显示的ActivityRecord可能处于这些数组中,但需要从中剔除
		*/
        mStackSupervisor.mStoppingActivities.remove(next);
        mStackSupervisor.mGoingToSleepActivities.remove(next);
        next.sleeping = false;
        mStackSupervisor.mWaitingVisibleActivities.remove(next);

        

         // 如果当前ASS中还有ActivityRecord不是处于PAUSED, STOPPED或STOPPING这三个状态之一,
    	// 那么,需要先等这些ActivityRecord进入停止状态
        if (!mStackSupervisor.allPausedActivitiesComplete()) {
     
            return false;
        }
        
        /*****************************************************************************************************************
       上述代码的作用:准备阶段,做一些初始化和可能的"异常"处理工作,在执行目标Activity的onCreate/onStart/onResume状态,还有很多障碍和初始化工作需要处理。比如系统要休眠时,当前启动目标Activity过程要中断;当ASS中有Activity处于Pausing状态时,要等相关的Activity执行完毕。 
       *****************************************************************************************************************/
        
        //[ActivityStack.java]
		/*
			setLaunchSource设置待启动的Activity的信息
			跟进setLaunchSource源码发现它最终会获取一个WakeLock,保证在显示Activity的过程中,系统不会进行休眠状态
		*/
        mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
        

         /*
           目标Activity的启动参数中是否包含FLAG_RESUME_WHILE_PAUSING
   		   如果存在FLAG_RESUME_WHILE_PAUSING的flag,表示可以在当前显示的发起端Activity执行Pausing时,
   		   能同时进行Resume操作
    	   即变量dontWaitForPause的取意就是不需要等到Activity执行Pause完毕
    	*/
        final boolean dontWaitForPause = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;


		/* 
		  这个是pause掉不是FocusedStack的其它ActivityStack的栈顶activity
 		  对于不是当前focusStack的并且存在有mResumedActivity不为null的都要paused
 		  譬如从Luncher启动一个新的App时会走入此分支(FLAG_ACTIVITY_NEW_TASK)

		 从5.2走过来,即已经pause Activity A时,没有需要要进行pause
 		*/
		boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
		/********************************************************************************/
			//这里是为了演示使用
			//ASS.java
		    boolean pauseBackStacks(boolean userLeaving, boolean resuming, boolean dontWait) {
     
		        boolean someActivityPaused = false;
		        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
     
		            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
		            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
     
		                final ActivityStack stack = stacks.get(stackNdx);
		                if (!isFocusedStack(stack) && stack.mResumedActivity != null) {
     
		                    someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
		                            dontWait);
		                }
		            }
		        }
		        return someActivityPaused;
		    }			
		/********************************************************************************/

		//从3.2走过来,此时要带入真实场景了,此时的mResumedActivity表示目标Stack栈中处于Resume状态的Activity,那么在此场景下就是Activity A,这个因该比较容易理解
		//从5.2走过来,此时要带入真实场景了,此时的mResumedActivity表示目标Stack栈中处于Resume状态的Activity,通过前面的分析可以此时没有处于Resume状态的Activty了,所以不会走入此分支
		if (mResumedActivity != null) {
     
			// 当前resumed状态activity不为空,则需要先暂停该Activity
			// pause当前栈的activity,即执行Activity的生命周期onPause
            pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);//-->进入这里
			
        }
        //从3.2走过来,当前有正在pause的Activity,尼玛按照我们场景Activity A启动Activity B,那不是到此就结束了啊,直接返回了,事实就是这样的,尼玛是不是走错片场了,后续你就知道了
        //从5.2走过来,不会进入此分支
        if (pausing) {
     
            if (next.app != null && next.app.thread != null) {
     
                mService.updateLruProcessLocked(next.app, true, null);
            }
            return true;
        }
         //检查要启动的Activity 组件是否等于当前被激活的 Activity 组件,如果等于
        //并且处于 RESUMED 状态,直接返回,我们前面演示的启动情况很显然不满足条件 
        else if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
                mStackSupervisor.allResumedActivitiesComplete()) {
     
            mWindowManager.executeAppTransition();
            mNoAnimActivities.clear();
            ActivityOptions.abort(options);
            return true;
        }

		//3.2 不往下执行
		//5.2 往下执行
		··· ···
            
       //[ActivityStack.java]
		//对已经Pause的Activity继续处理,主要是通知WMS做进一步的处理
        if (prev != null && prev != next) {
       //prev是Activity A,next是Activity B
            if (!mStackSupervisor.mWaitingVisibleActivities.contains(prev)
                    && next != null && !next.nowVisible) {
     
                mStackSupervisor.mWaitingVisibleActivities.add(prev);
            } else {
     
                if (prev.finishing) {
     
                    mWindowManager.setAppVisibility(prev.appToken, false);
                } else {
     
                }
            }
        }


        try {
     
        	 // 通过PackageManager修改待启动Package的状态
            AppGlobals.getPackageManager().setPackageStoppedState(
                    next.packageName, false, next.userId); /* TODO: Verify if correct userid */
        } catch (RemoteException e1) {
     
        } catch (IllegalArgumentException e) {
     
        }

		...

        ActivityStack lastStack = mStackSupervisor.getLastStack();
		//next.app :ProcessRecord
         //next.app.thread : IApplicationThread
        if (next.app != null && next.app.thread != null) {
      //如果目的端进程已经创建,即要启动的目标Activity所属进程已经存在
			...
            next.state = ActivityState.RESUMED;
            mResumedActivity = next;
            next.task.touchActiveTime();
            mRecentTasks.addLocked(next.task);
            mService.updateLruProcessLocked(next.app, true, null);
            updateLRUListLocked(next);
            mService.updateOomAdjLocked();
			...
            try {
     
			
				...

                next.sleeping = false;
                mService.showUnsupportedZoomDialogIfNeededLocked(next);
                mService.showAskCompatModeDialogLocked(next);
                next.app.pendingUiClean = true;
                next.app.forceProcessStateUpTo(mService.mTopProcessState);
                next.clearOptionsLocked();
				//执行目的端Activity的scheduleResumeActivity操作
                next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
                        mService.isNextTransitionForward(), resumeAnimOptions);
				...
            } catch (Exception e) {
     
				...
            }

            try {
     
                completeResumeLocked(next);
            } catch (Exception e) {
     
				//处理异常
                requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
                        "resume-exception", true);
                return true;
            }
        } else {
     //当目标Activity所属进程没有启动的时候,则会创建进程

            if (!next.hasBeenLaunched) {
     
                next.hasBeenLaunched = true;
            } else {
     
                if (SHOW_APP_STARTING_PREVIEW) {
     
                    next.showStartingWindow(null, true);
                }
            }
			
			//创建目标Activity进程   -->到5.3
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
		
        }
        return true;
    }

要显示的目标Activity已经做好入栈操作了,就是放在Stack的栈顶,可以通过ActivityStack.topRunningActivityLocked()找到它。

如果当前要Resume的目标Activity不是之前已经Resume的Activity,那么必须将Pause之前的Activity:

1)Pause其他任务栈的mResumedActivity,调用ASS.pauseBackStacks(之前resume的Activity在其他任务栈中)

2)Pause当前任务栈的mResumedActivity,调用 ActivityStack.startPausingLocked(“1)”最后也会调用到这个函数)

接下来,执行Pause ActivityA 的操作:

3.5、ActivityStack.startPausingLocked

//[ActivityStack.java]
    final boolean startPausingLocked(boolean userLeaving, 
    								boolean uiSleeping, //此时传递进来的参数为false
    								boolean resuming,//此时传递进来的参数为true
            						boolean dontWait) 
   {
     
        //判断当前的Stack栈中是否存在正在pausing的Activity
        if (mPausingActivity != null) {
     
            if (!mService.isSleepingLocked()) {
     
                completePauseLocked(false);
            }
        }
        
        //获取当前Stack栈中处于Resume状态的Activity,在我们当前的环境下就是Activity A了
        ActivityRecord prev = mResumedActivity;
        if (prev == null) {
     
            if (!resuming) {
     
                mStackSupervisor.resumeFocusedStackTopActivityLocked();
            }
            return false;
        }

		...
		// 变更ActivityStack中pauseActivity的记录,此处是重点
        mResumedActivity = null;
        mPausingActivity = prev;
        mLastPausedActivity = prev;
        mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
                || (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
        prev.state = ActivityState.PAUSING;
        prev.task.touchActiveTime();
        clearLaunchTime(prev);
        
		...
		 // 通知APP执行发起端的pause操作
        if (prev.app != null && prev.app.thread != null) {
     
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
            try {
     
                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
                        prev.userId, System.identityHashCode(prev),
                        prev.shortComponentName);
                mService.updateUsageStats(prev, false);
                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                        userLeaving, prev.configChangeFlags, dontWait);//-->进入Activity A的进程
            } catch (Exception e) {
     
                mPausingActivity = null;
                mLastPausedActivity = null;
                mLastNoHistoryActivity = null;
            }
        } else {
     
            mPausingActivity = null;
            mLastPausedActivity = null;
            mLastNoHistoryActivity = null;
        }

		//获取锁,防止休眠
        if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) {
     
            mStackSupervisor.acquireLaunchWakelock();
        }

        if (mPausingActivity != null) {
     
            if (!uiSleeping) {
     
                prev.pauseKeyDispatchingLocked();
            } else if (DEBUG_PAUSE) {
     
            }

            if (dontWait) {
     
                completePauseLocked(false);
                return false;

            } else {
     
            	//这个是经典的ANR埋雷,监控APP是否pause超时,时间只有500ms
                Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
                msg.obj = prev;
                prev.pauseTime = SystemClock.uptimeMillis();
                mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
                return true;
            }

        } else {
     
			...
        }
    }

4、ActivityThread.ApplicationThread.schedulePauseActivity(Activity A所在进程)

进入Activity A所在进程,处理Pause

4.1、ActivityThread.ApplicationThread.schedulePauseActivity

//[ActivityThread.java]
    private class ApplicationThread extends ApplicationThreadNative {
     
        public final void schedulePauseActivity(IBinder token, boolean finished,
                boolean userLeaving, int configChanges, boolean dontReport) {
     
            int seq = getLifecycleSeq();
            sendMessage(
                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                    token,
                    (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
                    configChanges,
                    seq);//详见1.3.2
        }    	
    }

4.2、ActivityThread.H.handleMessage

//ActivityThread.java
private class H extends Handler {
     
	public void handleMessage(Message msg) {
     
	    switch (msg.what) {
     
	        ...
                case PAUSE_ACTIVITY: {
     
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                    SomeArgs args = (SomeArgs) msg.obj;
                    handlePauseActivity((IBinder) args.arg1, false,
                            (args.argi1 & USER_LEAVING) != 0, args.argi2,
                            (args.argi1 & DONT_REPORT) != 0, args.argi3);//详见章节1.3.3
                    maybeSnapshot();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
	        ...
	    }
	}
}

4.3、ActivityThread.handlePauseActivity

//[ActivityThread.java]
    final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
    private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport, int seq) {
     
        //获取需要
        ActivityClientRecord r = mActivities.get(token);

        if (r != null) {
     

            if (userLeaving) {
     
                performUserLeavingActivity(r);
            }

            r.activity.mConfigChangeFlags |= configChanges;
            //执行Activity的onPause操作
            performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");//详见章节1.3.4

  
            if (r.isPreHoneycomb()) {
     
                QueuedWork.waitToFinish();
            }


            if (!dontReport) {
     
                try {
     
                	//通知AMS已经Pause成功了
                    ActivityManagerNative.getDefault().activityPaused(token);
                } catch (RemoteException ex) {
     
                    throw ex.rethrowFromSystemServer();
                }
            }
            mSomeActivitiesChanged = true;
        }
    }

4.4、ActivityThread.performPauseActivity

//[ActivityThread.java]
    final Bundle performPauseActivity(IBinder token, boolean finished,
            boolean saveState, String reason) {
     
        ActivityClientRecord r = mActivities.get(token);
        return r != null ? performPauseActivity(r, finished, saveState, reason) : null;
    }

    final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState, String reason) {
     
		
		...
        performPauseActivityIfNeeded(r, reason);

		...

        return !r.activity.mFinished && saveState ? r.state : null;
    }

    private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
     
        if (r.paused) {
     
            return;
        }

        try {
     
            r.activity.mCalled = false;
            mInstrumentation.callActivityOnPause(r.activity);
            EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
                    r.activity.getComponentName().getClassName(), reason);
            if (!r.activity.mCalled) {
     
				...
            }
        } catch (SuperNotCalledException e) {
     
            throw e;
        } catch (Exception e) {
     
			...
        }
        r.paused = true;
    }

4.5、Instrumentation.callActivityOnPause

//[Instrumentation.java]
    public void callActivityOnPause(Activity activity) {
     
        activity.performPause();
    }

4.6、Activity.performPause

//[Activity.java]
    final void performPause() {
     
        mDoReportFullyDrawn = false;
        mFragments.dispatchPause();
        mCalled = false;
        onPause();//执行Activity的onPause方法
        mResumed = false;
        if (!mCalled && getApplicationInfo().targetSdkVersion
                >= android.os.Build.VERSION_CODES.GINGERBREAD) {
     
            throw new SuperNotCalledException(
                    "Activity " + mComponent.toShortString() +
                    " did not call through to super.onPause()");
        }
        mResumed = false;
    }

目标Activity所属Stack栈存在Resume状态的Activity时会执行其onPause方法,否则执行的就是其它Stack栈中的了。

5、AMS.activityPaused(system_server进程)

4.2 中可以看出,执行完 4.3 的ActivityThread.performPauseActivity之后,会执行 ActivityManagerNative.getDefault().activityPaused(token); 用来通知AMS已经Pause成功了。

5.1 AMS.activityPaused

//[AMS.java]
    public final void activityPaused(IBinder token) {
     
        final long origId = Binder.clearCallingIdentity();
        synchronized(this) {
     
        	//获取已经pause的Activity所属Stack
            ActivityStack stack = ActivityRecord.getStackLocked(token);
            if (stack != null) {
     
                stack.activityPausedLocked(token, false);  //-->进入
            }
        }
        Binder.restoreCallingIdentity(origId);
    }

5.2 ActivityStack.activityPausedLocked + ActivityStack.completePauseLocked

//[ActivityStack.java]   
 final void activityPausedLocked(IBinder token, boolean timeout) {
     
        final ActivityRecord r = isInStackLocked(token);
        if (r != null) {
     
            mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
            if (mPausingActivity == r) {
     
               completePauseLocked(true, null);//此处传入的参数为true
                return;
            } else {
     
					...
            }
        }
        mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
    }

    private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
     
        ActivityRecord prev = mPausingActivity;
		...
		  if (resumeNext) {
     
            final ActivityStack topStack = mStackSupervisor.getFocusedStack();
            if (!mService.isSleepingOrShuttingDownLocked()) {
     //会进入此分支
                  final ActivityStack topStack = mStackSupervisor.getFocusedStack();
                //此时的prev为前台显示已经pause的Activity
                mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
            } else {
     
                mStackSupervisor.checkReadyForSleepLocked();
                ActivityRecord top = topStack.topRunningActivityLocked();
                if (top == null || (prev != null && top != prev)) {
     
                    mStackSupervisor.resumeFocusedStackTopActivityLocked();
                }
            }
        }
    	...
    }

再次进入 “3.2、ActivityStack.resumeFocusedStackTopActivityLocked”

5.3 ActivityStackSupervisor.startSpecificActivityLocked

创建目标Activity进程:

  • AMS请求Zygote创建目标Activity所属进程
  • Zygote孵化目标Activity所属进程
  • 初始化目标Activity所属进程
  • 注册目标Activity所属进程到system_server
  • 目标Activity所属进程创建Application实例对象
//[ActivityStackSupervisor.java]
    final ActivityManagerService mService;
    void startSpecificActivityLocked(ActivityRecord r, //目标Activity相关信息
            						 boolean andResume, //此时传递的参数值为true
            						 boolean checkConfig) //此时传递的参数值为false
   {
     
        //检查目标Activity所属的应用进程是否创建,假如是冷启动的情况当然是木有创建的
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.task.stack.setLaunchTime(r);
		
		/*
			当目标Activity对应的App进程和进程对应的ApplicationThread被创建时,进入此分支,此时的我们是木有机会了
		*/
        if (app != null && app.thread != null) {
     //
            try {
     
            	/*
            		判断此Activity是否携带FLAG_MULTIPROCESS或者其对应的进程名是"android"
            	    那"android"对应的进程到底是啥呢,其实它是system_server,这个是在zygote孵化它时指定的
            	*/
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
     
                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
                //正式启动目标Activity,开启生命周期
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
     
				...
            }

        }
		//调用AMS开启startProcess处理流程
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);//详见章节2.2
    }

5.4 AMS.startProcessLocked

final ProcessRecord startProcessLocked(String processName, //目标Activity对应的进程名,通常是包名
            ApplicationInfo info, //Activity所属APP的application信息
            boolean knownToBeDead, //true
            int intentFlags,  //0
            String hostingType, //"activity"
            ComponentName hostingName, //启动目标Activity时解析Intent时得到的ComponentName
            boolean allowWhileBooting,  //false
            boolean isolated,  //false 该进程是否是以隔离模式启动
            boolean keepIfLarge //true) {
     
        return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
                hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
                null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
                null /* crashHandler */);
    }

5.5 AMS.startProcessLocked

//[ActivityManagerService.java]
	//这个参数够多的,真是够多的
    final ProcessRecord startProcessLocked(String processName, //目标Activity对应的进程名,通常上是包名
    									   ApplicationInfo info,//Activity所属App的Application信息
            							   boolean knownToBeDead, //这个参数具体意义不明,传递过来的值为true
            							   int intentFlags, //参数的值为0
            							   String hostingType, //这个参数意义不明,参数值为"activity"
            							   ComponentName hostingName,//启动目标Activity时解析intent时得到的
            							   boolean allowWhileBooting, //是否允许在开启启动时,参数未false
            							   boolean isolated, //参数为false,这个值的意思是该进程是否是隔离的
            							   int isolatedUid, //指定隔离进程的UID
            							   boolean keepIfLarge,//参数意义不明,传递的值为true
            							   String abiOverride, //是否覆盖目标Activity所属app安装时的abi,abi通常影响so库的选择,取值为null
            							   String entryPoint, //参数意义不明,取值为null
            							   String[] entryPointArgs, //参数意义不明,取值为null
            							   Runnable crashHandler) //参数意义不明,取值为null
    {
     
        ...
        ProcessRecord app;
        if (!isolated) {
     //当不是隔离进程时
        	/*
	        	获取AMS中是否存在目标Activity所属进进程的ProcessRecord记录,在非isolated模式下AMS可以重用先前的ProcessRecord记录
	        	这里小伙们肯定有个疑问就是为啥startSpecificActivityLocked中检查了一次,这里又检查一次,
	        	而和startSpecificActivityLocked处理不同的是这里并没有因为ProcessRecord的存在而停止后续的脚步呢
	        	好吗,此处的逻辑感觉有点不是很清晰啊
        	*/
            app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
			// 启动参数中,带有FLAG_FROM_BACKGROUND标志,表示进程需要后台启动
            if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
     
            	// 后台启动一个BadProcess,直接退出
                if (mAppErrors.isBadProcessLocked(info)) {
     
                    return null;
                }
            } else {
     
                //清理进程Crash消息
                mAppErrors.resetProcessCrashTimeLocked(info);
                if (mAppErrors.isBadProcessLocked(info)) {
     
                	// 前台启动,则需要将宿主进程从坏的进程中剔除
                    mAppErrors.clearBadProcessLocked(info);
                    if (app != null) {
     
                        app.bad = false;
                    }
                }
            }
        } else {
     
            app = null;
        }
		
		/*
			此处涉及到了超自然现象,看注释的意思是对于大小核的架构的设备的话,此时使用cpuset将前台任务迁移到大核上
			这个已经超过本人的能力范畴之外了,pass
		*/
		nativeMigrateToBoost();
        mIsBoosted = true;
		...
		
		// 当进程已经被分配了PID时
        if (app != null && app.pid > 0) {
     
        	// 进程还处于启动的过程中
            if ((!knownToBeDead && !app.killed) || app.thread == null) {
     
                app.addPackage(info.packageName, info.versionCode, mProcessStats);
                return app;
            }

			/*
				这个地方要怎么理解呢,可能前面目标Activity所属App进程被创建过
				但是已经over了再启动时需要对其做一些清理工作
			*/
            killProcessGroup(app.uid, app.pid);
            handleAppDiedLocked(app, true, true);
        }

        String hostingNameStr = hostingName != null
                ? hostingName.flattenToShortString() : null;

        if (app == null) {
     
        	//在AMS中创建ProcessRecord信息记录
            app = newProcessRecordLocked(info, processName, isolated, isolatedUid);//-->1 进入这里
            if (app == null) {
     
                return null;
            }
            //设置crashHandler
            app.crashHandler = crashHandler;
        } else {
     
            app.addPackage(info.packageName, info.versionCode, mProcessStats);
        }

		// 如果系统还未启动,则需要将待启动进程先保持住,等系统启动后,再来启动这些进程
		//final ArrayList mProcessesOnHold = new ArrayList();
        if (!mProcessesReady
                && !isAllowedWhileBooting(info)
                && !allowWhileBooting) {
     
            if (!mProcessesOnHold.contains(app)) {
     
                mProcessesOnHold.add(app);
            }
            return app;
        }

        //又调用另外一个重载的startProcessLocked
        startProcessLocked(
                app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);//2 -->进入这里
        
        return (app.pid != 0) ? app : null;
    }
  • 首先判断是否是以isolated模式启动的目标Activity所属App进程,那么这个isolated模式是什么意思呢,网上说通过isolated来判断要启动的进程是否是隔离的,当为true时意味着这是一个隔离的进程(虽然这么说,但是本人是没有搞明白,这个隔离到底隔离的是啥,如果对此处有比较深入的小伙们可以告诉我)。

    对于隔离的进程而言,每次启动都是独立的,不能复用已有的进程信息。如果要启动一个非隔离的进程,那么就需要区分进程是在前台启动还是后台启动,这是用户体验相关的设计。在AMS中维护了一个badProcesses的结构体,用于保存一些“坏进程”,什么才是“坏进程”呢?如果一个进程在一分钟内连续崩溃两次,那就变成了一个“坏进程”。对于后台启动的进程而言(即启动参数中带有FLAG_FROM_BACKGROUND标识),如果进程崩溃了,会造成用户使用的困惑,因为进程崩溃时,会弹出一个对话框,而后台启动的进程是没有任何操作界面的,这时候弹一个框,用户会觉得自己什么都没干,却弹出了一个对话框。所以,后台启动一个“坏进程”时,会直接退出。

    当进程是在前台启动时,即便是一个"坏进程",那也应该宽恕这个进程以前的不良记录,因为这通常是用户通过界面主动要唤起的进程。本着用户是上帝的原则,还是得让用户达到启动进程的目的,即便这个进程可能再次崩溃。

  • 接着判断目标Activity所对应的ProcessRecord是否创建,如果还没有创建这时候会调用AMS.newProcessRecord来创建一个新的ProcessRecord

  • 接着调用AMS的另一个重载方法startProcessLocked继续目标Activity对应进程创建的处理流程

Android四大组件之Activity(四)—— 启动模式(launchMode) + Pause上一个Activity_第2张图片 Android四大组件之Activity(四)—— 启动模式(launchMode) + Pause上一个Activity_第3张图片 Android四大组件之Activity(四)—— 启动模式(launchMode) + Pause上一个Activity_第4张图片

下一章见!这篇太长了!

你可能感兴趣的:(android开发,java,android,java,移动开发)