AMS-ActivityStarter 对stack和task的处理

1 ActrivityStarter: ActivityStarter管理一次activity启动的上下文,但是对stack和task的操作也是少不了的
在启动activity的一次操作就是把stack移动到前台的操作.函数setTargetStackAndMoveToFrontIfNeeded,函数的意思是这只目标tsack并且如果需要移动到前台
函数的名字很长想表达的含义也不是很清晰. 我们来看下函数的注释
把我们在历史中找到的activity record的task和activity带到前台. 如果需要也可能清除task

private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
        mTargetStack = intentActivity.getStack();
        mTargetStack.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 = mSupervisor.getFocusedStack();
        ActivityRecord curTop = (focusStack == null)
                ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);

        final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
        if (topTask != null
                && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
                && !mAvoidMoveToFront) {
            mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
            if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
                    mSourceStack.topActivity().getTask() == mSourceRecord.getTask())) {
                // We really do want to push this one into the user's face, right now.
                if (mLaunchTaskBehind && mSourceRecord != null) {
                    intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
                }
                mMovedOtherTask = true;

                // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
                // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
                // So no point resuming any of the activities here, it just wastes one extra
                // resuming, plus enter AND exit transitions.
                // Here we only want to bring the target stack forward. Transition will be applied
                // to the new activity that's started after the old ones are gone.
                final boolean willClearTask =
                        (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
                if (!willClearTask) {
                    final ActivityStack launchStack = getLaunchStack(
                            mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
                    final TaskRecord intentTask = intentActivity.getTask();
                    if (launchStack == null || launchStack == mTargetStack) {
                        // We only want to move to the front, if we aren't going to launch on a
                        // different stack. If we launch on a different stack, we will put the
                        // task on top there.
                        mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
                                mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
                        mMovedToFront = true;
                    } else if (launchStack.mStackId == DOCKED_STACK_ID
                            || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
                        if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
                            // If we want to launch adjacent and mTargetStack is not the computed
                            // launch stack - move task to top of computed stack.
                            intentTask.reparent(launchStack.mStackId, ON_TOP,
                                    REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
                                    "launchToSide");
                        } else {
                            // TODO: This should be reevaluated in MW v2.
                            // We choose to move task to front instead of launching it adjacent
                            // when specific stack was requested explicitly and it appeared to be
                            // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
                            mTargetStack.moveTaskToFrontLocked(intentTask,
                                    mNoAnimation, mOptions, mStartActivity.appTimeTracker,
                                    "bringToFrontInsteadOfAdjacentLaunch");
                        }
                        mMovedToFront = true;
                    } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
                        // Target and computed stacks are on different displays and we've
                        // found a matching task - move the existing instance to that display and
                        // move it to front.
                        intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
                                REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
                                "reparentToDisplay");
                        mMovedToFront = true;
                    }
                    mOptions = null;

                    // We are moving a task to the front, use starting window to hide initial drawn
                    // delay.
                    intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
                            true /* taskSwitch */);
                }
                updateTaskReturnToType(intentActivity.getTask(), mLaunchFlags, focusStack);
            }
        }
        if (!mMovedToFront && mDoResume) {
            if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
                    + " from " + intentActivity);
            mTargetStack.moveToFront("intentActivityFound");
        }

        mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(), INVALID_STACK_ID,
                DEFAULT_DISPLAY, mTargetStack.mStackId);

        // If the caller has requested that the target task be reset, then do so.
        if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
            return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
        }
        return intentActivity;
    }

函数不是很长但是很不好理解
1把我们找到的task对应的activity设置为mTargetStack
2好到焦点stack 保存在变量focusStack中
3 找到焦点stack中的topActivity
这里的注释说的比较清楚,如果mTargetStack没有在前台,那么我们需要把它拿到前台.对于SINGLE_TASK_LAUNCH这里还不太明确,我们希望有相同的行为,就像一个新的实例正在启动,这意味着如果调用者不在前面,就不会把它带到前面。(这里是说如果调用这不在前台就不把它的stack和tack拿到前台).这里是说对于SINGLE_TASK_LAUNCH的情况如果调用者不在前台(注意这里是这调用者的task不在它的stack的前台)就不会把要启动的activity移动到前台.
4 首先做了一个条件判断.要满足这个条件才能进行后面的移动操作.. 这个条件其实是有三个条件组成
  1 焦点stack的topTask不应该为空,为空则以为着我们的焦点stack不存在.所以也没有必要移动. 同时也是给二个条件做铺垫,否则有可能发生空指针
  2 (topTask != intentActivity.getTask() || topTask != focusStack.topTask())  这里就是判断是否有移动的必要,条件1很好理解,如果要移动到上面的task本身就是焦点task也就没有必要去移动. 另外第二个条件则是把当focusStack上当前可见的task移动到最上面
  3 mAvoidMoveToFront 为false,这个变量的含义很清楚
