publicvoidstartActivity(Intent intent, @Nullable Bundle options){ if (options != null) { startActivityForResult(intent, -1, options); } else { // Note we want to go through this call for compatibility with // applications that may have overridden the method. startActivityForResult(intent, -1); } }
publicvoidstartActivityForResult(@RequiresPermission Intent intent, int requestCode){ startActivityForResult(intent, requestCode, null); }
publicvoidstartActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options){ if (mParent == null) { options = transferSpringboardActivityOptions(options); // 关键代码 Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); // if (ar != null) { mMainThread.sendActivityResult( mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); } if (requestCode >= 0) { mStartedActivity = true; }
cancelInputsAndStartExitTransition(options); // TODO Consider clearing/flushing other event sources and events for child windows. } else { if (options != null) { mParent.startActivityFromChild(this, intent, requestCode, options); } else { // Note we want to go through this method for compatibility with // existing applications that may have overridden it. mParent.startActivityFromChild(this, intent, requestCode); } } }
publicvoidstartActivityFromChild(@NonNull Activity child, @RequiresPermission Intent intent, int requestCode, @Nullable Bundle options){ options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, child, intent, requestCode, options); if (ar != null) { mMainThread.sendActivityResult( mToken, child.mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); } cancelInputsAndStartExitTransition(options); }
// We'll invoke onUserLeaving before onPause only if the launching // activity did not explicitly state that this is an automated launch. mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
if (mInTask == null) { if (mSourceRecord == null) { // This activity is not being started from another... in this // case we -always- start a new task. if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) { Slog.w(TAG, "startActivity called from non-Activity context; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent); mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; } } elseif (mSourceRecord.launchMode == 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. mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; } elseif (mLaunchSingleInstance || mLaunchSingleTask) { // The activity being started is a single instance... it always // gets launched into its own task. mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; } }
privatevoidcomputeSourceStack(){ if (mSourceRecord == null) { mSourceStack = null; return; } if (!mSourceRecord.finishing) { mSourceStack = mSourceRecord.getStack(); return; }
// 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 ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) { Slog.w(TAG, "startActivity called from finishing " + mSourceRecord + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent); mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; mNewTaskInfo = mSourceRecord.info;
// It is not guaranteed that the source record will have a task associated with it. For, // example, if this method is being called for processing a pending activity launch, it // is possible that the activity has been removed from the task after the launch was // enqueued. final TaskRecord sourceTask = mSourceRecord.getTask(); mNewTaskIntent = sourceTask != null ? sourceTask.intent : null; } mSourceRecord = null; mSourceStack = null; }
/** * Decide whether the new activity should be inserted into an existing task. Returns null * if not or an ActivityRecord with the task into which the new activity should be added. */ private ActivityRecord getReusableIntentActivity(){ // 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. boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 && (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0) || mLaunchSingleInstance || mLaunchSingleTask; // 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. putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null; ActivityRecord intentActivity = null; if (mOptions != null && mOptions.getLaunchTaskId() != -1) { final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId()); intentActivity = task != null ? task.getTopActivity() : null; } elseif (putIntoExistingTask) { if (mLaunchSingleInstance) { // There can be one and only one instance of single instance activity in the // history, and it is always in its own unique task, so we do a special search. intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false); } elseif ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) { // For the launch adjacent case we only want to put the activity in an existing // task if the activity already exists in the history. intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, !mLaunchSingleTask); } else { // Otherwise find the best task to put the activity in. intentActivity = mSupervisor.findTaskLocked(mStartActivity, mSourceDisplayId); } } return intentActivity; }