AMS分析--基于深入理解android(2)

final int startActivityUncheckedLocked(ActivityRecord r,
            ActivityRecord sourceRecord, int startFlags, boolean doResume,
            Bundle options) {
        final Intent intent = r.intent;
        final int callingUid = r.launchedFromUid;

        int launchFlags = intent.getFlags();

        /// M: AMS log enhancement @{
        if (!ActivityManagerService.IS_USER_BUILD)
            Slog.i(TAG, "ACT-launchFlags(original): 0x" + Integer.toHexString(launchFlags) + ", launchMode:" + r.launchMode
                + ", startFlags: " + startFlags + ", doResume:" + doResume);
        /// @}

        // We'll invoke onUserLeaving before onPause only if the launching
        // activity did not explicitly state that this is an automated launch.
        mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;//加上FLAG_ACTIVITY_NO_USER_ACTION这个标志,系统就不会调用onUserLeaveHint
        //比如用户主动切换任务,短按home进入桌面等会调用onUserLeaveHint,系统自动切花activity不会调用此方法,如来电,灭屏等

//当用户按Home键等操作使程序进入后台时 就会根据mUserLeaving=true,
//调用onUserLeaveHint(),
//onUserLeaveHint
//这个回调函数主要用来监听按Home键退出到桌面的动作,发生在onPause之前。在启动一个新的Activity时,
//ActivityStackSupervisor里会调用startActivityUncheckedLocked,在它里面会给mUserLeaving赋值。
//mUserLeaving用于指示当前activity退到后台时函数onUserLeaving是否被调用。
//可见,只有当设置了FLAG_ACTIVITY_NO_USER_ACTION标志时mUserLeaving才会为false,
//其他情况下mUserLeaving均为true,也就是onUserLeaveHint会被调用,注释里也说了onUserLeaveHint会在onPause之前被调用。

//例子可以查看 http://www.2cto.com/kf/201503/380568.html

android onUserLeaveHint和onUserInteraction

onUserLeaveHint 当用户的操作使一个activity准备进入后台时,此 方法会像activity的生命周期的一部分被调用。例如,当用户按下 Home键,
Activity#onUserLeaveHint()将会被回调。但是当来电导致来电activity自动占据前台,Activity#onUserLeaveHint()将不会被回调。

onUserLeaveHint() 用户手动离开当前activity,会调用该方法,比如用户主动切换任务,短按home进入桌面等。系统自动切换activity不会调用此方法,如来电,灭屏等。

onUserInteraction() activity在分发各种事件的时候会调用该方法,注意:启动另一个activity,Activity#onUserInteraction()会被调用两次,一次是activity捕获到事件,另一次是调用Activity#onUserLeaveHint()之前会调用Activity#onUserInteraction()。

  if (!doResume) {
            r.delayedResume = true;//还没有恢复的app  switch
        }
            //启动Activity时默认不会设置FLAG_ACTIVITY_PREVIOUS_IS_TOP 
    //故此notTop默认情况下会是null
        ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
       if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
            //ActivityRecord checkedCaller优先等于sourceRecord,其次选择正在运行的Activity
            //如果调用者和被启动的对象是同一个,不不需要重复启动 所以START_FLAG_ONLY_IF_NEEDED 可以置位空
            ActivityRecord checkedCaller = sourceRecord;
            if (checkedCaller == null) {
                checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
            }
            if (!checkedCaller.realActivity.equals(r.realActivity)) {
                // Caller is not the same as launcher, so always needed.//调用者和启动这不一致,所以是启动必须的,置位意思非必须的
                startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
            }
        }
   //根据sourceRecord的情况进行对应处理,能理解下面这段if/else的判断语句吗
   if(sourceRecord == null) {
      //如果请求的发起者为空,则当然需要新建一个Task
      if((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0)
         launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
   }else if (sourceRecord.launchMode ==ActivityInfo.LAUNCH_SINGLE_INSTANCE){
      //如果sourceRecord单独占一个Instance,则新的Activity必然处于另一个Task中
     launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
   } else if(r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
               || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
      //如果启动模式设置了singleTask或singleInstance,则也要创建新Task
      launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
   }//if(sourceRecord== null)判断结束
  ActivityInfo newTaskInfo = null;
        Intent newTaskIntent = null;
        final ActivityStack sourceStack;
        if (sourceRecord != null) {
            if (sourceRecord.finishing) {

                //如果sourceRecord已经处于finishing状态,那么他所在的Task就很有可能已经为空或者即将为空。
                //我们就不能盲目throw it in to that task。
                if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
                    Slog.w(TAG, "startActivity called from finishing " + sourceRecord
                            + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
                    newTaskInfo = sourceRecord.info;
                    newTaskIntent = sourceRecord.task.intent;
                }
                sourceRecord = null;
                sourceStack = null;
            } else {
                sourceStack = sourceRecord.task.stack;
            }
        } else {
            sourceStack = null;
        }
        if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
            //如果启动的activity需要新的task,那么新启动的activity将会与其caller断开依赖关系
            //,这个关系主要是指result反馈,A-->B,如果A是通过startActivityForResult()请求启动的,并且requestCode >=0,那么如果B是在新的task中
            //,那么B在finish的时候将不再向A反馈result,而是在启动过程中就会向A反馈一个RESULT_CANCELED。

            Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
            r.resultTo.task.stack.sendActivityResultLocked(-1,
                    r.resultTo, r.resultWho, r.requestCode,
                Activity.RESULT_CANCELED, null);
            r.resultTo = null;
        }//禁止两个task之间通信,发送取消发送结果消息给调用者
  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,所以r.resultTo 必须被以上函数设置为null

                ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
                        ? findTaskLocked(r)//从所有Stack中的所有Task中的Activity中查找看能否找到要启动的Activity,根据要启动的Activity启动模式是否是SingleInstance所采用的搜索方法是不一样的。  
                        : findActivityLocked(intent, r.info);
                if (intentActivity != null) {
                    if (r.task == null) {
                        r.task = intentActivity.task;
                    }
                    targetStack = intentActivity.task.stack;
                    targetStack.mLastPausedActivity = null;
                    if (DEBUG_TASKS) Slog.d(TAG, "Bring to front target: " + targetStack
                            + " from " + intentActivity);
                    moveHomeStack(targetStack.isHomeStack());//rus启动桌面
                    if (intentActivity.task.intent == null) {

                        intentActivity.task.setIntent(intent, r.info);

以下3种条件需要检查是否有有task可复用

⑴ (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

第⑴是一个组合条件,Intent.FLAG_ACTIVITY_MULTIPLE_TASK不能单独使用,它是和Intent.FLAG_ACTIVITY_NEW_TASK结合起来使用的,如果设置了Intent.FLAG_ACTIVITY_MULTIPLE_TASK,那么将会永远启动一个新的task,不管是否有可复用的task。

为什么是这3种条件,从android的开发文档中,我们可知LAUNCH_SINGLE_TASK和LAUNCH_SINGLE_INSTANCE两种launch mode的activity只允许作为task的root activity,既然是作为root activity,那么它所处的task的affinity必然是和它的是一样的,因此从mHistory中找打一个和自己的affinity相同的task是非常有必要的。

而对于设置了Intent.FLAG_ACTIVITY_NEW_TASK的Intent来说,并且没有设置Intent.FLAG_ACTIVITY_MULTIPLE_TASK,那么同样的,它也必须是作为它所处的task的root activity。道理是一样的。

AMS去mHistory中查找可复用的task,查找这个task的规则如下:    

⑴ launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE的情况,遵循如下规则: @findTaskLocked()

    ① 查找mHistory中是否有与要启动的activity相同affinity的task,上面也提过这几类activity启动时,均是作为task的root activity,并且其task的affinity必须和自己的affinity相同,因此首先需要去mHistory查找和自己affinity相同的task。

    ② 如果activity没有affinity,即属性android:taskAffinity设置为“”,空字符串时。此时AMS就会去mHistory中去查找是否有task的root activity和启动的activity相同,通过比较task.intent.getComponent()和启动activity的Comeponent比较,为什么是root activity,前面分析过了;

    ③ 如果task.Intent为空,这种情况发生在TaskReparenting之后,TaskReparenting之后,AMS为这个activity创建一个新的task,并将启动这个activity的Intent赋值给task.affinityIntent,并且此时的task.Intent==null。此时就需要比较task.affinityIntent.getComponent()和启动activity的Comeponent比较,看是否和启动的activity相同。

以上3个规则中,均是返回找的task中最上面的activity,而不一定是task的activity,至于如何处理要启动的activity和task中已有的activity,后面会介绍。

⑵ launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE的情况,遵循如下规则: @findActivityLocked()

对于ActivityInfo.LAUNCH_SINGLE_INSTANCE启动模式来说,它所处的task中只允许有它一个activity,因此它的规则只符合上面规则中的②;

对于第①条,由于设置了ActivityInfo.LAUNCH_SINGLE_INSTANCE启动模式的activity,它只能自己独处一个task,不可能和别人共享同一个task,因此mHistory即使存在了与该activity有相同的affinity的activity,如果这个activity和启动的activity不同,那么ActivityInfo.LAUNCH_SINGLE_INSTANCE启动模式的activity也不可能和它共用一个task,因此这第①条完全可以不用检查。

对于第②条,由于该模式的activity独处一个task,因此完全没有可能所处的task的affinity和自己的affinity不同,因此,假如mHistory存在相同的activity与启动的activity相同,那么这个activity的affinity必然和自己的相同。所以对于这种模式,第②条囊括了其他模式的①②两条。

对于第③条,同样的道理,ActivityInfo.LAUNCH_SINGLE_INSTANCE启动模式的activity不可能处在与自己不同affinity的task中,因此不可能出现TaskReparenting操作,所以这条也不需要。

+++++++++++++++++

什么是Affinity

       在某些情况下,Android需要知道一个Activity属于哪个Task,即使它没有被启动到一个具体的Task里。这是通过任务共用性(Affinities)完成的。任务共用性(Affinities)为这个运行一个或多个Activity的Task提供了一个独特的静态名称,默认的一个活动的任务共用性(Affinity)是实现了该Activity的.apk包的名字。

       当开始一个没有Intent.FLAG_ACTIVITY_NEW_TASK标志的Activity时,任务共用性affinities不会影响将会运行该新活动的Task:它总是运行在启动它的Task里。但是,如果使用了NEW_TASK标志,那么共用性(affinity)将被用来判断是否已经存在一个有相同共用性(affinity)的Task。如果是这样,这项Task将被切换到前面而新的Activity会启动于这个Task的顶层。

       这种特性在您必须使用NEW_TASK标志的情况下最有用,尤其是从状态栏通知或桌面快捷方式启动活动时。结果是,当用户用这种方式启动您的应用程序时,它的当前Task将被切换到前台,而且想要查看的Activity被放在最上面。

       你可以在程序清单(Manifest)文件的应用程序application标签中为.apk包中所有的活动分配你自己的任务共用性Affinites,或者在活动标记中为各个活动进行分配。

       一些说明其如何使用的例子如下:


如果您的.apk包含多个用户可以启动的高层应用程序,那么您可能需要对用户看到的每个Activity(活动)指定不同的affinities。一个不错的命名惯例是以附加一个以冒号分隔的字符串来扩展您的.apk包名。例如,“ com.android.contacts ”.apk可以有affinities:“com.android.contacts:Dialer”和“ com.android.contacts:ContactsList”。
如果您正在替换一个通知,快捷方式,或其他可以从外部发起的应用程序的“内部”活动,你可能需要明确设定您替代活动的taskAffinity和您准备替代的应用程序一样。例如,如果您想替换contacts详细信息视图(用户可以创建并调用快捷方式),你得把taskAffinity设置成“com.android.contacts”。

        跟 Task 有关的 manifest文件中Activity的特性值介绍

        android:allowTaskReparenting 
        用来标记Activity能否从启动的Task移动到有着affinity的Task(当这个Task进入到前台时)
       “true”,表示能移动,“false”,表示它必须呆在启动时呆在的那个Task里。

       如果这个特性没有被设定,设定到<application>元素上的allowTaskReparenting特性的值会应用到Activity上。默认值为“false”。
       一般来说,当Activity启动后,它就与启动它的Task关联,并且在那里耗尽它的整个生命周期。当当前的Task不再显示时,你可以使用这个特性来强制Activity移动到有着affinity的Task中。典型用法是:把一个应用程序的Activity移到另一个应用程序的主Task中。 
       例如,如果 email中包含一个web页的链接,点击它就会启动一个Activity来显示这个页面。这个Activity是由Browser应用程序定义的,但是,现在它作为email Task的一部分。如果它重新宿主到Browser Task里,当Browser下一次进入到前台时,它就能被看见,并且,当email Task再次进入前台时,就看不到它了。 
       Actvity的affinity是由taskAffinity特性定义的。Task的affinity是通过读取根Activity的affinity决定。因此,根Activity总是位于相同affinity的Task里。由于启动模式为“singleTask”和“singleInstance”的Activity只能位于Task的底部,因此,重新宿主只能限于“standard”和“singleTop”模式。

       android:alwaysRetainTaskState

       用来标记Activity所在的Task的状态是否总是由系统来保持。
      “true”,表示总是;“false”,表示在某种情形下允许系统恢复Task到它的初始化状态。默认值是“false”。
       这个特性只针对Task的根Activity有意义;对其它Activity来说,忽略之。 
       一般来说,特定的情形如当用户从主画面重新选择这个Task时,系统会对这个Task进行清理(从stack中删除位于根Activity之上的所有Activivity)。典型的情况,当用户有一段时间没有访问这个Task时也会这么做,例如30分钟。 
       然而,当这个特性设为“true”时,用户总是能回到这个Task的最新状态,无论他们是如何启动的。这非常有用,例如,像Browser应用程序,这里有很多的状态(例如多个打开的Tab),用户不想丢失这些状态。

       android:clearTaskOnLaunch

       用来标记是否从Task中清除所有的Activity,除了根Activity外(每当从主画面重新启动时)
      “true”,表示总是清除至它的根Activity,“false”表示不。默认值是“false”。
        这个特性只对启动一个新的Task的Activity(根Activity)有意义;对Task中其它的Activity忽略。 
        当这个值为“true”,每次用户重新启动这个Task时,都会进入到它的根Activity中,不管这个Task最后在做些什么,也不管用户是使用BACK还是HOME离开的。当这个值为“false”时,可能会在一些情形下(参考alwaysRetainTaskState特性)清除Task的Activity,但不总是。

       假设,某人从主画面启动了Activity P,并从那里迁移至Activity Q。接下来用户按下HOME,然后返回Activity P。一般,用户可能见到的是Activity Q,因为它是P的Task中最后工作的内容。然而,如果P设定这个特性为“true”,当用户按下HOME并使这个Task再次进入前台时,其上的所有的Activity(在这里是Q)都将被清除。因此,当返回到这个Task时,用户只能看到P。

       如果这个特性和allowTaskReparenting都设定为“true”,那些能重新宿主的Activity会移动到共享affinity的Task中;剩下的Activity都将被抛弃,如上所述。 

       android:finishOnTaskLaunch 

       用来标记当用户再次启动它的Task(在主画面选择这个Task)时已经存在的Activity实例是否要关闭(结束)
     “true”,表示应该关闭,“false”表示不关闭。默认值是“false”。 
       如果这个特性和allowTaskReparenting都设定为“true”,这个特性胜出。Activity的affinity忽略。这个Activity不会重新宿主,但是会销毁。 


 跟 Task 有关的 Intent对象中设置的Flag

       FLAG_ACTIVITY_BROUGHT_TO_FRONT 

       这个标志一般不是由程序代码设置的,如在launchMode中设置singleTask模式时系统帮你设定。 

       FLAG_ACTIVITY_CLEAR_TOP 

       如果设置,并且这个Activity已经在当前的Task中运行,因此,不再是重新启动一个这个Activity的实例,而是在这个Activity上方的所有Activity都将关闭,然后这个Intent会作为一个新的Intent投递到老的Activity(现在位于顶端)中。 
       例如,假设一个Task中包含这些Activity:A,B,C,D。如果D调用了startActivity(),并且包含一个指向Activity B的Intent,那么,C和D都将结束,然后B接收到这个Intent,因此,目前stack的状况是:A,B。 
       上例中正在运行的Activity B既可以在onNewIntent()中接收到这个新的Intent,也可以把自己关闭然后重新启动来接收这个Intent。如果它的启动模式声明为“multiple”(默认值),并且你没有在这个Intent中设置FLAG_ACTIVITY_SINGLE_TOP标志,那么它将关闭然后重新创建;对于其它的启动模式,或者在这个Intent中设置FLAG_ACTIVITY_SINGLE_TOP标志,都将把这个Intent投递到当前这个实例的onNewIntent()中。 
       这个启动模式还可以与FLAG_ACTIVITY_NEW_TASK结合起来使用:用于启动一个Task中的根Activity,它会把那个Task中任何运行的实例带入前台,然后清除它直到根Activity。这非常有用,例如,当从Notification Manager处启动一个Activity。

       FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET

       如果设置,这将在Task的Activity stack中设置一个还原点,当Task恢复时,需要清理Activity。也就是说,下一次Task带着FLAG_ACTIVITY_RESET_TASK_IF_NEEDED标记进入前台时(典型的操作是用户在主画面重启它),这个Activity和它之上的都将关闭,以至于用户不能再返回到它们,但是可以回到之前的Activity。 
       这在你的程序有分割点的时候很有用。例如,一个e-mail应用程序可能有一个操作是查看一个附件,需要启动图片浏览Activity来显示。这个Activity应该作为e-mail应用程序Task的一部分,因为这是用户在这个Task中触发的操作。然而,当用户离开这个Task,然后从主画面选择e-mail app,我们可能希望回到查看的会话中,但不是查看图片附件,因为这让人困惑。通过在启动图片浏览时设定这个标志,浏览及其它启动的Activity在下次用户返回到mail程序时都将全部清除。

       FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

       如果设置,新的Activity不会在最近启动的Activity的列表中保存。

       FLAG_ACTIVITY_FORWARD_RESULT

       如果设置,并且这个Intent用于从一个存在的Activity启动一个新的Activity,那么,这个作为答复目标的Activity将会传到这个新的Activity中。这种方式下,新的Activity可以调用setResult(int),并且这个结果值将发送给那个作为答复目标的Activity。

       FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY

       这个标志一般不由应用程序代码设置,如果这个Activity是从历史记录里启动的(常按HOME键),那么,系统会帮你设定。

       FLAG_ACTIVITY_MULTIPLE_TASK

       不要使用这个标志,除非你自己实现了应用程序启动器。与FLAG_ACTIVITY_NEW_TASK结合起来使用,可以禁用把已存的Task送入前台的行为。当设置时,新的Task总是会启动来处理Intent,而不管这是是否已经有一个Task可以处理相同的事情。 
       由于默认的系统不包含图形Task管理功能,因此,你不应该使用这个标志,除非你提供给用户一种方式可以返回到已经启动的Task。 
       如果FLAG_ACTIVITY_NEW_TASK标志没有设置,这个标志被忽略。

       FLAG_ACTIVITY_NEW_TASK

       如果设置,这个Activity会成为历史stack中一个新Task的开始。一个Task(从启动它的Activity到下一个Task中的Activity)定义了用户可以迁移的Activity原子组。Task可以移动到前台和后台;在某个特定Task中的所有Activity总是保持相同的次序。 
       这个标志一般用于呈现“启动”类型的行为:它们提供用户一系列可以单独完成的事情,与启动它们的Activity完全无关。 
       使用这个标志,如果正在启动的Activity的Task已经在运行的话,那么,新的Activity将不会启动;代替的,当前Task会简单的移入前台。参考FLAG_ACTIVITY_MULTIPLE_TASK标志,可以禁用这一行为。 
       这个标志不能用于调用方对已经启动的Activity请求结果。

        FLAG_ACTIVITY_NO_ANIMATION

        如果在Intent中设置,并传递给Context.startActivity()的话,这个标志将阻止系统进入下一个Activity时应用Acitivity迁移动画。这并不意味着动画将永不运行——如果另一个Activity在启动显示之前,没有指定这个标志,那么,动画将被应用。这个标志可以很好的用于执行一连串的操作,而动画被看作是更高一级的事件的驱动。

       FLAG_ACTIVITY_NO_HISTORY

       如果设置,新的Activity将不再历史stack中保留。用户一离开它,这个Activity就关闭了。这也可以通过设置noHistory特性。

       FLAG_ACTIVITY_NO_USER_ACTION 

       如果设置,作为新启动的Activity进入前台时,这个标志将在Activity暂停之前阻止从最前方的Activity回调的onUserLeaveHint()。 
       典型的,一个Activity可以依赖这个回调指明显式的用户动作引起的Activity移出后台。这个回调在Activity的生命周期中标记一个合适的点,并关闭一些Notification。 
       如果一个Activity通过非用户驱动的事件,如来电或闹钟,启动的,这个标志也应该传递给Context.startActivity,保证暂停的Activity不认为用户已经知晓其Notification。 

        FLAG_ACTIVITY_REORDER_TO_FRONT

       如果在Intent中设置,并传递给Context.startActivity(),这个标志将引发已经运行的Activity移动到历史stack的顶端。 
       例如,假设一个Task由四个Activity组成:A,B,C,D。如果D调用startActivity()来启动Activity B,那么,B会移动到历史stack的顶端,现在的次序变成A,C,D,B。如果FLAG_ACTIVITY_CLEAR_TOP标志也设置的话,那么这个标志将被忽略。 

       FLAG_ACTIVITY_SINGLE_TOP

       如果设置,当这个Activity位于历史stack的顶端运行时,不再启动一个新的。

+++++++++++++++++++

        // if the caller is not itself in the front.
                    final ActivityStack lastStack = getLastStack();
                    ActivityRecord curTop = lastStack == null?
                            null : lastStack.topRunningNonDelayedActivityLocked(notTop);//检测当前在堆栈顶端的Activity是否就是即将要启动的Activity
                    /* 这段代码的逻辑是看一下,当前在堆栈顶端的Activity是否就是即将要启动的Activity,有些情况下,如果即将要启动的Activity就在堆栈的顶端,*/
                    /*那么,就不会重新启动这个Activity的别一个实例了,*/
                    /*现在处理堆栈顶端的Activity是Launcher,与我们即将要启动的MainActivity不是同一个Activity,因此,这里不用进一步处理上述介绍的情况*/
                    if (curTop != null && (curTop.task != intentActivity.task ||
                            curTop.task != lastStack.topTask())) {
   //当 notTop !=null ,此时有可能 curTop.task != lastStack.topTask                     r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);//因为系统中存在这个Activity,所以把它拿到前台。不新建
                        //可以参考这篇http://www.2cto.com/kf/201407/319948.html
                        if (sourceRecord == null || (sourceStack.topActivity() != null &&
                                sourceStack.topActivity().task == sourceRecord.task)) {
                            // We really do want to push this one into the
                            // user's face, right now.
                            movedHome = true;//movedHome表示是否移动home task
                            targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
                            //这一步,将已经存在的我们的目标Task终于被移动到了前台!参数intentActivity.task就是我们搜索出来的我们要启动
                            //的Activity所在的Task,r就是我们要启动的ActivityRecord。
                            if ((launchFlags &
                                    (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
                                    == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
                                // Caller wants to appear on home activity.
                                intentActivity.task.mOnTopOfHome = true;//把当前新启动的任务置于Home任务之上,也就是按back键从这个任务返回的时候会回到home
                                //,即使这个不是他们最后看见的activity
                            }
                            options = null;
                            /// M: Fix ALPS01276300, at this case, avoid move home to top when resume top @{
                            intentActivity.task.mMovingToFront = true;
                            /// @}
                        }

Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP
检查Intent是否设置了Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP,这个标志我有点困惑,从它的注释可以看出它的含义是指如果设置了该flag,那么mHistory中最top的activity在后续的处理中将不被视为top,而将前一个activity视为top,如A–>B–>C,将B视为top。
这个top activity的作用很大,涉及到后面对task的处理。但是目前来看这个flag并没有起到该有的作用,代码中判断如果设置了该标志,那么AMS将会视当前正在启动的activity为top,然后去mHistory中去查找它的前一个activity为后续task处理的top activity(topRunningNonDelayedActivityLocked()中实现),但是现在的问题是此时此刻,正在启动的activity并不存在于mHistory中,因为我们在前一个函数中刚刚创建了这个ActivityRecord。如下面代码所示:
[java] view plaincopy
ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
!= 0 ? r : null;
因此,感觉这个flag的意义不是太大

      // If the caller has requested that the target task be
                    // reset, then do so.
                    if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
                        intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
                    }
                    if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
                        // We don't need to start a new activity, and
                        // the client said not to do anything if that
                        // is the case, so this is it!  And for paranoia, make
                        // sure we have correctly resumed the top activity.
                        if (doResume) {
                        //默认情况下startFlags不会设置START_FLAG_ONLY_IF_NEEDED,调用者和启动这不一致,所以是启动必须的,置位意思非必须的
                            resumeTopActivitiesLocked(targetStack, null, options);
                        } else {
                            ActivityOptions.abort(options);
                        }
                        /// M: Add debug task message @{
                        if (DEBUG_TASKS) {
                            Slog.i(TAG, "START_RETURN_INTENT_TO_CALLER, doResume = " + doResume);
                        }
                        /// @}
                        if (r.task == null)  Slog.v(TAG,
                                "startActivityUncheckedLocked: task left null",
                                new RuntimeException("here").fillInStackTrace());
                        return ActivityManager.START_RETURN_INTENT_TO_CALLER;
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED:如果设置该属性,并且这个activity在一个新的task中正在被启动或者被带到一个已经存在的task的顶部,这时这个activity将会被作为这个task的首个页面加载。这将会导致拥有这个应用的affinities的task处于一个合适的状态(移动activity到这个task或者activity从中移出),或者简单的重置这个task到它的初始状态

http://blog.csdn.net/windskier/article/details/7096521
Reset Task
如果Intent设置Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,最常见的情况,当从Home启动应用程序时,会设置这个flag;从recently task进入应用程序,则不会设置这个falg。
设置了FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,AMS会对复用的task作如下处理,下面称这个可复用的task为复用task:
⑴ mHistory中,对于复用task中的除root activity外的activity,有如下处理
在此之前,先介绍activity的几个关键属性:
① 如果复用task在后台时间超过30min,那么在这个过程中将删除除root activity之外的所有的activity;
② 如果新启动的activity设置了属性ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE,那么表明它并不要求后台20min的复用task删除activity;
③ 如果新启动的activity设置了属性ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH,那么表明不论复用task在后台是否超过30min,一律要求删除除root activity之外的所有的activity;
④ 复用task中的activity设置了属性ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH,那么复用task从home中再次被启动到前台时,这个activity会被删除;
⑤ 复用task中的activity设置了属性ActivityInfo.FLAG_ALLOW_TASK_REPARENTIN,并且这个activity的resultTo为空,那么也就是说这个activity和它的caller没有依赖关系,那么AMS认为这个activity暂时没有用处了,需要对其进行TaskReparenting操作,最好的方法是把它放到mHistory栈底,不影响其他task。
⑥ 复用task中的activity的Intent设置属性Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET,那么下次再从home中进入到task中,那么将删除设置了该属性的activity以上所有的activity,例如A–>B–>C–>D–>E,加入在C启动D时设置了该属性,那么下次从HOME中再次进入到这个task中时,将会是A–>B–>C。
⑦ 如果复用task中的activity的resultTo不为空,也就是启动这个activity的是一个activity,那么这个activity的处理将按照它的前一个activity的处理方式来处理,不管在何时情况下,它的前一个activity都是启动它的activity,即便resultTo不是前一个activity,如设置了Intent.FLAG_ACTIVITY_FORWARD_RESULT。如果复用task中每个activity的resultTo都不为空,并且上述处理优先级在其前面的属性没有设置的话,那么这个复用task中的activity将不作任何的处理。
一般情况下,activity的resultTo都不为空,除非设置了Intent.FLAG_ACTIVITY_FORWARD_RESULT,那么此时被启动的activity的caller的resultTo将会为空。
task中的activity的属性设置是上述属性的组合,因此reset task过程要按照一定的优先级来处理,上述属性的处理优先级是:⑥=④>⑦>⑤>③=②>①
具体操作顺序如下:
♣ 根据⑥,④条件来删除复用task中相应的activity;
♣ ⑦条件下,将会暂时不做处理,再根据它的前一个activity的属性来做处理,即使这个activity设置了allowTaskReparenting;
♣ 如果activity的resultTo为空,并且满足条件⑤,那么将其及其以上未作处理的,满足条件⑦的所有activity,一并进行TaskReparenting操作,并放置在mHistory栈底。它们在mHistory栈底顺序如同在复用task中的顺序;
♣ 根据①②③的条件来删除复用task中相应的activity。
⑵ mHistory中,不属于复用task的activity,并且它的resultTo不为空,那么将根据它的前一个activity的处理来处理;
⑶ mHistory中,不属于复用task,但是和当前启动的activity有相同affinity,并且允许TaskReparenting操作,那么将进行以下操作:
♣ 如果满足上述的①②③④的条件,但是其中的task不是复用task,而是这个activity所处的task,那么将输出这个activity,而不是进行TaskReparenting操作。
为什么非复用task中的activity,和当前启动的activity有相同affinity,并且允许TaskReparenting操作,满足了①②③④的条件之后要删除呢,为什么非复用task中的其他activity,不需要删除呢?
正因为它和启动的activity有相同的affinity,因此AMS认为这个activity是和启动activity相关的,以后可能会重新调用,所以当其满足删除条件后,这时它将不允许TaskReparenting操作,并且不应该再允许它存在于其他的task中,此时应该删除。
♣ 如果没有满足①②③④的条件,那么将会对其进行TaskReparenting操作,重新将其移动到复用task或新启动的task中。

         if ((launchFlags &
                            (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
                            == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
                        // The caller has requested to completely replace any
                        // existing task with its new activity.  Well that should
                        // not be too hard...
                        reuseTask = intentActivity.task;
                        reuseTask.performClearTaskLocked();//清空所有的Activity
                        reuseTask.setIntent(r.intent, r.info);
                    } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0  // 启动之后删除其他Activity
                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {                       
                        ActivityRecord top =
                                intentActivity.task.performClearTaskLocked(r, launchFlags);
                                // 这3种条件有一个共同点,就是启动的activity启动之后,在这个task中,这个activity之上不能有其他的activity
                        if (top != null) {
                            if (top.frontOfTask) {                    
                                top.task.setIntent(r.intent, r.info);
                            }
                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
                                    r, top.task);
                            /// M: AMS log enhancement @{
                            if(!ActivityManagerService.IS_USER_BUILD)
                               Slog.d(TAG, "ACT-AM_NEW_INTENT " + r + top.task);
                            /// @}
                            top.deliverNewIntentLocked(callingUid, r.intent);
                        } else {

                            addingToTask = true;

                            sourceRecord = intentActivity;

                        }
                    }
  //此时条件加上FLAG_ACTIVITY_NEW_TASK,且正要启动的Activity为root Activity,并且是在栈顶显示的
                        if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
                                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
                                && intentActivity.realActivity.equals(r.realActivity)) {
                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
                                    intentActivity.task);
                            if (intentActivity.frontOfTask) {
                                intentActivity.task.setIntent(r.intent, r.info);
                            }
                            /// M: AMS log enhancement @{
                            if (!ActivityManagerService.IS_USER_BUILD)
                                Slog.d(TAG, "ACT-AM_NEW_INTENT " + r + intentActivity.task);
                            /// @}
                            intentActivity.deliverNewIntentLocked(callingUid, r.intent);
                            //判断要启动的Activity的包名是否为空,如果不为空的话,那么得到mHistory最顶部的ActivityRecord
                            //,接着判断当前顶部的Activity与要启动的Activity是否相同,并且Activity的进程以及ApplicationThread不为空
                            //,接着如果判断launchFlags为FLAG_ACTIVITY_SINGLE_TOP或者LaunchMode为SINGLE_TOP或者SINGLE_TASK的话,那么就调用resumeTopActivityLocked
                                //,并且调用top.deliverNewIntentLocked回调Activity的onNewIntent。否则如果包名为空,那么返回CLASS_NOT_FOUND结果。
                        } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
                            // In this case we are launching the root activity
                            // of the task, but with a different intent.  We
                            // should start a new instance on top.
                            //我们要打开的app的初始界面不等于我们r.intent。即我们要新建r.intent的activity
                            addingToTask = true;
                            sourceRecord = intentActivity;

                            /// M: Add debug task message @{
                            if (DEBUG_TASKS) {
                                Slog.i(TAG, "since different intents, start new activity...");
                            }
                            /// @}
                        }
 else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
                        // In this case an activity is being launched in to an
                        // existing task, without resetting that task.  This
                        // is typically the situation of launching an activity
                        // from a notification or shortcut.  We want to place
                        // the new activity on top of the current task.
                        addingToTask = true;
                        //addingToTask 如果为true表示正在添加至某个task
                        sourceRecord = intentActivity;
                        //在这种情况下只是把这个activity 移动到task顶部。并不重置这个task

                        /// M: Add debug task message @{
                        if (DEBUG_TASKS) {
                            Slog.i(TAG, "place the new activity on top of the current task...");
                        }
                        /// @}
                    } else if (!intentActivity.task.rootWasReset) {
                        // In this case we are launching in to an existing task
                        // that has not yet been started from its front door.
                        // The current task has been brought to the front.
                        // Ideally, we'd probably like to place this new task
                        // at the bottom of its stack, but that's a little hard
                        // to do with the current organization of the code so
                        // for now we'll just drop it.
                        intentActivity.task.setIntent(r.intent, r.info);
                    }

FLAG_ACTIVITY_RESET_TASK_IF_NEEDED:
   一般与FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET结合使用,如果设置该属性,这个activity将在一个新的task中启动或者或者被带到一个已经存在的task的顶部,这时这个activity将会作为这个task的首个页面加载。将会导致与这个应用具有相同亲和力的task处于一个合适的状态(移动activity到这个task或者从中移出),或者简单的重置这个task到它的初始状态
   FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET:在当前的Task堆栈中设置一个还原点,当带有FLAG_ACTIVITY_RESET_TASK_IF_NEEDED的Intent请求启动这个堆栈时(典型的例子是用户从桌面再次启动这个应用),还原点之上包括这个应用将会被清除。应用场景:在email程序中预览图片时,会启动图片观览的actvity,当用户离开email处理其他事情,然后下次再次从home进入email时,我们呈现给用户的应该是上次email的会话,而不是图片观览,这样才不会给用户造成困惑。
例: 存在Activity A, Activity B, Activity C, Activity A启动开僻Task堆栈, 命名为TaskA(TaskA堆栈状态: A),
在Activity A中启动Activity B(TaskA堆栈状态: AB), 接着Activity B启动Activity C(TaskA堆栈状态: ABC),
启动Activity C的Intent中设置FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET标题, 这样TaskA中有一个还原点,
当有包含FLAG_ACTIVITY_RESET_TASK_IF_NEEDED的Intent请求TaskA堆栈时(比如请求Activity A)
系统就会将还原点以上的Activity清除, TaskA堆栈中只剩下了AB.

   if (!addingToTask && reuseTask == null) {
                       //如果没有正在添加至某个Task, 并且不用加入一个已清除所有Activity的Task
                //此时只需要显示栈顶Activity即可 
                        if (doResume) {
                            targetStack.resumeTopActivityLocked(null, options);
                        } else {
                            ActivityOptions.abort(options);
                        }
                        /// M: Add debug task message @{
                        if (DEBUG_TASKS) {
                            Slog.i(TAG, "START_TASK_TO_FRONT, doResume = " + doResume);
                        }
                        /// @}
                        if (r.task == null)  Slog.v(TAG,
                            "startActivityUncheckedLocked: task left null",
                            new RuntimeException("here").fillInStackTrace());
                        return ActivityManager.START_TASK_TO_FRONT;
                    }
                    /// M: Fix ALPS01276300, reset mMovingToFront flag here @{
                    intentActivity.task.mMovingToFront = false;
                    /// @}

Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP
检查Intent是否设置了Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP,这个标志我有点困惑,从它的注释可以看出它的含义是指如果设置了该flag,那么mHistory中最top的activity在后续的处理中将不被视为top,而将前一个activity视为top,如A–>B–>C,将B视为top。
这个top activity的作用很大,涉及到后面对task的处理。但是目前来看这个flag并没有起到该有的作用,代码中判断如果设置了该标志,那么AMS将会视当前正在启动的activity为top,然后去mHistory中去查找它的前一个activity为后续task处理的top activity(topRunningNonDelayedActivityLocked()中实现),但是现在的问题是此时此刻,正在启动的activity并不存在于mHistory中,因为我们在前一个函数中刚刚创建了这个ActivityRecord。如下面代码所示:
ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
!= 0 ? r : null;
因此,感觉这个flag的意义不是太大。

if (r.packageName != null) {
            ActivityStack topStack = getFocusedStack();
            ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
            if (top != null && r.resultTo == null) {
                if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
                    if (top.app != null && top.app.thread != null) {//检测是否可复用Activity,top为Launcher,r为Setting,不满足
                        if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
                                    top.task);
                            topStack.mLastPausedActivity = null;
                            if (doResume) {
                                resumeTopActivitiesLocked();
                            }
                            ActivityOptions.abort(options);
                            if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {

                                if (r.task == null)  Slog.v(TAG,
                                    "startActivityUncheckedLocked: task left null",
                                    new RuntimeException("here").fillInStackTrace());
                                return ActivityManager.START_RETURN_INTENT_TO_CALLER;
                            }
                            top.deliverNewIntentLocked(callingUid, r.intent);
                           //    当设置Intent.FLAG_ACTIVITY_SINGLE_TOP或者launchMode == ActivityInfo.LAUNCH_SINGLE_TOP或者launchMode == ActivityInfo.LAUNCH_SINGLE_TASK这几种情况下,如果top activity与启动的activity为同一个activity,那么将复用top activity,并直接resume top activity
                            if (r.task == null)  Slog.v(TAG,
                                "startActivityUncheckedLocked: task left null",
                                new RuntimeException("here").fillInStackTrace());
                            return ActivityManager.START_DELIVERED_TO_TOP;
                        }
                    }
                }
            }