5 设置mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT),证明这个task是移动上来的,同时之后也会将这个intent分发给启动的activity
6 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
mSourceStack.topActivity().getTask() == mSourceRecord.getTask())) 这个判断就是前面注释中说的要求调用者的task属于它所在的stack的最上面
7 对于mLaunchTaskBehind设置成true的表示不把要启动的activity放到前台,只是放到后面,并且要在recentActivity中放到调用者的task前面,实现是通过一个双向链表的结构维护他们的关心,这里是更新这个链表
8 如果启动参数设置了FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK标志表明要清空我们要带到上面来的task,这种情况由setTaskFromIntentActivity函数去处理.所以不会进入下面的if语句
9 这种情况才是我们要真正移动task的情况我们来看下如何处理
1 首先计算出来要在哪个stack中启动
2 如果没有找到明确的launchStack或者就是我们要带到前面的task所在的stack,这种情况只需要调用 mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, “bringingFoundTaskToFront”) 把task启动到这个stack的前台就可以了,看来getLaunchTask函数主要用于处理指定了lunchTask的情况
3.1  对于没有指定的情况,使用 mTargetStack.moveTaskToFrontLocked(
intentActivity.task, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, “bringingFoundTaskToFront”)函数将task移动到顶部,这个函数我们会在专门分析stack,task的章节分析,由于这里已经把task移动的了顶端,所以设置mMovedToFront = true
3.2 launchStack.mStackId == DOCKED_STACK_ID
|| launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID 对于docker和full stack这两种情况
1 FLAG_ACTIVITY_LAUNCH_ADJACENT 启动task到堆栈底部,并不移动到前台
2 将task移动到前台
4 更新returnType
5 对于不需要移动task的情况,直接移动stack到前台
6 FLAG_ACTIVITY_RESET_TASK_IF_NEEDED处理
7 返回

 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
            int launchFlags, ActivityOptions aOptions) {
        final TaskRecord task = r.task;
        if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
            return mSupervisor.mHomeStack;
        }

        ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
        if (stack != null) {
            return stack;
        }

        if (task != null && task.stack != null) {
            stack = task.stack;
            if (stack.isOnHomeDisplay()) {
                if (mSupervisor.mFocusedStack != stack) {
                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
                            "computeStackFocus: Setting " + "focused stack to r=" + r
                                    + " task=" + task);
                } else {
                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
                            "computeStackFocus: Focused stack already="
                                    + mSupervisor.mFocusedStack);
                }
            }
            return stack;
        }

        final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
        if (container != null) {
            // The first time put it on the desired stack, after this put on task stack.
            r.mInitialActivityContainer = null;
            return container.mStack;
        }

        // The fullscreen stack can contain any task regardless of if the task is resizeable
        // or not. So, we let the task go in the fullscreen task if it is the focus stack.
        // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
        // we can also put it in the focused stack.
        final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
        final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
                || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
                || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
        if (canUseFocusedStack && (!newTask
                || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
            if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
                    "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
            return mSupervisor.mFocusedStack;
        }

        // We first try to put the task in the first dynamic stack.
        final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
        for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
            stack = homeDisplayStacks.get(stackNdx);
            if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
                if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
                        "computeStackFocus: Setting focused stack=" + stack);
                return stack;
            }
        }

        // If there is no suitable dynamic stack then we figure out which static stack to use.
        final int stackId = task != null ? task.getLaunchStackId() :
                bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
                        FULLSCREEN_WORKSPACE_STACK_ID;
        stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
                + r + " stackId=" + stack.mStackId);
        return stack;
    }

