之前一篇文章分析了Android Activity啟動(dòng)過程源碼 這里單獨(dú)拿出來(lái)一篇文章分析Activity 啟動(dòng)模式的源碼
我們知道Activity的start是走到Instrumentation的execStartActivity方法中盏阶,而這里是調(diào)用了ActivityManagerNative的getDefault方法 來(lái)獲得一個(gè)ActivityManagerService(以下簡(jiǎn)稱AMS)的遠(yuǎn)程代理對(duì)象,要走到AMS的startActivity方法。
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, null, options);
checkStartActivityResult(result, intent);
這里先解釋一下startActivity方法里的一些參數(shù)
參數(shù) | 作用 |
---|---|
whoThread | IApplicationThread的binder對(duì)象 用于AMS進(jìn)行進(jìn)程間通信 |
who | 上下文對(duì)象 其實(shí)就是Activity |
intent | 目標(biāo)intent |
intent.resolveTypeIfneed | 若沒有在Manifest文件里面注明Activity的mime類型,返回null |
token | Binder對(duì)象 通過它可以獲得Activity的相關(guān)信息 后邊會(huì)保存到sourceRecord這個(gè)對(duì)象里面 |
target | 我們調(diào)用的Activity |
requestCode | 若沒有設(shè)置結(jié)果就是小于0 |
0 | flags |
ProfilerInfo | null |
options | 是一個(gè)bunder對(duì)象肩祥,記錄用intent傳遞的信息 |
這里對(duì)應(yīng)著AMS 中startactivity的參數(shù)
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,
UserHandle.getCallingUserId());
}
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
false, ALLOW_FULL_ONLY, "startActivity", null);
// TODO: Switch to user app stacks here.
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, options, userId, null, null);
}
然后會(huì)調(diào)用ActivityStackSupervisor的startActivityMayWait方法
而ActivityStackSupervisor 就是專門管理activity的堆棧的類
這里會(huì)先解析我們的intent來(lái)獲取信息佑惠,通過調(diào)用函數(shù)resoleActivity方法獲取ActivityInfo,這里主要是activity在AndroidManifest.xml里的信息
再往下看葛假,進(jìn)入到startActivityLocked 方法中
另提一下activity 在 AMS 中的形式是 ActivityRecord,task 在 AMS 中的形式為TaskRecord,進(jìn)程在 AMS 中的管理形式為 ProcessRecord
我們發(fā)現(xiàn)這里有兩個(gè)ActivityRecord對(duì)象 有sourceRecord 和resultRecord
sourceRecord 代表的是最開始的activity
這就是通過resultTo這個(gè)binder對(duì)象獲得Mainactivity的相關(guān)信息然后保存到這個(gè)對(duì)象中
resultRecord 代表的是接受啟動(dòng)結(jié)果的Activity
因?yàn)閞equestcode==-1 所以這里resultRecord==null
final int launchFlags = intent.getFlags();
這里獲取Intent的啟動(dòng)Flag 就是我們?cè)贗ntent.setFlag里面設(shè)置的標(biāo)志
這個(gè)函數(shù)的主要作用就是處理sourceRecord和resultRecord兩個(gè)對(duì)象
在這里sourceRecord和resultRecord指向的應(yīng)該是同一個(gè)activity
然后調(diào)用startActivityUncheckedLocked來(lái)處理本次的啟動(dòng)Activity的請(qǐng)求
從這里我們可以看到 獲取了activity的launchModel 情竹,也就是對(duì)launchModel的判斷處理應(yīng)該是在這里
這里先判斷是否FLAG_ACTIVITY_NEW_DOCUMENT藐不,這個(gè)平時(shí)用的比較少,在android5.0上主要是決定你的task和activity是如何展現(xiàn)在overview screen 中的秦效,詳細(xì)請(qǐng)看Android 5.0 Overview Screen--總覽畫面
再往下看
startFlags == 0 所以此時(shí)不會(huì)進(jìn)入這個(gè)判斷雏蛮,沒有設(shè)置這個(gè)FLAG_ACTIVITY_PREVIOUS_IS_TOP,所以我們的notTop==null
接著 系統(tǒng)默認(rèn)addingToTask= false 默認(rèn)是開啟新的Task阱州,從后面的判斷也可以看出來(lái)
之前說過 sourceRecord就是最開始的activity 所以它不會(huì)為null挑秉,這樣就到了else 中 inTask = null;
在這里判斷了啟動(dòng)模式苔货,判斷當(dāng)前activity的啟動(dòng)模式和要啟動(dòng)的activity的啟動(dòng)模式犀概,根據(jù)相應(yīng)的啟動(dòng)模式設(shè)置launchFlags
這里目的是判斷啟動(dòng)的activity是否在堆棧里存在,如果存在就直接在進(jìn)行相應(yīng)的操作
在文章開頭 resultRecord 默認(rèn)為null而且requestCode假如沒有設(shè)置的話夜惭,requestCode小于0姻灶,所以resultRecord沒有被賦值,所以我們構(gòu)造ActivityRecord 時(shí)傳入的是null滥嘴,也就是可以進(jìn)入這個(gè)if判斷里
再往里看
這里會(huì)判斷啟動(dòng)的activity是否是SingleInstance木蹬,根據(jù)此進(jìn)入不同的方法,目的是找到activity若皱,如果有就返回镊叁,如果沒有就返回null,先來(lái)看findTaskLocked方法
stack里的findTaskLocked方法比較長(zhǎng)走触,頂部activity晦譬,如果沒有就返回null,從注釋上來(lái)看就是返回堆棧里的activity,簡(jiǎn)單說一下就是返回發(fā)起請(qǐng)求的activity互广,也是這個(gè)函數(shù)返回的activity
/**
* Returns the top activity in any existing task matching the given
* Intent. Returns null if no such task is found.
*/
ActivityRecord findTaskLocked(ActivityRecord target) {
Intent intent = target.intent;
ActivityInfo info = target.info;
ComponentName cls = intent.getComponent();
if (info.targetActivity != null) {
cls = new ComponentName(info.packageName, info.targetActivity);
}
final int userId = UserHandle.getUserId(info.applicationInfo.uid);
boolean isDocument = intent != null & intent.isDocument();
// If documentData is non-null then it must match the existing task data.
Uri documentData = isDocument ? intent.getData() : null;
if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + target + " in " + this);
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, "Skipping " + task + ": voice session");
continue;
}
if (task.userId != userId) {
// Looking for a different task.
if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": different user");
continue;
}
final ActivityRecord r = task.getTopActivity();
if (r == null || r.finishing || r.userId != userId ||
r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": mismatch root " + r);
continue;
}
final Intent taskIntent = task.intent;
final Intent affinityIntent = task.affinityIntent;
final boolean taskIsDocument;
final Uri taskDocumentData;
if (taskIntent != null && taskIntent.isDocument()) {
taskIsDocument = true;
taskDocumentData = taskIntent.getData();
} else if (affinityIntent != null && affinityIntent.isDocument()) {
taskIsDocument = true;
taskDocumentData = affinityIntent.getData();
} else {
taskIsDocument = false;
taskDocumentData = null;
}
if (DEBUG_TASKS) Slog.d(TAG, "Comparing existing cls="
+ taskIntent.getComponent().flattenToShortString()
+ "/aff=" + r.task.rootAffinity + " to new cls="
+ intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
if (!isDocument && !taskIsDocument && task.rootAffinity != null) {
if (task.rootAffinity.equals(target.taskAffinity)) {
if (DEBUG_TASKS) Slog.d(TAG, "Found matching affinity!");
return r;
}
} else if (taskIntent != null && taskIntent.getComponent() != null &&
taskIntent.getComponent().compareTo(cls) == 0 &&
Objects.equals(documentData, taskDocumentData)) {
if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
//dump();
if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
+ r.intent);
return r;
} else if (affinityIntent != null && affinityIntent.getComponent() != null &&
affinityIntent.getComponent().compareTo(cls) == 0 &&
Objects.equals(documentData, taskDocumentData)) {
if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
//dump();
if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
+ r.intent);
return r;
} else if (DEBUG_TASKS) {
Slog.d(TAG, "Not a match: " + task);
}
}
return null;
}
這里簡(jiǎn)單說一下敛腌,先是從mTaskHistory中遍歷得到一個(gè)任務(wù)Task,并根據(jù)userid找到當(dāng)前的task 惫皱,找到這個(gè)任務(wù)的頂部activity像樊,并且保證它啟動(dòng)模式不是singleInstance,都滿足了返回以下條件的activity
再回到剛才的方法往下看
這里先去activitystack里的moveToFront()方法
// If the caller has requested that the target task be
// reset, then do so.
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.
if (doResume) {
resumeTopActivitiesLocked(targetStack, null, options);
} else {
ActivityOptions.abort(options);
}
return ActivityManager.START_RETURN_INTENT_TO_CALLER;
}
if ((launchFlags &
(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
== (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.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...
reuseTask = intentActivity.task;
reuseTask.performClearTaskLocked();
reuseTask.setIntent(r);
} else if ((launchFlags&Intent.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.
ActivityRecord top =
intentActivity.task.performClearTaskLocked(r, launchFlags);
if (top != null) {
if (top.frontOfTask) {
// 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);
} 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.
addingToTask = true;
// Now pretend like this activity is being started
// by the top of its task, so it is put in the
// right place.
sourceRecord = intentActivity;
}
} 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.
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);
} 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.
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.
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.
intentActivity.task.setIntent(r);
}
if (!addingToTask && reuseTask == null) {
// 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);
} else {
ActivityOptions.abort(options);
}
return ActivityManager.START_TASK_TO_FRONT;
}
這里主要看
這里走到了ActivityStack的performClearTaskLocked方法里
/**
* Perform clear operation as requested by
* {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
* stack to the given task, then look for
* an instance of that activity in the stack and, if found, finish all
* activities on top of it and return the instance.
*
* @param newR Description of the new activity being started.
* @return Returns the old activity that should be continued to be used,
* or null if none was found.
*/
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;
}
if (r.realActivity.equals(newR.realActivity)) {
// Here it is! Now finish everything in front...
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 (stack.finishActivityLocked(r, Activity.RESULT_CANCELED, null, "clear",
false)) {
--activityNdx;
--numActivities;
}
}
// Finally, if this is a normal launch mode (that is, not
// expecting onNewIntent()), then we will finish the current
// instance of the activity so a new fresh one can be started.
if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
&& (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
if (!ret.finishing) {
stack.finishActivityLocked(ret, Activity.RESULT_CANCELED, null,
"clear", false);
return null;
}
}
return ret;
}
}
return null;
}
這里就是根據(jù)ID找到等于參數(shù)taskId的任務(wù)旅敷,然后在這個(gè)任務(wù)中查找是否已經(jīng)存在即將要啟動(dòng)的Activity的實(shí)例生棍,如果存在,就會(huì)把這個(gè)Actvity實(shí)例上面直到任務(wù)堆棧頂端的Activity通過調(diào)用finishActivityLocked函數(shù)將它們結(jié)束掉媳谁。
在這里便引出了manifest文件中<activity>的一個(gè)重要屬性涂滴,taskAffinity。在官方文檔中可以得到關(guān)于taskAffinity的以下信息
- taskAffinity表示當(dāng)前activity具有親和力的一個(gè)任務(wù)(原句為The task that the activity has an affinity for.)晴音,大致可以這樣理解柔纵,這個(gè) taskAffinity表示一個(gè)任務(wù),這個(gè)任務(wù)就是當(dāng)前activity所在的任務(wù)锤躁。
在概念上搁料,具有相同的affinity的activity(即設(shè)置了相同taskAffinity屬性的activity)屬于同一個(gè)任務(wù)。 - 一個(gè)任務(wù)的affinity決定于這個(gè)任務(wù)的根activity(root activity)的taskAffinity系羞。
- 這個(gè)屬性決定兩件事:當(dāng)activity被re-parent時(shí)加缘,它可以被re-paren哪個(gè)任務(wù)中;當(dāng)activity以FLAG_ACTIVITY_NEW_TASK標(biāo)志啟動(dòng)時(shí)觉啊,它會(huì)被啟動(dòng)到哪個(gè)任務(wù)中拣宏。(這個(gè)比較 難以理解,請(qǐng)結(jié)合<activity>中的屬性allowTaskReparenting和Intent中的標(biāo)志 FLAG_ACTIVITY_NEW_TASK加以理解)
- 默認(rèn)情況下杠人,一個(gè)應(yīng)用中的所有activity具有相同的taskAffinity勋乾,即應(yīng)用程序的包名。我們可以通過設(shè)置不同的taskAffinity屬性給應(yīng)用中的activity分組嗡善,也可以把不同的 應(yīng)用中的activity的taskAffinity設(shè)置成相同的值辑莫。
為一個(gè)activity的taskAffinity設(shè)置一個(gè)空字符串,表明這個(gè)activity不屬于任何task罩引。
回到前面的startActivityUncheckedLocked函數(shù)中各吨,這里的變量top就為null了,于是執(zhí)行下面的else語(yǔ)句
所以 此時(shí)將addintToTask=true 并且sourceRecord = 我們的activity袁铐,再往下看
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.
ActivityStack topStack = getFocusedStack();
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);
return ActivityManager.START_DELIVERED_TO_TOP;
}
}
}
}
} else {
if (r.resultTo != 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;
}
根據(jù)注釋我們能看出這個(gè)方法是檢查當(dāng)前任務(wù)的頂端是否是我們要啟動(dòng)的activity揭蜒,接著往下看横浑,便是啟動(dòng)activity
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) {
if (isLockTaskModeViolation(reuseTask)) {
Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
newTask = true;
targetStack = adjustStackFocus(r, newTask);
if (!launchTaskBehind) {
targetStack.moveToFront();
}
if (reuseTask == null) {
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, "Starting new activity " + r + " in new task " +
r.task);
} else {
r.setTask(reuseTask, taskToAffiliate);
}
if (!movedHome) {
if ((launchFlags &
(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
== (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.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) {
final TaskRecord sourceTask = sourceRecord.task;
if (isLockTaskModeViolation(sourceTask)) {
Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
targetStack = sourceTask.stack;
targetStack.moveToFront();
final TaskRecord topTask = targetStack.topTask();
if (topTask != sourceTask) {
targetStack.moveTaskToFrontLocked(sourceTask, r, options);
} else {
mWindowManager.moveTaskToTop(topTask.taskId);
}
if (!addingToTask && (launchFlags&Intent.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(r, launchFlags);
keepCurTransition = true;
if (top != null) {
ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
top.deliverNewIntentLocked(callingUid, r.intent);
// 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) {
// 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);
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.
r.setTask(sourceTask, null);
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
+ " in existing task " + r.task + " from source " + sourceRecord);
} else if (inTask != null) {
// The calling is asking that the new activity be started in an explicit
// task it has provided to us.
if (isLockTaskModeViolation(inTask)) {
Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
targetStack = inTask.stack;
targetStack.moveTaskToFrontLocked(inTask, r, options);
targetStack.moveToFront();
mWindowManager.moveTaskToTop(inTask.taskId);
// 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) {
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);
return ActivityManager.START_DELIVERED_TO_TOP;
}
}
if (!addingToTask) {
// 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;
}
r.setTask(inTask, null);
if (DEBUG_TASKS) Slog.v(TAG, "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.
targetStack = adjustStackFocus(r, newTask);
targetStack.moveToFront();
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, "Starting new activity " + r
+ " in new guessed " + r.task);
}
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;
targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
if (!launchTaskBehind) {
// Don't set focus on an activity that's going to the back.
mService.setFocusedActivityLocked(r);
}
return ActivityManager.START_SUCCESS;
}
首先將newTask變量初始化為false,表示不要在新的任務(wù)中啟動(dòng)Activity屉更。由于前面的已經(jīng)把a(bǔ)ddingToTask設(shè)置為true徙融,因此,這里會(huì)執(zhí)行中間的else if語(yǔ)句瑰谜,即這里會(huì)把r.task設(shè)置為sourceRecord.task欺冀,即把即將啟動(dòng)的Activity放在原Activity所在的任務(wù)中啟動(dòng)。最后萨脑,就是調(diào)用startActivityLocked函數(shù)繼續(xù)進(jìn)行啟動(dòng)Activity的操作了