我是靠谱客的博主 甜美柠檬,最近开发中收集的这篇文章主要介绍ActivityManagerService->Activity启动->任务选择和Activity复用(Android 6.0),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

之前分析过很多次Ams管理Activity启动,但是并没有太认真,最近想重新分析下Android 10.0,发现难度比较大,所以先找软柿子捏捏,从Android 6.0入手,后面再分析一遍Android 10.0。

分析Android代码的过程,其实就是对Android设计的理解,所以建议读者再读本篇代码分析文章之前一定一定要读下下面两篇Android的官方文档,来了解下Android对Activity任务管理实现了什么样的功能。 这两篇官方文档分别是:
了解任务和返回堆栈
“最近使用的应用”屏幕

这两篇文章足以说明Android对任务的管理,所以我就不进行简介了,直接来分析代码。

还是稍微说两句把, 一般从一个A Activity启动B Activity 不加任何标志,且B Activity的launchMode不是singleTask或者singleInstance, 则A 作为sourceActivity, B会启动到A activity所在的task中。 当从B按返回键的时候就会返回到A Activity。 但是很多时候并不是从Activity 启动另一个Activity,比如从通知中启动Activity,又或者想将一个Activity启动到另外的task, 就需要添加FLAG_ACTIVITY_NEW_TASK 标志。
FLAG_ACTIVITY_NEW_TASK的标志的用意是将Activity启动到最匹配的Task, 那么怎么找到最匹配的task呢,在了解任务和返回堆栈的处理亲和性一节有详细说明。主要就是根据包名或者android:taskAffinity 属性指定的亲和性。 另外处理documentLuanchMode的情况还要参考document data。好了 我觉得说的做够多了,下面直接看代码吧。