computeStackFocus函数主要用于计算activity要启动在哪个stack中。整个过程是按照一定的优先级去处理的
1.首先如果要启动的activity不是应用activity,或者所在的task不是应用的tack,就直接返回mHomeStack, 对于非应用的activity,剩下的两种activity类型为 static final int HOME_ACTIVITY_TYPE = 1; 代表桌面
static final int RECENTS_ACTIVITY_TYPE = 2; 多任务
2 如果不是home stack,那么要以指定的stack为主,主要就是参数aOptions所指定的task
3 二中没有找到合适的结果,返回task所在的stack. 如果这里没有找到,那么说面task不在stack中
4 从ActivityContainer中找stack,也就是父activity
5 对于焦点stack类型为FULLSCREEN_WORKSPACE_STACK_ID或者DOCKED_STACK_ID或者FREEFORM_WORKSPACE_STACK_ID这三种可以获取焦点的stack, 直接返回mFocusedStack
6 返回动态stack
7 根据task的类型找到一个或者创建一个stack 

int getLaunchStackId() {
        if (!isApplicationTask()) {
            return HOME_STACK_ID;
        }
        if (mBounds != null) {
            return FREEFORM_WORKSPACE_STACK_ID;
        }
        return FULLSCREEN_WORKSPACE_STACK_ID;
    }

这里可以看到isApplicationTask为false必然使用桌面 stack, mBounds部为空说明有个大小,所以放在自由模式的stack 中,最后如果二者都是不放在全屏的stack中。

private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
        mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
                mOptions);

        if (mReuseTask == null) {
            final TaskRecord task = mTargetStack.createTaskRecord(
                    mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
                    mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
                    mNewTaskIntent != null ? mNewTaskIntent : mIntent,
                    mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
            mStartActivity.setTask(task, taskToAffiliate);
            if (mLaunchBounds != null) {
                final int stackId = mTargetStack.mStackId;
                if (StackId.resizeStackWithLaunchBounds(stackId)) {
                    mService.resizeStack(
                            stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
                } else {
                    mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
                }
            }
            if (DEBUG_TASKS) Slog.v(TAG_TASKS,
                    "Starting new activity " +
                            mStartActivity + " in new task " + mStartActivity.task);
        } else {
            mStartActivity.setTask(mReuseTask, taskToAffiliate);
        }
    }

这个函数虽然叫setTaskFromReuseOrCreateNewTask,但是它也做了另外一个工作就是计算了mTargetStack
这个函数主要分为两种情况
1 mReuseTask不为空的时候,这种有两种情况 分别是FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK的情况,另外一种就是指定了task。  
这种情况很好处理,直接设置mStartActivity的task为mReuseTask。
2 就是没有复用的task,所以在mTargetStack中创建一个task,通过createTaskRecord函数。这个函数我们分析stack的时候再完整分析。 另外还处理了mLaunchBounds不为空的情况,对于画中画的stack采用mService.resizeStack(
stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1)更新大小,不是画中画模式则使用 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds)更新配置

下面分析setTaskFromSourceRecord函数,用于从sourceActivity中获取task

private int setTaskFromSourceRecord() {
        final TaskRecord sourceTask = mSourceRecord.task;
        // We only want to allow changing stack if the target task is not the top one,
        // otherwise we would move the launching task to the other side, rather than show
        // two side by side.
        final boolean moveStackAllowed = sourceTask.stack.topTask() != sourceTask;
        if (moveStackAllowed) {
            mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
                    mOptions);
        }

        if (mTargetStack == null) {
            mTargetStack = sourceTask.stack;
        } else if (mTargetStack != sourceTask.stack) {
            mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
                    ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
        }
        if (mDoResume) {
            mTargetStack.moveToFront("sourceStackToFront");
        }
        final TaskRecord topTask = mTargetStack.topTask();
        if (topTask != sourceTask && !mAvoidMoveToFront) {
            mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
                    mStartActivity.appTimeTracker, "sourceTaskToFront");
        }
        if (!mAddingToTask && (mLaunchFlags & 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(mStartActivity, mLaunchFlags);
            mKeepCurTransition = true;
            if (top != null) {
                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
                top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
                // For paranoia, make sure we have correctly resumed the top activity.
                mTargetStack.mLastPausedActivity = null;
                if (mDoResume) {
                    mSupervisor.resumeFocusedStackTopActivityLocked();
                }
                ActivityOptions.abort(mOptions);
                return START_DELIVERED_TO_TOP;
            }
        } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
            // 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(mStartActivity);
            if (top != null) {
                final TaskRecord task = top.task;
                task.moveActivityToFrontLocked(top);
                top.updateOptionsLocked(mOptions);
                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
                top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
                mTargetStack.mLastPausedActivity = null;
                if (mDoResume) {
                    mSupervisor.resumeFocusedStackTopActivityLocked();
                }
                return 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.
        mStartActivity.setTask(sourceTask, null);
        if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
                + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
        return START_SUCCESS;
    }

函数首先也是要计算目标stack,首先是通过判断能否移动source activity所在的stack到顶端,只有source activity不在它所在的stack的顶端task的情况才允许移动stack,否则的话只是会把task移动到目标stack上。 这样的目标只是尽可能的减少操作。
如果确实可以移动stack,才会从lunch参数中去计算stack. 否则的话使用source activity所在的stack. 使用函数mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
ON_TOP, FORCE_FOCUS, “launchToSide”, !ANIMATE)
然后如果需要就去移动task到目标stack,如果要马上显示要启动的activity还需要把stack移动到前面。使用函数mTargetStack.moveToFront(“sourceStackToFront”)
使用 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, “sourceTaskToFront”)函数将task移动的stack最顶层, 对于stack和task移动好了之后就该处理activity了。
下面处理的两种情况,分别是!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0 这种情况多数是由于调用者指定的task. 这里要处理FLAG_ACTIVITY_CLEAR_TOP,清除目标顶部activity,然后如果复用activity,则分发newIntent。再使activity可见Stack->resumeFocusedStackTopActivityLocked(),最后返回START_DELIVERED_TO_TOP 。另外的一种情况就是(!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) ,对FLAG_ACTIVITY_REORDER_TO_FRONT的处理,这种情况移动activity到task顶部,分发newIntent,然后显示返回START_DELIVERED_TO_TOP。
最后设置启动的activity所在的task, mStartActivity.setTask(sourceTask, null)

