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, @Nullable Bundle options){ if (mParent == null) { options = transferSpringboardActivityOptions(options); // 关键代码 Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this,mMainThread.getApplicationThread(),mToken,this, intent,options); // if (ar != null) { mMainThread.sendActivityResult( mToken,mEmbeddedID,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,options); } else { // Note we want to go through this method for compatibility with // existing applications that may have overridden it. mParent.startActivityFromChild(this,requestCode); } } }
publicvoidstartActivityFromChild(@NonNull Activity child,@RequiresPermission Intent intent,@Nullable Bundle options){ options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this,child, intent,options); if (ar != null) { mMainThread.sendActivityResult( mToken,child.mEmbeddedID, ar.getResultCode(),ar.getResultData()); } cancelInputsAndStartExitTransition(options); }
int res = startActivityLocked(caller,ephemeralIntent, aInfo,voiceSession,voiceInteractor, resultTo,callingPid, callingUid,realCallingPid,realCallingUid, options,ignoreTargetSecurity,componentSpecified,outRecord,container, inTask,reason);
// 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, !mLaunchSingleTask); } else { // Otherwise find the best task to put the activity in. intentActivity = mSupervisor.findTaskLocked(mStartActivity,mSourceDisplayId); } } return intentActivity; }