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
如果大家对上述场景分析有兴趣的话,可以在评论里一起探讨结果。
android Activity启动过程(四)startActivityUncheckedLocked的更多相关文章
- android Activity启动过程(一)从startActivty开始说起
从启动startActivity开始说起 MainActivity.startActivity() Activity.startActivity() Activity.startActivityFor ...
- [Android]Activity启动过程
Android系统启动加载流程: 参考图 Linux内核加载完毕 启动init进程 init进程fork出zygote进程 zygote进程在ZygoteInit.main()中进行初始化的时候for ...
- android Activity启动过程(三)从栈顶Activity的onPause到启动activityon的Resume过程
ActivityStack.startPausingLocked() IApplicationThread.schudulePauseActivity() ActivityThread.sendMes ...
- android Activity启动过程(二)从ActivityManagerService的startActivity到栈顶Activity的onPause过程
ActivityManagerService.startActivity() ActvityiManagerService.startActivityAsUser() ActivityStackSup ...
- Android深入四大组件(四)Android8.0 根Activity启动过程(前篇)
前言 在几个月前我写了Android深入四大组件(一)应用程序启动过程(前篇)和Android深入四大组件(一)应用程序启动过程(后篇)这两篇文章,它们都是基于Android 7.0,当我开始阅读An ...
- Android深入四大组件(五)Android8.0 根Activity启动过程(后篇)
前言 在几个月前我写了Android深入四大组件(一)应用程序启动过程(前篇)和Android深入四大组件(一)应用程序启动过程(后篇)这两篇文章,它们都是基于Android 7.0,当我开始阅读An ...
- Android 面试必备 - 系统、App、Activity 启动过程“一锅端”
Android 系统启动过程 从系统层看: linux 系统层 Android系统服务层 Zygote 从开机启动到Home Launcher: 启动bootloader (小程序:初始化硬件) 加载 ...
- Android应用程序的Activity启动过程简要介绍和学习计划
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6685853 在Android系统中,Activ ...
- Android世界第一个activity启动过程
Android世界第一个activity启动过程 第一次使用Markdown,感觉不错. Android系统从按下开机键一直到launcher的出现,是一个如何的过程,中间都做出了什么操作呢.带着这些 ...
随机推荐
- Socket编程--TCP服务端注意事项
僵尸进程处理 僵尸进程和孤儿进程: 基本概念:我们知道在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程.子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预 ...
- DropDownList 控件的SelectedIndexChanged事件触发不了
先看看网友的问题: 根据Asp.NET的机制,在html markup有写DropDownList控件与动态加载的控件有点不一样.如果把DropDownList控件写在html markup,即.as ...
- “网易大数据讲堂第一期:数说”直播活动资料:课程回放收看及PPT下载
欢迎访问网易云社区,了解更多网易技术产品运营经验. "网易大数据讲堂第一期:数说"直播活动昨晚顺利举行.感谢各位"数"友的支持和参与. 本次活动PPT可点击这里 ...
- gRPC官方文档(概览)
文章来自gRPC 官方文档中文版 概览 开始 欢迎进入 gRPC 的开发文档,gRPC 一开始由 google 开发,是一款语言中立.平台中立.开源的远程过程调用(RPC)系统. 本文档通过快速概述和 ...
- ubuntu - 安装sqoop
解析过程 参考:https://www.cnblogs.com/qingyunzong/p/8807252.html#_label4 一.下载 二.解压到指定目录 三.配置sqoop环境变量并生效 四 ...
- AI进阶之路
一.方法论 二.发展趋势 三.入门查看 1. https://hongyuxie.github.io/MyResume_CN/ 上班后大家还刷算法题吗 编程面试的 10 大算法概念汇总 技术面试宝典: ...
- Python从小看到大
最近迷恋上了python,因为一个朋友说python这种脚本语言很厉害,可以做网络攻防的时候用,但是由于自己太笨了,不得不从基础教程学起. 行左右.你可能会问为什么这么少的代码量,这门语言没有火起来, ...
- ajax遍历数据生成下拉框
<script type="text/javascript"> function GetEQIDList(ModuleID) { $. ...
- rest framework认证组件和django自带csrf组件区别详解
使用 Django 中的 csrf 处理 Django中有一个django.middleware.csrf.CsrfViewMiddleware中间件提供了全局的csrf检查.它的原理是在<fo ...
- 剑指offer —— 从尾到头打印链表
1.问题:输入一个链表,从尾到头打印链表每个节点的值. /** * public class ListNode { * int val; * ListNode next = null; * * Lis ...