setTaskFromInTask函数用于处理mInTask不为空的情况

private int setTaskFromInTask() {
        if (mLaunchBounds != null) { // 1 对mLaunchBounds的处理
            mInTask.updateOverrideConfiguration(mLaunchBounds);
            int stackId = mInTask.getLaunchStackId();
            if (stackId != mInTask.stack.mStackId) {
                final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
                        mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
                stackId = stack.mStackId;
            }
            if (StackId.resizeStackWithLaunchBounds(stackId)) {
                mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
            }
        }
        mTargetStack = mInTask.stack;   //2 移动task到stack顶部
        mTargetStack.moveTaskToFrontLocked(
                mInTask, mNoAnimation, mOptions, mStartActivity.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 = mInTask.getTopActivity(); // 3 处理FLAG_ACTIVITY_SINGLE_TOP
        if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
            if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
                    || mLaunchSingleTop || mLaunchSingleTask) {
                ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
                if ((mStartFlags & 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 START_RETURN_INTENT_TO_CALLER;
                }
                top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
                return START_DELIVERED_TO_TOP;
            }
        }

        if (!mAddingToTask) { //4 不需要添加activity到task
            // 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(mOptions);
            return START_TASK_TO_FRONT;
        }

        mStartActivity.setTask(mInTask, null); //5 设置tasl
        if (DEBUG_TASKS) Slog.v(TAG_TASKS,
                "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);

        return START_SUCCESS;
    }

代码主要分为5部分,如注释所说
1 处理mLaunchBounds,如果指定了Lunch bounds则需要把task移动到lunch stack中,并且给该stack设置大小mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1)
2 移动task到所在的stack前台
3 处理FLAG_ACTIVITY_SINGLE_TOP的情况,重发intent ,返回START_DELIVERED_TO_TOP
4 不需要添加activity的时候,只需要带到前台,intask +NEW_TASK就是这种情况,返回START_TASK_TO_FRONT
5 mStartActivity.setTask(mInTask, null) 

private void setTaskToCurrentTopOrCreateNewTask() {
        mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
                mOptions);
        if (mDoResume) {
            mTargetStack.moveToFront("addingToTopTask");
        }
        final ActivityRecord prev = mTargetStack.topActivity();
        final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
                        mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
                        mStartActivity.info, mIntent, null, null, true);
        mStartActivity.setTask(task, null);
        mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
        if (DEBUG_TASKS) Slog.v(TAG_TASKS,
                "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
    }

这种情况是用于处理没有指定source record,并且没有指定task,也不创建新的task,这种情况下采用此函数处理,将activity启动到top task中。作者注释中说希望永远不进入这个分支,开来google在fraemwork设计的时候也不能完全确定会不会有这种情况,但是这里的代码只是为了保险起见,从这里来看我们能窥探到一些系统设计的方式。
函数很简单,也是首先计算stack,如果task不明确的情况都会通过computeStackFocus计算task, 然后设置要启动的activity为目标stack最底部的task上(如果没有会创建),之后把task移动到顶部

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值