概述
之前分析过很多次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)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复