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移动到顶部