前言:之前我们分析过Activity在AMS中的启动流程,当时也简单的说了下Activity的启动模式,现在我们更详细,更全面的解析一下它;
启动Activity的时候,Activity.startActivity()方法会将启动流程交给AMS,AMS又将启动交给ActivityStarter处理,关于Activity的启动模式,就在ActivityStarter.startActivityUnchecked()方法里;
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
//代码1
//初始化属性
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor);
//代码2
//将启动模式SingleInstance或者SingleTask转化成FLAG_ACTIVITY_NEW_TASK标签,保存在mLaunchFlags
computeLaunchingTaskFlags();
//代码3
//初始化获取当前的ActivityStack,ActivityStack是用来管理栈的
computeSourceStack();
//将收集到的flags设置给Intent
mIntent.setFlags(mLaunchFlags);
//代码4
//找到可以复用的栈或者Activity
ActivityRecord reusedActivity = getReusableIntentActivity();
final int preferredLaunchStackId =
(mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
final int preferredLaunchDisplayId =
(mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;
if (reusedActivity != null) {//成立,此时reusedActivity不为null,有可复用的Activity或者栈
if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(),
(mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
mSupervisor.showLockTaskToast();
Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
//给Settings分配栈;
//将:要启动的Activity绑定到已经找到的可复用的栈中,这样,它们就在同一个栈中了
if (mStartActivity.getTask() == null) {
mStartActivity.setTask(reusedActivity.getTask());
}
//设置栈的intent和taskAffinity和rootAffinity;
//我们可以发现,第一个被加入到栈的Activity,它的intent就是栈的intent,它的taskAffinity就是栈的affinity和rootAffinity;
if (reusedActivity.getTask().intent == null) {
reusedActivity.getTask().setIntent(mStartActivity);
}
//当intent中有FLAG_ACTIVITY_CLEAR_TOP标签,或者启动模式为SingleInstance,SingleTask时;
//也就是说,启动模式为SingleInstance,SingleTask时,就默认为有FLAG_ACTIVITY_CLEAR_TOP标签
if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| isDocumentLaunchesIntoExisting(mLaunchFlags)
|| mLaunchSingleInstance || mLaunchSingleTask) {
//找到的可复用栈
final TaskRecord task = reusedActivity.getTask();
//代码5
//查找栈中是否存在与mStartActivity相同的Activity,假设存在这个Activity,那就finish并且删除掉栈中所有位于这个Activity前面的Activity
final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
mLaunchFlags);
//上面的代码有可能把reusedActivity也从栈中给删除了,但是reusedActivity在后面的setTargetStackAndMoveToFrontIfNeeded()方法中会被用到,
//所以得给reusedActivity重新设置task
if (reusedActivity.getTask() == null) {
reusedActivity.setTask(task);
}
if (top != null) {//top != null,意味着栈中存在与mStartActivity相同的Activity
if (top.frontOfTask) {//位于栈底的Activity才有资格成为frontOfTask,此时的top,不一定位于栈底
top.getTask().setIntent(mStartActivity);
}
//调用mStartActivity的onNewIntet()方法
deliverNewIntent(top);
}
}
sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);
//代码6
//(1)mStartActivity的启动,将目标ActivityStack放到前台;
//(2)也有可能会导致从栈A跳转到栈B,那我们现在就要把栈B放到前台,以后的操作都是操作栈B的;
reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
final ActivityRecord outResult =
outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
outActivity[0] = reusedActivity;
}
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
resumeTargetStackIfNeeded();
return START_RETURN_INTENT_TO_CALLER;
}
//代码7
//处理一些特殊标签,判断新启动的Activity是否被添加进已经存在的栈
setTaskFromIntentActivity(reusedActivity);
//举个例子,这个例子会使下面的判断成立;
//栈中有A,B,C,D 4个Activity,现在再次启动B,启动模式为singleTask;
//这样,下面的判断就成立了,函数直接返回,不再往下执行
if (!mAddingToTask && mReuseTask == null) {
resumeTargetStackIfNeeded();
if (outActivity != null && outActivity.length > 0) {
outActivity[0] = reusedActivity;
}
return START_TASK_TO_FRONT;
}
}
if (mStartActivity.packageName == null) {
final ActivityStack sourceStack = mStartActivity.resultTo != null
? mStartActivity.resultTo.getStack() : null;
if (sourceStack != null) {
sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
null /* data */);
}
ActivityOptions.abort(mOptions);
return START_CLASS_NOT_FOUND;
}
final ActivityStack topStack = mSupervisor.mFocusedStack;
final ActivityRecord topFocused = topStack.topActivity();
final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
//代码8
//接下来处理SingleTop启动模式,要想SingleTop起作用,那要启动的Activity必须已经位于栈顶
final boolean dontStart = top != null && mStartActivity.resultTo == null
&& top.realActivity.equals(mStartActivity.realActivity)
&& top.userId == mStartActivity.userId
&& top.app != null && top.app.thread != null
&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| mLaunchSingleTop || mLaunchSingleTask);
if (dontStart) {//当启动模式为SINGLE_TOP时,并且要启动的Activity已经位于栈顶,那就执行onNewIntent()方法
topStack.mLastPausedActivity = null;
if (mDoResume) {
mSupervisor.resumeFocusedStackTopActivityLocked();
}
ActivityOptions.abort(mOptions);
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
return START_RETURN_INTENT_TO_CALLER;
}
//执行onNewIntent()方法
deliverNewIntent(top);
mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,
preferredLaunchDisplayId, topStack.mStackId);
return START_DELIVERED_TO_TOP;
}
boolean newTask = false;
final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
? mSourceRecord.getTask() : null;
int result = START_SUCCESS;
//接下来就开始创建栈或者绑定栈了
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
String packageName= mService.mContext.getPackageName();
if (mPerf != null) {
mStartActivity.perfActivityBoostHandler =
mPerf.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, packageName, -1, BoostFramework.Launch.BOOST_V1);
}
//代码9
//先是处理FLAG_ACTIVITY_NEW_TASK标签,含有此标签,表示可能会需要创建一个新栈
result = setTaskFromReuseOrCreateNewTask(
taskToAffiliate, preferredLaunchStackId, topStack);
} else if (mSourceRecord != null) {
//代码10
//正常绑定
//一般情况下,mSourceRecord就是调用者,如本例中的Launcher;
//但也有特殊情况,举个例子,如果启动模式为singleTask,栈中又不存在相同的Activity时,mSourceRecord就是栈顶的Activity,
result = setTaskFromSourceRecord();
} else if (mInTask != null) {
result = setTaskFromInTask();
} else {
setTaskToCurrentTopOrCreateNewTask();
}
if (result != START_SUCCESS) {
return result;
}
mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
if (mSourceRecord != null) {
mStartActivity.getTask().setTaskToReturnTo(mSourceRecord);
}
if (newTask) {
EventLog.writeEvent(
EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
mStartActivity.getTask().taskId);
}
ActivityStack.logStartActivity(
EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
mTargetStack.mLastPausedActivity = null;
sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);
//启动
mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
mOptions);
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mWindowManager.executeAppTransition();
} else {
if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityUnchecked");
}
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
} else {
mTargetStack.addRecentActivityLocked(mStartActivity);
}
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
preferredLaunchDisplayId, mTargetStack.mStackId);
return START_SUCCESS;
}
先把ActivityStarter.startActivityUnchecked()函数的代码贴出来,然后慢慢分析,假设我们要从Launcher中启动Settings:
(1)setInitialState():
private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
boolean doResume, int startFlags, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
reset();
//要启动的Activity的ActivityRecord,即Settings
mStartActivity = r;
//Settings的intent
mIntent = r.intent;
//Activity启动动画,可以忽略
mOptions = options;
mCallingUid = r.launchedFromUid;
//调用者的ActivityRecord,也就是Launcher
mSourceRecord = sourceRecord;
//下面4个属性可以忽略
mVoiceSession = voiceSession;
mVoiceInteractor = voiceInteractor;
mSourceDisplayId = getSourceDisplayId(mSourceRecord, mStartActivity);
mLaunchBounds = getOverrideBounds(r, options, inTask);
//启动模式:single_top
mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
//启动模式:single_instance
mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
//启动模式:single_task
mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
//调整mLaunchFlags;
//(1)如果此时的启动模式是single_instance或者是single_task,Intent.FLAG_ACTIVITY_NEW_DOCUMENT和FLAG_ACTIVITY_MULTIPLE_TASK标签无效
//(2)将documentLaunchMode转化成intent中相应的flag
mLaunchFlags = adjustLaunchFlagsToDocumentMode(
r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
mLaunchTaskBehind = r.mLaunchTaskBehind
&& !mLaunchSingleTask && !mLaunchSingleInstance
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
sendNewTaskResultRequestIfNeeded();
if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {//忽略
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
}
if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {//忽略
if (mLaunchTaskBehind
|| r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
}
}
//如果设置了这个标志,可以在避免用户离开当前Activity时回调onUserLeaveHint()
mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
mDoResume = doResume;//mDoResume为true
if (!doResume || !r.okToShowLocked()) {//不成立
r.delayedResume = true;
mDoResume = false;
}
//动画参数,忽略
if (mOptions != null && mOptions.getLaunchTaskId() != -1
&& mOptions.getTaskOverlay()) {
............
}
//使用这个标记启动的Activity会被自己立即终止。
mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
mInTask = inTask;//mInTask为null
if (inTask != null && !inTask.inRecents) {//不成立
mInTask = null;
}
mStartFlags = startFlags;
if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {//不成立
............
}
//Activity启动的时候不执行动画
mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
}
点评:setInitialState()方法初始化了一些属性,重要的属性有:
mStartActivity: 即Settings的ActivityRecord;
mSourceRecord: Launcher的ActivityRecord;
mLaunchSingleTop: 是否是singleTop启动模式;
mLaunchSingleInstance: singleInstance启动模式;
mLaunchSingleTask: singleTask启动模式;
(2)computeLaunchingTaskFlags():
private void computeLaunchingTaskFlags() {
if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {//不成立
............
} else {
mInTask = null;
if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
&& mSourceRecord.isFreeform()) {
mAddingToTask = true;
}
}
if (mInTask == null) {
if (mSourceRecord == null) {//不成立
if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
}
} else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
} else if (mLaunchSingleInstance || mLaunchSingleTask) {
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
}
}
}
点评:将启动模式SingleInstance或者SingleTask转化成FLAG_ACTIVITY_NEW_TASK标签,保存在mLaunchFlags;
(3)computeSourceStack():
private void computeSourceStack() {
if (mSourceRecord == null) {
mSourceStack = null;
return;
}
if (!mSourceRecord.finishing) {//成立
mSourceStack = mSourceRecord.getStack();
return;
}
.........
}
点评:初始化了mSourceStack;
(4)ActivityRecord reusedActivity = getReusableIntentActivity();
private ActivityRecord getReusableIntentActivity() {
//如果要让putIntoExistingTask为true,那么下面三种情况可满足这个条件:
//(1)当启动模式为SingleInstance;
//(2)当启动模式为singleTask;
//(3)使用了Intent.FLAG_ACTIVITY_NEW_TASK标签,并且没有使用FLAG_ACTIVITY_MULTIPLE_TASK标签
boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
(mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)//成立
|| mLaunchSingleInstance || mLaunchSingleTask;
putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;//成立
ActivityRecord intentActivity = null;
if (mOptions != null && mOptions.getLaunchTaskId() != -1) {//不成立
final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
intentActivity = task != null ? task.getTopActivity() : null;
} else if (putIntoExistingTask) {
if (mLaunchSingleInstance) {//启动模式为SingleInstance
//找到与mIntent相同ComponentName的Activity;
intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
mStartActivity.isHomeActivity());
} else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {//忽略
intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
!mLaunchSingleTask);
} else {//启动模式为singleTask或者使用了Intent.FLAG_ACTIVITY_NEW_TASK标签
//遍历所有的栈,找到rootAffinity与Settings的taskAffinity相同的栈,返回的intentActivity是栈中的第一个Activity
intentActivity = mSupervisor.findTaskLocked(mStartActivity, mSourceDisplayId);
}
}
return intentActivity;
}
点评:当启动模式为SingleInstance时:
调用mSupervisor.findActivityLocked():
ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
boolean compareIntentFilters) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
//遍历所有的ActivityStack
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
//到ActivityStack中去寻找匹配的ActivityRecord
final ActivityRecord ar = stacks.get(stackNdx)
.findActivityLocked(intent, info, compareIntentFilters);
if (ar != null) {
return ar;
}
}
}
return null;
}
看下ActivityStack是怎么寻找的:
ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
boolean compareIntentFilters) {
ComponentName cls = intent.getComponent();
if (info.targetActivity != null) {//当匹配该intent的Activity不止一个的时候,可以指定targetActivity
cls = new ComponentName(info.packageName, info.targetActivity);
}
final int userId = UserHandle.getUserId(info.applicationInfo.uid);
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
final ArrayList<ActivityRecord> activities = task.mActivities;
//遍历所有的栈
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
ActivityRecord r = activities.get(activityNdx);
if (!r.okToShowLocked()) {
continue;
}
if (!r.finishing && r.userId == userId) {
if (compareIntentFilters) {
if (r.intent.filterEquals(intent)) {
return r;
}
} else {
//找到class一样的Activity
if (r.intent.getComponent().equals(cls)) {
return r;
}
}
}
}
}
return null;
}
对于启动模式为SingleInstance的Activity来说,找到Intent中相同的Component才算是找到可以复用的Activity;
当启动模式为singleTask或者同时使用了Intent.FLAG_ACTIVITY_NEW_TASK时,调用mSupervisor.findTaskLocked(mStartActivity, mSourceDisplayId):
ActivityRecord findTaskLocked(ActivityRecord r, int displayId) {
mTmpFindTaskResult.r = null;
mTmpFindTaskResult.matchedByRootAffinity = false;
ActivityRecord affinityMatch = null;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
//遍历所有的ActivityStack
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (!checkActivityBelongsInStack(r, stack)) {
continue;
}
//由ActivityStack去寻找合适的Task,并将结果保存在mTmpFindTaskResult中
stack.findTaskLocked(r, mTmpFindTaskResult);
//mTmpFindTaskResult.r != null,表示已经查找到了可以复用的ActivityStack
if (mTmpFindTaskResult.r != null) {
if (!mTmpFindTaskResult.matchedByRootAffinity) {//不成立
............
} else if (mTmpFindTaskResult.r.getDisplayId() == displayId) {//成立
//返回满足条件的ActivityRecord,作为可以复用的Activity或者栈
affinityMatch = mTmpFindTaskResult.r;
}
}
}
}
.........
return affinityMatch;
}
看下ActivityStack的查找:
void findTaskLocked(ActivityRecord target, FindTaskResult result) {
Intent intent = target.intent;
ActivityInfo info = target.info;
ComponentName cls = intent.getComponent();
if (info.targetActivity != null) {//如果有targetActivity
cls = new ComponentName(info.packageName, info.targetActivity);
}
final int userId = UserHandle.getUserId(info.applicationInfo.uid);
boolean isDocument = intent != null & intent.isDocument();
Uri documentData = isDocument ? intent.getData() : null;
//遍历所有的栈
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
if (task.voiceSession != null) {
// We never match voice sessions; those always run independently.
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": voice session");
continue;
}
if (task.userId != userId) {
continue;
}
//得到栈中第一个没有被正在finish的ActivityRecord
final ActivityRecord r = task.getTopActivity(false /* includeOverlays */);
if (r == null || r.finishing || r.userId != userId ||
r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r);
continue;
}
//Activity的类型必须得一致
if (r.mActivityType != target.mActivityType) {
continue;
}
//taskIntent为task的intent
final Intent taskIntent = task.intent;
//affinityIntent为task的affinityIntent
final Intent affinityIntent = task.affinityIntent;
.........
if (taskIntent != null && taskIntent.getComponent() != null &&
taskIntent.getComponent().compareTo(cls) == 0 &&
Objects.equals(documentData, taskDocumentData)) {
.........
} else if (affinityIntent != null && affinityIntent.getComponent() != null &&
affinityIntent.getComponent().compareTo(cls) == 0 &&
Objects.equals(documentData, taskDocumentData)) {
.........
} else if (!isDocument && !taskIsDocument
&& result.r == null && task.rootAffinity != null) {//看这个判断
//栈名一致, 满足
if (task.rootAffinity.equals(target.taskAffinity)) {
result.r = r;
result.matchedByRootAffinity = true;
}
}
}
}
从上面的代码可以看出,可以被复用的栈必须满足以下条件:
(1)栈中有一个没有被finish的Activity;
(2)栈中第一个没有被正在finish的Activity与要启动的Activity的type必须一样;
(3)该栈的栈名必须与要启动的Activity的栈名一致;
总结:当启动模式为SingleInstance或者singleTask,又或者使用了Intent.FLAG_ACTIVITY_NEW_TASK标签时才会去寻找可以复用的Actiivty或者栈;
启动模式为SingleInstance:在所有的Activity中寻找与Intent相同Component的Activity,找到了才算是找到可以复用的Activity;
当启动模式为SingleTask,或者使用了Intent.FLAG_ACTIVITY_NEW_TASK标签:在所有的栈中寻找rootAffinity与Settings的taskAffinity相同的栈,一旦找到,就返回栈顶的Activity;
也就是,一个是找Activity,一个是找栈;
(5)接下来就是处理FLAG_ACTIVITY_CLEAR_TOP标签了:
注意:当启动模式为SingleInstance或者SingleTask时,就默认为有FLAG_ACTIVITY_CLEAR_TOP标签,也就是说,光有Intent.FLAG_ACTIVITY_NEW_TASK标签而没有FLAG_ACTIVITY_CLEAR_TOP标签,是没有cleanTop功能的;
来看下是怎么cleanTop的:
final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,mLaunchFlags);
ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
mReuseTask = true;
final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
mReuseTask = false;
return result;
}
final ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
int numActivities = mActivities.size();
for (int activityNdx = numActivities - 1; activityNdx >= 0; --activityNdx) {
ActivityRecord r = mActivities.get(activityNdx);
if (r.finishing) {
continue;
}
//如果Settings之前已经就存在于栈中了,那就finish掉栈中位于Settings前面的Acvitivty
if (r.realActivity.equals(newR.realActivity)) {
final ActivityRecord ret = r;
for (++activityNdx; activityNdx < numActivities; ++activityNdx) {
r = mActivities.get(activityNdx);
if (r.finishing) {
continue;
}
ActivityOptions opts = r.takeOptionsLocked();
if (opts != null) {
ret.updateOptionsLocked(opts);
}
if (mStack != null && mStack.finishActivityLocked(
r, Activity.RESULT_CANCELED, null, "clear-task-stack", false)) {
--activityNdx;
--numActivities;
}
}
//ActivityInfo.LAUNCH_MULTIPLE表示启动模式为标准模式;
//下面的判断如果成立,那就表示一个正常启动的Activity如果含有FLAG_ACTIVITY_CLEAR_TOP标签,那它会将自己以及位于它前面的Activity全部给finish掉
if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
&& (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
&& !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
if (!ret.finishing) {
if (mStack != null) {
mStack.finishActivityLocked(
ret, Activity.RESULT_CANCELED, null, "clear-task-top", false);
}
return null;
}
}
return ret;
}
}
return null;
}
(6)再接下来,就是将目标ActivityStack和Task移动到前台:
reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
mTargetStack = intentActivity.getStack();
mTargetStack.mLastPausedActivity = null;
final ActivityStack focusStack = mSupervisor.getFocusedStack();
//获取最近使用的Activity,也就是Launcher
ActivityRecord curTop = (focusStack == null)
? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
//获取Launcher所在的栈
final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
//Settings所在栈和Launcher所在栈不同,所以下面的判断是成立的
if (topTask != null
&& (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
&& !mAvoidMoveToFront) {//成立
//给Settings添加Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT标签
mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
mSourceStack.topActivity().getTask() == mSourceRecord.getTask())) {//成立
if (mLaunchTaskBehind && mSourceRecord != null) {
intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
}
mMovedOtherTask = true;
//如果一个Activity既存在FLAG_ACTIVITY_NEW_TASK标签又存在FLAG_ACTIVITY_CLEAR_TASK标签,那就表示它要将栈中的元素全部清楚,那也就是说,
//不需要将该Activity的所在栈移动到前台了
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);
//intentTask是之前找到的可复用的栈
final TaskRecord intentTask = intentActivity.getTask();
if (launchStack == null || launchStack == mTargetStack) {//成立
//通过insertTaskAtTop()将目标栈移动到前台
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) {
intentTask.reparent(launchStack.mStackId, ON_TOP,
REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
"launchToSide");
} else {
mTargetStack.moveTaskToFrontLocked(intentTask,
mNoAnimation, mOptions, mStartActivity.appTimeTracker,
"bringToFrontInsteadOfAdjacentLaunch");
}
mMovedToFront = true;
} else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
"reparentToDisplay");
mMovedToFront = true;
} else if (launchStack.getStackId() == StackId.HOME_STACK_ID
&& mTargetStack.getStackId() != StackId.HOME_STACK_ID) {
intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
"reparentingHome");
mMovedToFront = true;
}
mOptions = null;
intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
true /* taskSwitch */);
}
updateTaskReturnToType(intentActivity.getTask(), mLaunchFlags, focusStack);
}
}
if (!mMovedToFront && mDoResume) {//成立
//将目标ActivityStack移动前台
mTargetStack.moveToFront("intentActivityFound");
}
mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(), INVALID_STACK_ID,
DEFAULT_DISPLAY, mTargetStack.mStackId);
if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
}
return intentActivity;
}
可以看到,setTargetStackAndMoveToFrontIfNeeded()函数的作用,就是将Settings所在的ActivityStack移动到前台,并且将Settings所在栈移动到ActivityStack的顶部;
(7)处理一些特殊的标签,判断是否要将Activity添加进栈中;
setTaskFromIntentActivity(reusedActivity):
private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {//如果含有NEW_TASK和CLEAR_TASK标签
final TaskRecord task = intentActivity.getTask();
//清除栈中所有的Activity
task.performClearTaskLocked();
mReuseTask = task;
mReuseTask.setIntent(mStartActivity);
mMovedOtherTask = true;
} else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| mLaunchSingleInstance || mLaunchSingleTask) {//如果含CLEAR_TOP标签,或者启动模式为singleTask或者singleInstance
//将栈中位于mStartActivity前面的Activity全部清除
ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
mLaunchFlags);
if (top == null) {//如果top == null,那就表示栈中之前不存在mStartActivity,也就是Settings之前没有启动过
//要将Settings添加进栈中
mAddingToTask = true;
//不再将Settings放在我们以前认为的栈中
mStartActivity.setTask(null);
//现在假设Settings是由其栈的顶部启动的,那mSourceRecord就等于初始化栈中(未清除)的栈顶Activity;
//比如,刚开始的时候,栈P中的Activity从下往上排列依次有A,B,C,D;现在要启动B,B的启动模式为SingleTask,那么此时栈P中只存在A和B;
//intentActivity就是我们之前在可复用栈,也就是栈P的栈顶Activity D,所以,mSourceRecord为D;
mSourceRecord = intentActivity;
final TaskRecord task = mSourceRecord.getTask();
if (task != null && task.getStack() == null) {
mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
null /* bounds */, mLaunchFlags, mOptions);
mTargetStack.addTask(task,
!mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
}
}
} else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
//上面这个判断表示,要启动的Activity已经位于栈底;
//如果我们使用的是singleTask或者singleInstance,那此时栈中只有一个元素,就是mStartActivity自己;
//如果我们使用的是NEW_TASK标签,那此时栈中还有其他元素
if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
&& intentActivity.realActivity.equals(mStartActivity.realActivity)) {
//上面这个判断表示,如果启动模式为SingleTop,并且要启动的Activity已经位于栈顶
if (intentActivity.frontOfTask) {
intentActivity.getTask().setIntent(mStartActivity);
}
//那就不重新启动Activity了,直接调用onNewIntent
deliverNewIntent(intentActivity);
} else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
mAddingToTask = true;
mSourceRecord = intentActivity;
}
} else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
mAddingToTask = true;
mSourceRecord = intentActivity;
} else if (!intentActivity.getTask().rootWasReset) {
intentActivity.getTask().setIntent(mStartActivity);
}
}
(8)接下来就是处理SingleTop启动模式,要想SingleTop起作用,那要启动的Activity必须已经位于栈顶;
当启动模式为SingleTop,或者SingleTask,或者含有SINGLE_TOP标签,并且要启动的Activity又已经位于栈顶时,那就执行onNewIntent()方法;
(9)再接着,就是要开始创建栈或者绑定栈了;
先处理FLAG_ACTIVITY_NEW_TASK标签,含有此标签,表示可能会需要创建一个新栈;
result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, preferredLaunchStackId, topStack):
private int setTaskFromReuseOrCreateNewTask(
TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
mTargetStack = computeStackFocus(
mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
if (mReuseTask == null) {//如果不含有FLAG_ACTIVITY_CLEAR_TASK标签,那么mReuseTask == null
//创建一个栈TaskRecord,并把该TaskRecord加入到ActivityStack的顶部
final TaskRecord task = mTargetStack.createTaskRecord(
mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
//task是一个新栈
addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
if (mLaunchBounds != null) {
final int stackId = mTargetStack.mStackId;
if (StackId.resizeStackWithLaunchBounds(stackId)) {
mService.resizeStack(
stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
} else {
mStartActivity.getTask().updateOverrideConfiguration(mLaunchBounds);
}
}
} else {//mReuseTask != null,意味着含有FLAG_ACTIVITY_CLEAR_TASK标签,
// 那就表示此时的mReuseTask栈已经被清除干净了,直接将Settings加入到mReuseTask栈中;
//此后,mReuseTask中只有一个元素,就是mStartActivity,也就是Settings
addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
}
if (taskToAffiliate != null) {
mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
}
if (mSupervisor.isLockTaskModeViolation(mStartActivity.getTask())) {
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
if (!mMovedOtherTask) {
updateTaskReturnToType(mStartActivity.getTask(), mLaunchFlags,
preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
}
if (mDoResume) {
mTargetStack.moveToFront("reuseOrNewTask");
}
return START_SUCCESS;
}
private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
//如果即将启动的Settings没有栈,或者Settings的栈就是新栈,那就将Settings加入到新栈的栈顶
parent.addActivityToTop(mStartActivity);
} else {
//如果即将启动的Settings已经被绑定了栈,之前的栈和新栈不同,那就得将Settings从旧栈中移除,并移动到新栈;
//举个例子:栈A中有a,b,c三个Activity,这3个Activity从上到下依次排列,a在栈顶,他们的taskAffinity是"a";
//在Activity a中再次启动Activity b,启动模式为singleTask,不过给b指定了taskAffinity为"b",此时会出现什么情况呢?
//由于Activity b先前在栈a中,也就是与栈a进行了绑定了,现在要先将Activity b从栈a中移除,然后再将它添加到栈b中
mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
}
}
(10)来看下正常情况下的绑定:
result = setTaskFromSourceRecord();
private int setTaskFromSourceRecord() {
if (mSupervisor.isLockTaskModeViolation(mSourceRecord.getTask())) {
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
String packageName = mService.mContext.getPackageName();
if (mPerf != null) {
mStartActivity.perfActivityBoostHandler =
mPerf.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, packageName, -1, BoostFramework.Launch.BOOST_V1);
}
final TaskRecord sourceTask = mSourceRecord.getTask();
final ActivityStack sourceStack = mSourceRecord.getStack();
// We only want to allow changing stack in two cases:
// 1. 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.
// 2. If activity is not allowed on target display.
final int targetDisplayId = mTargetStack != null ? mTargetStack.mDisplayId
: sourceStack.mDisplayId;
//我们在前面已经将要启动的Activity所在栈移动到前台了,所以,sourceStack.topTask()就是要启动的Activity所在栈;
//正常情况下,sourceTask就是调用者,如本例中的Launcher,所以,sourceStack.topTask() != sourceTask;
//但也有特殊情况,如果启动模式为singleTask,栈中又不存在相同的Activity时,mSourceRecord就是栈顶的Activity,sourceStack.topTask() == sourceTask
final boolean moveStackAllowed = sourceStack.topTask() != sourceTask
|| !mStartActivity.canBeLaunchedOnDisplay(targetDisplayId);
if (moveStackAllowed) {
mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
mOptions);
// If target stack is not found now - we can't just rely on the source stack, as it may
// be not suitable. Let's check other displays.
if (mTargetStack == null && targetDisplayId != sourceStack.mDisplayId) {
// Can't use target display, lets find a stack on the source display.
mTargetStack = mService.mStackSupervisor.getValidLaunchStackOnDisplay(
sourceStack.mDisplayId, mStartActivity);
}
if (mTargetStack == null) {
// There are no suitable stacks on the target and source display(s). Look on all
// displays.
mTargetStack = mService.mStackSupervisor.getNextValidLaunchStackLocked(
mStartActivity, -1 /* currentFocus */);
}
}
if (mTargetStack == null) {//不成立
mTargetStack = sourceStack;
} else if (mTargetStack != sourceStack) {//也不成立
sourceTask.reparent(mTargetStack.mStackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT,
!ANIMATE, DEFER_RESUME, "launchToSide");
}
final TaskRecord topTask = mTargetStack.topTask();
//两个栈不同,得把相应的栈移动到前台
if (topTask != sourceTask && !mAvoidMoveToFront) {
mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, "sourceTaskToFront");
} else if (mDoResume) {
mTargetStack.moveToFront("sourceStackToFront");
}
//处理FLAG_ACTIVITY_CLEAR_TOP标签
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.getTask());
deliverNewIntent(top);
// 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.getTask();
task.moveActivityToFrontLocked(top);
top.updateOptionsLocked(mOptions);
ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
deliverNewIntent(top);
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.
//将Activity添加到相应的Task
addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
+ " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
return START_SUCCESS;
}
总结:今天是过年放假前的最后一天工作日,实在是没有心情写了,下午还得解一个bug;
关于AMS中的启动模式分析,断断续续的写了一周左右,暂时就先分析到这里了,后面会结合实际情况,再来个大的总结;
完结,撒花!