final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
            boolean doResume, Bundle options, TaskRecord inTask) {
        final Intent intent = r.intent;
        final int callingUid = r.launchedFromUid;

        // In some flows in to this function, we retrieve the task record and hold on to it
        // without a lock before calling back in to here...  so the task at this point may
        // not actually be in recents.  Check for that, and if it isn't in recents just
        // consider it invalid.
        // inTask为要将Activity启动到的task,只有最近任务可以指定inTask参数,如果指定的task不在最近任务中,设置inTask为空。
        if (inTask != null && !inTask.inRecents) {
            Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
            inTask = null;
        }

        final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP;
        final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;
        final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;

        int launchFlags = intent.getFlags();
        // launchSingleInstance 或者 launchSingleTask标志launchMode的activity 不允使用FLAG_ACTIVITY_NEW_DOCUMENT 或者 FLAG_ACTIVITY_MULTIPLE_TASK标志。
        if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
                (launchSingleInstance || launchSingleTask)) {
            // We have a conflict between the Intent and the Activity manifest, manifest wins.
            Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
                    ""singleInstance" or "singleTask"");
            launchFlags &=
                    ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
        } else {
            // 处理documentLaunchMode, 参考文章Android android:documentLaunchMode属性和FLAG_ACTIVITY_NEW_DOCUMENT说明[添加链接描述](https://blog.csdn.net/woai110120130/article/details/111092009)
            switch (r.info.documentLaunchMode) {
                case ActivityInfo.DOCUMENT_LAUNCH_NONE:
                    break;
                case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
                    break;
                case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
                    break;
                case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
                    launchFlags &= ~Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
                    break;
            }
        }

        final boolean launchTaskBehind = r.mLaunchTaskBehind
                && !launchSingleTask && !launchSingleInstance
                && (launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0;

        // FLAG_ACTIVITY_NEW_TASK标志默认不将Activity启动到sourceRecord,要在新的task中启动,所以resultTo是无效的,返回结果为RESULT_CANCELED。(这里主要处理startActivityForResult)。
        if (r.resultTo != null && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0
                && r.resultTo.task.stack != null) {
            // For whatever reason this activity is being launched into a new
            // task...  yet the caller has requested a result back.  Well, that
            // is pretty messed up, so instead immediately send back a cancel
            // and let the new task continue launched as normal without a
            // dependency on its originator.
            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;
        }

        // FLAG_ACTIVITY_NEW_DOCUMENT 默认加入 FLAG_ACTIVITY_NEW_TASK
        if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
        }

        // If we are actually going to launch in to a new task, there are some cases where
        // we further want to do multiple task.
        // DOCUMENT_LAUNCH_ALWAYS 总是在新task中启动,添加FLAG_ACTIVITY_MULTIPLE_TASK标志
        if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
            if (launchTaskBehind
                    || r.info.documentLaunchMode == ActivityInfo.DOCUMENT_LAUNCH_ALWAYS) {
                launchFlags |= Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
            }
        }

        // 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;
        if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
                "startActivity() => mUserLeaving=" + mUserLeaving);

        // If the caller has asked not to resume at this point, we make note
        // of this in the record so that we can skip it when trying to find
        // the top running activity.
        if (!doResume) {
            r.delayedResume = true;
        }

        // 有些Activity不作为top activity使用,比如ResolveActivity。
        ActivityRecord notTop =
                (launchFlags & Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;

        // If the onlyIfNeeded flag is set, then we can do this if the activity
        // being launched is the same as the one making the call...  or, as
        // a special case, if we do not know the caller then we count the
        // current top activity as the caller.
        if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
            ActivityRecord checkedCaller = sourceRecord;
            if (checkedCaller == null) {
                checkedCaller = mFocusedStack.topRunningNonDelayedActivityLocked(notTop);
            }
            // sourceActivity和要启动的Activity不是相同的Activity,
            // 所以可定需要启动Activity,清除START_FLAG_ONLY_IF_NEEDED标志。
            if (!checkedCaller.realActivity.equals(r.realActivity)) {
                // Caller is not the same as launcher, so always needed.
                startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
            }
        }
        // 重要!!!!:addingToTask表示需要创建新的Activity并且不要创建新的Task
        boolean addingToTask = false;
        TaskRecord reuseTask = null;

        // If the caller is not coming from another activity, but has given us an
        // explicit task into which they would like us to launch the new activity,
        // then let's see about doing that.
        // 没有sourceRecord 并且指定的启动task有效
        if (sourceRecord == null && inTask != null && inTask.stack != null) {
            final Intent baseIntent = inTask.getBaseIntent();
            final ActivityRecord root = inTask.getRootActivity();
            if (baseIntent == null) {  // task 没有baseIntent, 抛出异常。
                ActivityOptions.abort(options);
                throw new IllegalArgumentException("Launching into task without base intent: "
                        + inTask);
            }

            // If this task is empty, then we are adding the first activity -- it
            // determines the root, and must be launching as a NEW_TASK.
            // 检查intask的合法性
            if (launchSingleInstance || launchSingleTask) {
                // 因为launchSingleInstance和 launchSingleTask 启动时带NEW_TASK标志,要想复用intask, 
                // instask必须亲和性匹配,不匹配一律抛出异常。
                if (!baseIntent.getComponent().equals(r.intent.getComponent())) {
                    ActivityOptions.abort(options);
                    throw new IllegalArgumentException("Trying to launch singleInstance/Task "
                            + r + " into different task " + inTask);
                }
                if (root != null) {
                    ActivityOptions.abort(options);
                    throw new IllegalArgumentException("Caller with inTask " + inTask
                            + " has root " + root + " but target is singleInstance/Task");
                }
            }

            // If task is empty, then adopt the interesting intent launch flags in to the
            // activity being started.
            if (root == null) {
                // 空task 更新task的baseIntent,baseIntent决定了task的亲和性
                final int flagsOfInterest = Intent.FLAG_ACTIVITY_NEW_TASK
                        | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT
                        | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
                launchFlags = (launchFlags&~flagsOfInterest)
                        | (baseIntent.getFlags()&flagsOfInterest);
                intent.setFlags(launchFlags);
                inTask.setIntent(r);
                // addingToTask表示需要创建新的Activity并且不要创建新的Task, 这里使用inTask,inTask空,所以创建新Activity
                addingToTask = true;

            // If the task is not empty and the caller is asking to start it as the root
            // of a new task, then we don't actually want to start this on the task.  We
            // will bring the task to the front, and possibly give it a new intent.
            } else if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
                addingToTask = false;
                // addingToTask表示需要创建新的Activity并且不要创建新的Task, 这里可能复用Task和Activity所以设置为False
            } else {
                addingToTask = true;
                //addingToTask表示需要创建新的Activity并且不要创建新的Task, 
                //复用inTask,启动新Activity(没有FLAG_ACTIVITY_NEW_TASK所以不是singleTask和singleInstance)
            }

            reuseTask = inTask;
        } else {
            // inTask无效设置为空
            inTask = null;
        }

        if (inTask == null) {  // inTask 为空的情况
            if (sourceRecord == null) {
                // This activity is not being started from another...  in this
                // case we -always- start a new task.
                sourceRecord  为空不能启动到sourceRecord 所在的task,添加FLAG_ACTIVITY_NEW_TASK标志,用于找到合适的task
                if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && inTask == null) {
                    Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
                            "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
                }
            } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
                sourceRecord 为的launchMode为LAUNCH_SINGLE_INSTANCE, 不能将Activity启动到SourceActivity所在的Task,添加FLAG_ACTIVITY_NEW_TASK标志
                // The original activity who is starting us is running as a single
                // instance...  this new activity it is starting must go on its
                // own task.
                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
            } else if (launchSingleInstance || launchSingleTask) {
                // 要启动的activity的lunchMode为launchSingleInstance || launchSingleTask, 使用FLAG_ACTIVITY_NEW_TASK标志
                // The activity being started is a single instance...  it always
                // gets launched into its own task.
                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
            }
        }

        ActivityInfo newTaskInfo = null;
        Intent newTaskIntent = null;
        ActivityStack sourceStack;
        if (sourceRecord != null) {
            if (sourceRecord.finishing) { 
            // sourceRecord 正在finishing,不能添加Activity到SourceActivity所在的Task中,
            // 添加FLAG_ACTIVITY_NEW_TASK标志, 保留newTaskInfo, newTaskIntent 用于创建新Task的时候使用
                // If the source is finishing, we can't further count it as our source.  This
                // is because the task it is associated with may now be empty and on its way out,
                // so we don't want to blindly throw it in to that task.  Instead we will take
                // the NEW_TASK flow and try to find a task for it. But save the task information
                // so it can be used when creating the new 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 {
                // 使用sourceActivity 设置sourceStask
                sourceStack = sourceRecord.task.stack;
            }
        } else {
            // sourceActivity不存在,所以sourceStack也不存在
            sourceStack = null;
        }

        boolean movedHome = false;
        ActivityStack targetStack;

        intent.setFlags(launchFlags);
        final boolean noAnimation = (launchFlags & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0;

        // We may want to try to place the new activity in to an existing task.  We always
        // do this if the target activity is singleTask or singleInstance; we will also do
        // this if NEW_TASK has been requested, and there is not an additional qualifier telling
        // us to still place it in a new task: multi task, always doc mode, or being asked to
        // launch this as a new task behind the current one.
        // FLAG_ACTIVITY_MULTIPLE_TASK标志表示要启动Activity到新的Task中。
        // FLAG_ACTIVITY_NEW_TASK,launchSingleInstance, launchSingleTask可能复用Activity或者Task,
        // 下面的分支尝试寻找复用的Task和Activity。
        if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
                (launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
                || launchSingleInstance || launchSingleTask) {
            // If bring to front is requested, and no result is requested and we have not
            // been given an explicit task to launch in to, and
            // we can find a task that was started with this same
            // component, then instead of launching bring that one to the front.
            if (inTask == null && r.resultTo == null) {
                // See if there is a task to bring to the front.  If this is
                // a SINGLE_INSTANCE activity, there can be one and only one
                // instance of it in the history, and it is always in its own
                // unique task, so we do a special search.
                // 寻找复用的Activity或者Task,当launchSingleInstance为真的时候要启动的Activity只能存在一个实例
                // 所以必须要找到Activity才能复用,使用findActivityLocked来寻找。 而对于NEW_TASK或者singleTask的情况
                // 使用findTaskLocked来寻找复用的Task,这里findTaskLocked函数返回可以复用的Task的栈顶Activity,一般
                // 寻找复用Task是根据亲和性,复用的Activity可能不在这个Task中,也可能在这个Task中,后面还会继续做一些操作
                // 来寻找复用的Activity。
                ActivityRecord intentActivity = !launchSingleInstance ?
                        findTaskLocked(r) : findActivityLocked(intent, r.info);
                if (intentActivity != null) { // 这里表示找到了可复用的Activity
                    // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused
                    // but still needs to be a lock task mode violation since the task gets
                    // cleared out and the device would otherwise leave the locked task.
                    // 违反lockTask规则,返回ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION
                    if (isLockTaskModeViolation(intentActivity.task,
                            (launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
                        showLockTaskToast();
                        Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
                        return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
                    }
                    if (r.task == null) { // 设置Task
                        r.task = intentActivity.task;
                    }
                    if (intentActivity.task.intent == null) { // 设置Task的 baseIntent
                        // This task was started because of movement of
                        // the activity based on affinity...  now that we
                        // are actually launching it, we can assign the
                        // base intent.
                        intentActivity.task.setIntent(r);
                    }
                    targetStack = intentActivity.task.stack;
                    targetStack.mLastPausedActivity = null;
                    // If the target task is not in the front, then we need
                    // to bring it to the front...  except...  well, with
                    // SINGLE_TASK_LAUNCH it's not entirely clear.  We'd like
                    // to have the same behavior as if a new instance was
                    // being started, which means not bringing it to the front
                    // if the caller is not itself in the front.
                    final ActivityStack focusStack = getFocusedStack();
                    // 当前焦点Activity
                    ActivityRecord curTop = (focusStack == null)
                            ? null : focusStack.topRunningNonDelayedActivityLocked(notTop);
                    boolean movedToFront = false;
                    if (curTop != null && (curTop.task != intentActivity.task ||
                            curTop.task != focusStack.topTask())) {
                    // 焦点Task 和 要复用的Task不是同一个Task或者 
                    // 焦点Task和复用的Task为同一个Task但是当前Task不是TopTask,
                    // 那需要移动Task到顶部,这样才能在task上启动Activity或者复用Activity。
                        r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
                        if (sourceRecord == null || (sourceStack.topActivity() != null &&
                                sourceStack.topActivity().task == sourceRecord.task)) {
                            // 没有sourceRecord或者 sourceRecord的task在stack顶部,
                            // 这里新的Activity启动需要有个Task切换的过程
                            // 调用moveTaskToFrontLocked进行切换。这里会将targetStack
                            // 设为焦点stack。 sourceRecord的Task不再
                            // Task顶部的时候为后台Activity启动Activity,不需要把目标Task搞到前台
                            // We really do want to push this one into the user's face, right now.
                            if (launchTaskBehind && sourceRecord != null) {
                                intentActivity.setTaskToAffiliateWith(sourceRecord.task);
                            }
                            movedHome = true;
                            targetStack.moveTaskToFrontLocked(intentActivity.task, noAnimation,
                                    options, r.appTimeTracker, "bringingFoundTaskToFront");
                            movedToFront = true;
                            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.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
                            }
                            options = null;
                        }
                    }
                    if (!movedToFront) {
                        // 前面moveTaskToFrontLocked会将目标stack移动到前台,如果那里没有移动,这里来移动
                        if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + targetStack
                                + " from " + intentActivity);
                        targetStack.moveToFront("intentActivityFound");
                    }

                    // If the caller has requested that the target task be
                    // reset, then do so.
                    // 点击桌面图标会设置FLAG_ACTIVITY_RESET_TASK_IF_NEEDED标志,用来释放过期的Activity
                    // 这块请参考https://developer.android.com/guide/components/activities/tasks-and-back-stack
                    // 返回堆栈一节。
                    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.
                        // START_FLAG_ONLY_IF_NEEDED标志前边已经验证过了,如果caller或者焦点Activity不是要
                        // 启动的Activity, 已经去掉了START_FLAG_ONLY_IF_NEEDED标志,所以Task已经被弄到了
                        // 前台, 所以直接resume Activity就好了。 这个分支就反回了。
                        if (doResume) {
                            resumeTopActivitiesLocked(targetStack, null, options);

                            // Make sure to notify Keyguard as well if we are not running an app
                            // transition later.
                            if (!movedToFront) {
                                notifyActivityDrawnForKeyguard();
                            }
                        } else {
                            ActivityOptions.abort(options);
                        }
                        return ActivityManager.START_RETURN_INTENT_TO_CALLER;
                    }
                    if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                            == (FLAG_ACTIVITY_NEW_TASK | 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...
                        // FLAG_ACTIVITY_CLEAR_TASK 标志清空Task, reuseTask 为复用的Task
                        reuseTask = intentActivity.task;
                        reuseTask.performClearTaskLocked();
                        reuseTask.setIntent(r);
                    } else if ((launchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
                            || launchSingleInstance || launchSingleTask) {
                        // In this situation we want to remove all activities
                        // from the task up to the one being started.  In most
                        // cases this means we are resetting the task to its
                        // initial state.
                        // FLAG_ACTIVITY_CLEAR_TOP, launchSingleInstance, launchSingleTask都需要将
                        // 可以复用的Activity上的Activity清掉,调用performClearTaskLocked来清掉复用Activity
                        // 上的Activity, 这里如果复用的Activity的launchMode为standard,也会被清掉。如果复用的
                        // Activity 没有被清掉,并且也存在task中,那么通过将会返回,保存再top中。
                        ActivityRecord top =
                                intentActivity.task.performClearTaskLocked(r, launchFlags);
                        if (top != null) {
                            // 找到了可复用的Activity,调用
                            // top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage)
                            // 用于发射新的Intent(Activity的onNewIntent方法)
                            if (top.frontOfTask) {
                                // Task中唯一的Activity,用于设置Task的亲和性。
                                // Activity aliases may mean we use different
                                // intents for the top activity, so make sure
                                // the task now has the identity of the new
                                // intent.
                                top.task.setIntent(r);
                            }
                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
                                    r, top.task);
                            top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
                        } else {
                            // A special case: we need to start the activity because it is not
                            // currently running, and the caller has asked to clear the current
                            // task to have this activity at the top.
                            // 没有找到复用的Activity, 这里addingToTask设置为true,表示不创建新的Task,
                            // 创建新的Activity。
                            addingToTask = true;
                            // Now pretend like this activity is being started by the top of its
                            // task, so it is put in the right place.
                            // 这里intentActivity已经被带到了前台,所以设置sourceRecord为intentActivity
                            // 并且intentActivity.task是复用的Task,后面启动Activity的过程只需要走
                            // 在sourceRecord.task 中启动的流程就可以了。
                            sourceRecord = intentActivity;
                            TaskRecord task = sourceRecord.task;
                            if (task != null && task.stack == null) {
                                // 如果sourceRecord.task的stack不存在,则加到焦点栈上,这种情况在clearTask时发生。
                                // Target stack got cleared when we all activities were removed
                                // above. Go ahead and reset it.
                                targetStack = computeStackFocus(sourceRecord, false /* newTask */);
                                targetStack.addTask(
                                        task, !launchTaskBehind /* toTop */, false /* moving */);
                            }

                        }
                    } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
                        // In this case the top activity on the task is the
                        // same as the one being launched, so we take that
                        // as a request to bring the task to the foreground.
                        // If the top activity in the task is the root
                        // activity, deliver this new intent to it if it
                        // desires.
                        // 非(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)的情况
                        // 非FLAG_ACTIVITY_CLEAR_TOP的情况
                        // 非launchSingleInstance || launchSingleTask的情况
                        // intentActivity为Task顶部的Activity并且是根Activity,这种情况下
                        // 如果要给launchSingleTop的Activity或者(launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP)
                        // 启动的情况下发射新的Intent。ntentActivity.deliverNewIntentLocked(
                        // callingUid, r.intent, r.launchedFromPackage)
                        if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 || launchSingleTop)
                                && intentActivity.realActivity.equals(r.realActivity)) {
                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
                                    intentActivity.task);
                            if (intentActivity.frontOfTask) {
                                intentActivity.task.setIntent(r);
                            }
                            intentActivity.deliverNewIntentLocked(callingUid, r.intent,
                                    r.launchedFromPackage);
                        } 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.
                            // 这种情况标准启动。 intentActivit没法复用,但是会把Activity启动的Task上,所以设置
                            // addingToTask为真,表示不创建Task但是创建新的Activity。这里复用的Task为
                            // intentActivity的Task, 所以设置sourceRecord为intentActivity
                            addingToTask = true;
                            sourceRecord = intentActivity;
                        }
                    } 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.
                        // 从桌面图标启动Activity设置FLAG_ACTIVITY_RESET_TASK_IF_NEEDED标志。
                        // 这里不是从桌面 启动Activity。
                        // 到这里真的没有复用的Activity了,复用的Task还在, 所以设置
                        // addingToTask为真,表示不创建Task但是创建新的Activity。这里复用的Task为
                        // intentActivity的Task, 所以设置sourceRecord为intentActivity
                        addingToTask = true;
                        sourceRecord = intentActivity;
                    } 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.
                        // 之前该Task不是从桌面启动的,现在从桌面启动(FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
                        // 更新Task亲和性和图标什么的
                        intentActivity.task.setIntent(r);
                    } else {
                        // 我自己加的,这个分支只是要把Task带到前台,典型情况就是点击桌面图标,把Task带到前台。
                    }
                    if (!addingToTask && reuseTask == null) {
                        // addingToTask的一个含义就是启动新的Activity。
                        // reuseTask表示复用Task,Activity还没启动. 进入这个分支表示要么复用
                        // 了Activity要么就只是把Task带台,这种情况并没有真的启动Activity, 
                        // 返回START_TASK_TO_FRONT
                        // We didn't do anything...  but it was needed (a.k.a., client
                        // don't use that intent!)  And for paranoia, make
                        // sure we have correctly resumed the top activity.
                        if (doResume) {
                            targetStack.resumeTopActivityLocked(null, options);
                            if (!movedToFront) {
                                // Make sure to notify Keyguard as well if we are not running an app
                                // transition later.
                                notifyActivityDrawnForKeyguard();
                            }
                        } else {
                            ActivityOptions.abort(options);
                        }
                        return ActivityManager.START_TASK_TO_FRONT;
                    }
                }
            }
        }

        //String uri = r.intent.toURI();
        //Intent intent2 = new Intent(uri);
        //Slog.i(TAG, "Given intent: " + r.intent);
        //Slog.i(TAG, "URI is: " + uri);
        //Slog.i(TAG, "To intent: " + intent2);

        if (r.packageName != null) {
            // If the activity being launched is the same as the one currently
            // at the top, then we need to check if it should only be launched
            // once.
            // 没有NEW_TASK标志的情况或者使用inTask的情况,这里还是有机会复用Activity的,所以再做一轮尝试复用
            ActivityStack topStack = mFocusedStack;
            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) {
                        if ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
                            || launchSingleTop || launchSingleTask) {
                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
                                    top.task);
                            // For paranoia, make sure we have correctly
                            // resumed the top activity.
                            topStack.mLastPausedActivity = null;
                            if (doResume) {
                                resumeTopActivitiesLocked();
                            }
                            ActivityOptions.abort(options);
                            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!
                                return ActivityManager.START_RETURN_INTENT_TO_CALLER;
                            }
                            top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
                            return ActivityManager.START_DELIVERED_TO_TOP;
                        }
                    }
                }
            }

        } else {
            // 异常情况,返回
            if (r.resultTo != null && r.resultTo.task.stack != null) {
                r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
                        r.requestCode, Activity.RESULT_CANCELED, null);
            }
            ActivityOptions.abort(options);
            return ActivityManager.START_CLASS_NOT_FOUND;
        }

        boolean newTask = false;
        boolean keepCurTransition = false;

        TaskRecord taskToAffiliate = launchTaskBehind && sourceRecord != null ?
                sourceRecord.task : null;

        // Should this be considered a new task?
        if (r.resultTo == null && inTask == null && !addingToTask
                && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
            // 这种情况创建新Task或者是用reuseTask(这种情况reuseTask是被FLAG_ACTIVITY_CLEAR_TASK情况的)
            // 先把目标Task移动到前台。
            newTask = true;
            targetStack = computeStackFocus(r, newTask);
            targetStack.moveToFront("startingNewTask");

            if (reuseTask == null) {
                // reuseTask不存在创建
                r.setTask(targetStack.createTaskRecord(getNextTaskId(),
                        newTaskInfo != null ? newTaskInfo : r.info,
                        newTaskIntent != null ? newTaskIntent : intent,
                        voiceSession, voiceInteractor, !launchTaskBehind /* toTop */),
                        taskToAffiliate);
                if (DEBUG_TASKS) Slog.v(TAG_TASKS,
                        "Starting new activity " + r + " in new task " + r.task);
            } else {
                // 更新Activity的Task
                r.setTask(reuseTask, taskToAffiliate);
            }
            if (isLockTaskModeViolation(r.task)) { 
                // 违反LockTask 返回 START_RETURN_LOCK_TASK_MODE_VIOLATION
                Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
                return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
            }
            if (!movedHome) {
                // FLAG_ACTIVITY_TASK_ON_HOME 标志设置Task返回到桌面
                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, so before starting
                    // their own activity we will bring home to the front.
                    r.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
                }
            }
        } else if (sourceRecord != null) {
            // 启动Activity到sourceRecord的情况
            final TaskRecord sourceTask = sourceRecord.task;
            if (isLockTaskModeViolation(sourceTask)) {
                // 违反LockTask返回START_RETURN_LOCK_TASK_MODE_VIOLATION
                Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
                return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
            }
            // 移动目标stack到前台
            targetStack = sourceTask.stack;
            targetStack.moveToFront("sourceStackToFront");
            final TaskRecord topTask = targetStack.topTask();
            if (topTask != sourceTask) {
                // 移动Task到前台
                targetStack.moveTaskToFrontLocked(sourceTask, noAnimation, options,
                        r.appTimeTracker, "sourceTaskToFront");
            }
            if (!addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
                // 不允许创建Task的情况,FLAG_ACTIVITY_CLEAR_TOP标志,执行performClearTaskLocked,
                // 找到复用的Activity,执行deliverNewIntentLocked发射新的intent,
                // 返回 START_DELIVERED_TO_TOP
                // 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);
                keepCurTransition = true;
                if (top != null) {
                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
                    top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
                    // For paranoia, make sure we have correctly
                    // resumed the top activity.
                    targetStack.mLastPausedActivity = null;
                    if (doResume) {
                        targetStack.resumeTopActivityLocked(null);
                    }
                    ActivityOptions.abort(options);
                    return ActivityManager.START_DELIVERED_TO_TOP;
                }
            } else if (!addingToTask &&
                    (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
                // 不允许创建新的Task的情况,处理FLAG_ACTIVITY_REORDER_TO_FRONT标志
                // In this case, we are launching an activity in our own task
                // that may already be running somewhere in the history, and
                // we want to shuffle it to the front of the stack if so.
                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);
                    top.updateOptionsLocked(options);
                    top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
                    targetStack.mLastPausedActivity = null;
                    if (doResume) {
                        targetStack.resumeTopActivityLocked(null);
                    }
                    return ActivityManager.START_DELIVERED_TO_TOP;
                }
            }
            // An existing activity is starting this new activity, so we want
            // to keep the new one in the same task as the one that is starting
            // it.
            // 真的启动Activity到sourceRecord所在的Task中。
            r.setTask(sourceTask, null);
            if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + r
                    + " in existing task " + r.task + " from source " + sourceRecord);

        } else if (inTask != null) {
            // The caller is asking that the new activity be started in an explicit
            // task it has provided to us.
            // 使用inTask启动后的情况
            if (isLockTaskModeViolation(inTask)) {
                Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
                return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
            }
            // 移动目标Task到前台
            targetStack = inTask.stack;
            targetStack.moveTaskToFrontLocked(inTask, noAnimation, options, r.appTimeTracker,
                    "inTaskToFront");

            // Check whether we should actually launch the new activity in to the task,
            // or just reuse the current activity on top.
            ActivityRecord top = inTask.getTopActivity();
            if (top != null && top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
                if ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
                        || launchSingleTop || launchSingleTask) {
                    // 最后一次复用Activity的机会
                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
                    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!
                        return ActivityManager.START_RETURN_INTENT_TO_CALLER;
                    }
                    top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
                    return ActivityManager.START_DELIVERED_TO_TOP;
                }
            }

            if (!addingToTask) {
                // 不允许创建Activity或者复用Tsk,到这就结束算了,返回 START_TASK_TO_FRONT
                // We don't actually want to have this activity added to the task, so just
                // stop here but still tell the caller that we consumed the intent.
                ActivityOptions.abort(options);
                return ActivityManager.START_TASK_TO_FRONT;
            }
            // 使用inTask
            r.setTask(inTask, null);
            if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + r
                    + " in explicit task " + r.task);

        } else {
            // This not being started from an existing activity, and not part
            // of a new task...  just put it in the top task, though these days
            // this case should never happen.
            // 没有合适的Task和复用的Ativity, 只能使用焦点Activity的栈了。
            targetStack = computeStackFocus(r, newTask);
            targetStack.moveToFront("addingToTopTask");
            ActivityRecord prev = targetStack.topActivity();
            r.setTask(prev != null ? prev.task : targetStack.createTaskRecord(getNextTaskId(),
                            r.info, intent, null, null, true), null);
            mWindowManager.moveTaskToTop(r.task.taskId);
            if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + r
                    + " in new guessed " + r.task);
        }
        // 后面就是真的要启动Activity了。
        mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
                intent, r.getUriPermissionsLocked(), r.userId);

        if (sourceRecord != null && sourceRecord.isRecentsActivity()) {
            r.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
        }
        if (newTask) {
            EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
        }
        ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
        targetStack.mLastPausedActivity = null;
        // 真正要启动Activity了。
        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
        if (!launchTaskBehind) {
            // 更新焦点Activity
            // Don't set focus on an activity that's going to the back.
            mService.setFocusedActivityLocked(r, "startedActivity");
        }
        return ActivityManager.START_SUCCESS;
    }

所有解释我都写在注释中了,我觉得已经非常详细了,全网没有比这个再详细的了。 有耐心的就看吧。

最后

以上就是甜美柠檬为你收集整理的ActivityManagerService->Activity启动->任务选择和Activity复用(Android 6.0)的全部内容,希望文章能够帮你解决ActivityManagerService->Activity启动->任务选择和Activity复用(Android 6.0)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(43)

评论列表共有 0 条评论

立即
投稿
返回
顶部