android Activity启动过程(四)startActivityUncheckedLocked
final int startActivityUncheckedLocked(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. 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(); 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 { 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; if (r.resultTo != null && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { // 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; } 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. 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, "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; } //如果从Launcher程序启动应用,launchFlags为 FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_TASK_IF_NEEDED //否则一般情况下launcheFlags为0,除非启动Activity时设置了特殊的flag //启动Activity时默认不会设置FLAG_ACTIVITY_PREVIOUS_IS_TOP //故此notTop默认情况下会是null 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. //START_FLAG_ONLY_IF_NEEDED表示只有在需要的时候才启动目标Activity。也就是说如果调用者和被启动的是一个,那么就没有必要去进行重复的步骤了 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) { //默认情况下这里的代码不会执行 ActivityRecord checkedCaller = sourceRecord; if (checkedCaller == null) { checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop); } if (!checkedCaller.realActivity.equals(r.realActivity)) { // Caller is not the same as launcher, so always needed. startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED; } } 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. /* * 如果调用者不是来自另一个activity(不是在activity中调用startActivity), * 但是给了我们用于放入新activity的一个明确的task,将执行下面代码 * * 我们往上追溯,发现inTask是 中 ActivityManagerService.startActivityAsUser()方法传递的null, * 所以if里面的不会执行 */ if (sourceRecord == null && inTask != null && inTask.stack != null) { final Intent baseIntent = inTask.getBaseIntent(); final ActivityRecord root = inTask.getRootActivity(); if (baseIntent == null) { 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. if (launchSingleInstance || launchSingleTask) { 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) { 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 = 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; } else { addingToTask = true; } reuseTask = inTask; } else { inTask = null; } //根据activity的设置,如果满足下列条件,将launchFlags置为FLAG_ACTIVITY_NEW_TASK if (inTask == null) { if (sourceRecord == null) { // This activity is not being started from another... in this // case we -always- start a new task. //如果调用者为null,将launchFlags置为 创建一个新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) { // 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) { // 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) { // 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 { sourceStack = sourceRecord.task.stack; } } else { sourceStack = null; } boolean movedHome = false; ActivityStack targetStack; intent.setFlags(launchFlags); // 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. /* * 我们尝试将新的activity放在一个现有的任务中。但是如果activity被要求是singleTask或者singleInstance, * 我们会将activity放入一个新的task中.下面的if中主要处理将目标进程置于栈顶,然后将目标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. //如果被开启的activity不是需要开启新的task,而是single instance或者singleTask, 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是否已经开启了SINGLE_INSTANCE //findTaskLocked()方法用于查找目标activity所在的task ActivityRecord intentActivity = !launchSingleInstance ? findTaskLocked(r) : findActivityLocked(intent, r.info); if (intentActivity != null) { if (isLockTaskModeViolation(intentActivity.task)) { showLockTaskToast(); Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode"); return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION; } if (r.task == null) { r.task = intentActivity.task; } targetStack = intentActivity.task.stack; targetStack.mLastPausedActivity = null; if (DEBUG_TASKS) Slog.d(TAG, "Bring to front target: " + targetStack + " from " + intentActivity); targetStack.moveToFront(); if (intentActivity.task.intent == null) { // 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); } // 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 lastStack = getLastStack(); ActivityRecord curTop = lastStack == null? null : lastStack.topRunningNonDelayedActivityLocked(notTop); if (curTop != null && (curTop.task != intentActivity.task || curTop.task != lastStack.topTask())) { r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT); if (sourceRecord == null || (sourceStack.topActivity() != null && sourceStack.topActivity().task == sourceRecord.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, r, options); 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 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) { //将task中位于目标activity上面的其他activitys清理掉 // 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; } } } } //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. //如果被启动的Activity正好是栈顶的Activity, //并且被启动的Activity启动模式是singleTop或者singleTask, //则不用将新的ActivityRecord加入到栈里 //top Activity为Launcher应用的Activity ActivityStack topStack = getFocusedStack(); ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop); //当前处于堆栈顶端的task 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; } 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. //在调用者指定的确定的task中开启目标activity 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; //继续调用目标ActivityStack的startActivityLocked()方法,这个方法没有返回值,执行完毕之后直接返回START_SUCCESS 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; }
实际场景分析
实际场景1:
应用内有两个Activity,A和B,A为第应用入口Activity,从A可跳转至B,A和B的启动模式都为standard
1)从Launcher程序第1次启动应用时的任务调度情况:
任务调度时会创建新task并将新的ActivityRecord加入这个新的task
2)然后跳转至应用内Activity时的任务调度情况:
任务调度时会将新的ActivityRecord加入已有的task
3)然后按Home键,再打开应用程序时的调度情况:
任务调度时会先找到已有的相关task,并显示栈顶的Activity
1)从Launcher程序第1次启动应用时
会创建新task并将新的ActivityRecord加入这个新的task,任务调度执行如下所示:
final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord, int startFlags, boolean doResume, Bundle options) { //... //launchFlags为FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_TASK_IF_NEEDED int launchFlags = intent.getFlags(); //... //没设置FLAG_ACTIVITY_PREVIOUS_IS_TOP,故此notTop为null ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null; //startFlags未设置ActivityManager.START_FLAG_ONLY_IF_NEEDED //... //sourceRecord为Launcher应用的Activity launcher应用activity的启动模式为singleTask // 故此下面的3个条件分支的内容都不会执行 if (sourceRecord == null) { //... } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { //... } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) { //... } //... //r.resultTo不为null, launchFlags设置了FLAG_ACTIVITY_NEW_TASK,需要将r.resultTo置为null if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { //... r.resultTo = null; } boolean addingToTask = false; boolean movedHome = false; TaskRecord reuseTask = null; //因为launchFlags为FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_TASK_IF_NEEDED //故此下面的条件会满足, 也就是说只要从Launcher程序启动应用,下面这个条件肯定会满足 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 && (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0) || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { //... if (r.resultTo == null) { //因为应用被第一次启动,故此找不到相关task,taskTop则为null ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE ? findTaskLocked(intent, r.info) : findActivityLocked(intent, r.info); if (taskTop != null) { //... 这里面的内容不会执行 } } } //... //r.packageName != null if (r.packageName != null) { //如果被启动的Activity正好是栈顶的Activity, //并且被启动的Activity启动模式是singleTop或者singleTask, //则不用将新的ActivityRecord加入到栈里 //top Activity为Launcher应用的Activity ActivityRecord top = topRunningNonDelayedActivityLocked(notTop); if (top != null && r.resultTo == null) { //top.realActivity.equals(r.realActivity)不满足 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) { //... 这里的代码不会被执行 } } } else { //... } boolean newTask = false; boolean keepCurTransition = false; // 此时 r.resultTo为null addingToTask为false launchFlags设置了FLAG_ACTIVITY_NEW_TASK if (r.resultTo == null && !addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { if (reuseTask == null) { // todo: should do better management of integers. mService.mCurTask++; if (mService.mCurTask <= 0) { mService.mCurTask = 1; } //创建新task r.setTask(new TaskRecord(mService.mCurTask, r.info, intent), null, true); if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " + r.task); } else { //...这里的代码会执行 } newTask = true; if (!movedHome) { moveHomeToFrontFromLaunchLocked(launchFlags); } } else if (sourceRecord != null) { //... 这里的代码不会被执行 } else { //...这里的代码不会被执行 } //... startActivityLocked(r, newTask, doResume, keepCurTransition, options); return ActivityManager.START_SUCCESS; }
2)跳转至应用内Activity时
会将新的ActivityRecord加入已有的task,任务调度执行如下所示:
final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord, int startFlags, boolean doResume, Bundle options) { //此时launchFlags为0 int launchFlags = intent.getFlags(); //notTop为null ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null; //startFlags未设置ActivityManager.START_FLAG_ONLY_IF_NEEDED //... if (sourceRecord == null) { //...这里的代码不会被执行 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { //...这里的代码不会被执行 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) { //...这里的代码不会被执行 } //r.resultTo != null 但是launchFlags未设置FLAG_ACTIVITY_NEW_TASK if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { //... 这里的代码不执行 } boolean addingToTask = false; boolean movedHome = false; TaskRecord reuseTask = null; //launchFlags为0 r的启动模式为standard 故此下面的逻辑都不会执行 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 && (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0) || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { //... 这里的代码不执行 } //... if (r.packageName != null) { //top 是ActivityA 的ActivityRecord, //但是被启动的Activity和top不是同一个Activity ActivityRecord top = topRunningNonDelayedActivityLocked(notTop); if (top != null && r.resultTo == null) { if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) { //...这里的代码不执行 } } } else { //...这里的代码不执行 } boolean newTask = false; boolean keepCurTransition = false; //此时 r.resultTo !=null sourceRecord != null addingToTask=false if (r.resultTo == null && !addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { //...这里的代码不执行 } else if (sourceRecord != null) { if (!addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) { //... 这里的代码不执行 } else if (!addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) { //... 这里的代码不执行 } //添加到现有的task r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false); //... } else { //... 这里的代码不执行 } //... return ActivityManager.START_SUCCESS; }
3)然后按Home键,再打开应用程序
此时会先找到已有的相关task,并显示栈顶的Activity,任务调度执行如下所示:
final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord, int startFlags, boolean doResume, Bundle options) { //... //launchFlags为FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_TASK_IF_NEEDED int launchFlags = intent.getFlags(); //notTop为null ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null; //startFlags未设置ActivityManager.START_FLAG_ONLY_IF_NEEDED //... if (sourceRecord == null) { //...这里的代码不会被执行 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { //...这里的代码不会被执行 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) { //...这里的代码不会被执行 } //此时 r.resultTo != null launchFlags设置了FLAG_ACTIVITY_NEW_TASK if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { //... r.resultTo = null; } boolean addingToTask = false; boolean movedHome = false; TaskRecord reuseTask = null; //此时launchFlags设置了FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_TASK_IF_NEEDED if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 && (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0) || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { //此时 r.resultTo == null if (r.resultTo == null) { //此时已有相关task,并且task 栈的栈顶是Activity B的ActivityRecord //故此taskTop为Activity B的ActivityRecord ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE ? findTaskLocked(intent, r.info) : findActivityLocked(intent, r.info); if (taskTop != null) { //... // 此时curTop是Launcher应用的Activity的ActivityRecord ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop); if (curTop != null && curTop.task != taskTop.task) { r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT); //此时Launcher应用的task在栈顶,故此callerAtFront为true, //此时会把被启动的应用的task移至栈顶 boolean callerAtFront = sourceRecord == null || curTop.task == sourceRecord.task; if (callerAtFront) { // We really do want to push this one into the // user's face, right now. movedHome = true; moveHomeToFrontFromLaunchLocked(launchFlags); moveTaskToFrontLocked(taskTop.task, r, options); options = null; } } //此时launchFlags设置了FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_TASK_IF_NEEDED //此时需要重置task 重置完后 taskTop为ActivityB的ActivityRecord if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { taskTop = resetTaskIfNeededLocked(taskTop, r); } //startFlags为0 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) { //... 这些代码都不会被执行 } //根据launchFlags和被启动的activity的信息 设置resueTask addingTask变量的值 //没设置 Intent.FLAG_ACTIVITY_CLEAR_TASK if ((launchFlags & (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) { //... 这些代码都不会被执行 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { //... 这些代码都不会被执行 } else if (r.realActivity.equals(taskTop.task.realActivity)) { //... 这些代码都不会被执行 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) { //因为从Launcher程序启动时launchFlags设置了FLAG_ACTIVITY_RESET_TASK_IF_NEEDED //所以不会进入该分支 //... 这些代码都不会被执行 } else if (!taskTop.task.rootWasReset) { //... 这些代码都不会被执行 } //此时addingToTask为false,reuseTask为null,故此显示栈顶Actvity即可 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) { resumeTopActivityLocked(null, options); } else { ActivityOptions.abort(options); } return ActivityManager.START_TASK_TO_FRONT; } } } } //... 以下代码都不会被执行 }
实际场景2:
应用内有两个Activity,A和B,A为第应用入口Activity,从A可跳转至B,A的启动模式都为standard,B的启动模式为singleTop
此时已从Launchenr程序打开应用,启动了Actvity A,再从A跳转至B,此时的任务调度情况:
此时不会创建新的Task,而是将B的ActivityRecord加入到A所在的task里
任务调度执行如下所示:
final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord, int startFlags, boolean doResume, Bundle options) { //... //此时launcheFlags为0 int launchFlags = intent.getFlags(); //notTop为null ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null; //默认情况下startFlags不会设置START_FLAG_ONLY_IF_NEEDED if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) { //...这里的代码不会执行 } //r.launchMode = ActivityInfo.LAUNCH_SINGLE_TASK if (sourceRecord == null) { //这里的代码不会执行 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { //这里的代码不会执行 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) { launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; } //此时r.resultTo!=null launchFlags设置了Intent.FLAG_ACTIVITY_NEW_TASK if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { //... r.resultTo = null; } //addingToTask如果为true表示正在添加至某个task,后续需要将r添加至sourceRecord所在的task boolean addingToTask = false; //movedHome表示是否移动home task boolean movedHome = false; TaskRecord reuseTask = null; if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 && (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0) || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { //此时 r.resultTo = null if (r.resultTo == null) { //此时找到的taskTop是Activity A的ActivityRecord, //因为Actvity B和A的ActivityRecord所在的Task是相关的 ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE ? findTaskLocked(intent, r.info) : findActivityLocked(intent, r.info); //找到了相关task if (taskTop != null) { //重设task的intent if (taskTop.task.intent == null) { //... } //此时找到的task已在栈顶 ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop); if (curTop != null && curTop.task != taskTop.task) { //... 这里的代码不会执行 } //launchFlags为0 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { taskTop = resetTaskIfNeededLocked(taskTop, r); } //... 一般情况下startFlags 不会设置 START_FLAG_ONLY_IF_NEEDED if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) { //... } // ==================== begin // launchFlags此时为0 if ((launchFlags & (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) { //...这里的代码不执行 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { // r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK // 故此会进入该分支 //因为B还从未启动,故此得到的top为null ActivityRecord top = performClearTaskLocked( taskTop.task.taskId, r, launchFlags); if (top != null) { //...这里的代码不执行 } else { addingToTask = true; sourceRecord = taskTop; } } else if (r.realActivity.equals(taskTop.task.realActivity)) { //...这里的代码不执行 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) { //...这里的代码不执行 } else if (!taskTop.task.rootWasReset) { //...这里的代码不执行 } // ==================== end // 此时 addingToTask为true if (!addingToTask && reuseTask == null) { //...这里的代码不执行 } } } } //... if (r.packageName != null) { ActivityRecord top = topRunningNonDelayedActivityLocked(notTop); if (top != null && r.resultTo == null) { //此时task还没有B的ActivityRecord,故此不会进入下述分支 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) { //...这里的代码不执行 } } } else { //...这里的代码不执行 } boolean newTask = false; boolean keepCurTransition = false; // 此时 r.resultTo == null addingToTask为true sourceRecord != null if (r.resultTo == null && !addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { //...这里的代码不执行 } else if (sourceRecord != null) { if (!addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) { //...这里的代码不执行 } else if (!addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) { //...这里的代码不执行 } //将B的ActivityRecord加入A的ActivityRecord所在的Task里 r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false); //... } else { //...这里的代码不执行 } //... startActivityLocked(r, newTask, doResume, keepCurTransition, options); return ActivityManager.START_SUCCESS; }
总结
从上面的分析可以看出来,Activity和Task的调度算法非常复杂,需结合实际场景才好分析,只有这样才知道是否需要新建Task,还是将新的ActivityRecord加入到已有的Task里,不过我们如果能理解启动模式的一些特点,对理解调度算法会有很大帮助。
大家可以结合下述场景分析调度算法:
1.从通知栏启动Activity:
假设应用有Activity A ,Activity A已启动,
此时发了一个通知,该通知用于启动Activity A,启动Activity A时不加任何特殊flag
点击通知,针对以下情况对任务调度情况进行分析:
-
Activity A的启动模式为standard
-
Activity A的启动模式为singleTop
-
Activity A的启动模式为singleTask
-
Activity A的启动模式为singleInstance
2.跨应用跳转Activity
假设应用app1有一个Activity A,另一个应用app2有一个Activity B
Activity A可跳转至Activity B
因为Activity A和Actiivty B在不同应用,所以Activity的taskffinity必然不同
现在Activity A已启动,跳转至Activity B,
针对以下4种情况分析跳转之后的Activity Task情况
-
Activity B的启动模式为standard
-
Activity B的启动模式为singleTop
-
Activity B的启动模式为singleTask
-
Activity B的启动模式为singleInstance
如果大家对上述场景分析有兴趣的话,可以在评论里一起探讨结果。