else {
if (r.resultTo != null) {
r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
r.requestCode, Activity.RESULT_CANCELED, null);
}
ActivityOptions.abort(options);
if (r.task == null) Slog.v(TAG,
“startActivityUncheckedLocked: task left null”,
new RuntimeException(“here”).fillInStackTrace());
return ActivityManager.START_CLASS_NOT_FOUND;//找不到包名所以取消
}

boolean newTask = false;
        boolean keepCurTransition = false;

        // Should this be considered a new task?
        if (r.resultTo == null && !addingToTask
                && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
            targetStack = adjustStackFocus(r);//adjustStackFocus()获取目标stack。
            moveHomeStack(targetStack.isHomeStack());
            if (reuseTask == null) {
                r.setTask(targetStack.createTaskRecord(getNextTaskId(),
                        newTaskInfo != null ? newTaskInfo : r.info,
                        newTaskIntent != null ? newTaskIntent : intent,
                        true), null, true);
                if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
                        r.task);
            } else {//如果reuse不为空,此时启动 c 会把 A B 清空
                r.setTask(reuseTask, reuseTask, true);
            }
            newTask = true;
if (!movedHome) {
                if ((launchFlags &
                        (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
                        == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
                    // Caller wants to appear on home activity, so before starting
                    // their own activity we will bring home to the front.
                    r.task.mOnTopOfHome = true;
                }
            }

FLAG_ACTIVITY_TASK_ON_HOME :把当前新启动的任务置于Home任务之上,也就是按back键从这个任务返回的时候会回到home,即使这个不是他们最后看见的activity
注意这个标记必须和FLAG_ACTIVITY_NEW_TASK一起使用。
mOnTopOfHome的意思就是当我们按back键的时候发现mOnTopOfHome为true就返回到桌面。

  } else if (sourceRecord != null) {//表示当前要启动的Activity和sourceRecord在同一个task中,因此不需要addingToTask =true
            TaskRecord sourceTask = sourceRecord.task;
            targetStack = sourceTask.stack;
            moveHomeStack(targetStack.isHomeStack());
            /// M: Fix ALPS01276300, need adjust task again since we may move home stack back here @{
            mWindowManager.moveTaskToTop(targetStack.topTask().taskId);
            /// @}
            if (!addingToTask &&
                    (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
                // In this case, we are adding the activity to an existing
                // task, but the caller has asked to clear that task if the
                // activity is already running.
                ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
                /// M: ALPS01265303, Fix google focused stack issue, performClearTaskLocked() may finish all activities in task.
                /// If task is cleared and task.mOnTopOfHome is true, it will adjust focused stack to HomeStack. 
                /// We should adjust right focused task for WMS again. @{
                if (r.task != null) {
                    mWindowManager.moveTaskToTop(r.task.taskId);
                    Slog.v(TAG, "WMS moveTaskToTop after AMS clear task, r = " + r + " task = " + r.task);
                } else {
                    mWindowManager.moveTaskToTop(sourceTask.taskId);
                    Slog.v(TAG, "WMS moveTaskToTop after AMS clear task, r = " + r + " sourceTask = " + sourceTask);
                }

addingToTask变量初始化为false,这个变量也将决定是否要将有关r的Activity在新的任务中启动,从名字我们就可以看出,默认不增加到原有的任务中启动,即要在新的任务中启动。

            keepCurTransition = true;
                if (top != null) {
                    top.setTask(sourceTask, sourceRecord.thumbHolder, false); //为该AactivityRecord设置一个新的TaskRecord
                    mService.setFocusedActivityLocked(top);
                    /// @}
                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
                    /// M: AMS log enhancement @{
                    if(!ActivityManagerService.IS_USER_BUILD)
                        Slog.d(TAG, "ACT-AM_NEW_INTENT " + top + top.task);
                    /// @}
                    top.deliverNewIntentLocked(callingUid, r.intent);//重载要启动的的Activity,因为要启动的Activity在当前正在显示的task,所以可以使用此函数
                    // For paranoia, make sure we have correctly
                    // resumed the top activity.
                    targetStack.mLastPausedActivity = null;
                    //因为现在在启动新的Activity,没有需要暂停的Activity
                    if (doResume) {
                        targetStack.resumeTopActivityLocked(null);
                    }
                    ActivityOptions.abort(options);
                    if (r.task == null)  Slog.w(TAG,
                        "startActivityUncheckedLocked: task left null",
                        new RuntimeException("here").fillInStackTrace());
                    return ActivityManager.START_DELIVERED_TO_TOP;
                }
else if (!addingToTask &&
                    (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
                    //如果已经启动了四个Activity:A,B,C和D,在D Activity里
                    //,想再启动一个Actvity B,但不变成A,B,C,D,B,而是希望是A,C,D,B
                    //,则可以像下面写代码:

            //Intent intent = new Intent(this, MainActivity.class);  
            //intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);   
            //startActivity(intent); 

                final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
                if (top != null) {
                    final TaskRecord task = top.task;
                    task.moveActivityToFrontLocked(top);
                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
                    /// M: AMS log enhancement @{
                    if(!ActivityManagerService.IS_USER_BUILD)
                        Slog.d(TAG, "ACT-AM_NEW_INTENT " + top + top.task);
                    /// @}
                    top.updateOptionsLocked(options);
                    top.deliverNewIntentLocked(callingUid, r.intent);
                    targetStack.mLastPausedActivity = null;
                    if (doResume) {
                        targetStack.resumeTopActivityLocked(null);
                    }
                    return ActivityManager.START_DELIVERED_TO_TOP;
                }
                 r.setTask(sourceTask, sourceRecord.thumbHolder, false);//因为 sourceRecord不为空说明是task内部启动。所以r的task与sourceRecord一样

猜你喜欢

转载自blog.csdn.net/lb5761311/article/details/52210298