归筠溪 发表于 4 天前

startActivity到底发生了什么(二)

startActivity到底发生了什么(二)

启动另外一个应用的MainActivity
        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>注意必须设置exported为true才能被另一个进程启动。
val intent = Intent()
intent.setClassName("io.github.customview", "io.github.customview.activity.MainActivity")
intent.putExtra("name", "ITGuoKe")
context.startActivity(intent)启动另一个app的Activity,并传递参数。
app startActivity

context.startActivity(intent)通过多态实际上调用的是Activity的startActivity方法,然后startActivityForResult->Instrumentation.execStartActivity(注意是第四个参数为Activity的重载方法),最后IPC调用ActivityTaskManagerService的startActivity方法ActivityTaskManager.getService().startActivity.
系统服务ActivityTaskManagerService

startActivity -> startActivityAsUser -> getActivityStartController().obtainStarter
查看ActivityStartController的方法obtainStarter的源码如下
ActivityStarter obtainStarter(Intent intent, String reason) {
        return mFactory.obtain().setIntent(intent).setReason(reason);
}然后查看ActivityStarter的execute的方法源码:
int execute() {        // Required for logging ContentOrFileUriEventReported in the finally block.        String callerActivityName = null;        ActivityRecord launchingRecord = null;        try {                onExecutionStarted();                if (mRequest.intent != null) {                        // Refuse possible leaked file descriptors                        if (mRequest.intent.hasFileDescriptors()) {                                throw new IllegalArgumentException("File descriptors passed in Intent");                        }                        // Remove existing mismatch flag so it can be properly updated later                        mRequest.intent.removeExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH);                }                final LaunchingState launchingState;                synchronized (mService.mGlobalLock) {                        final ActivityRecord caller = ActivityRecord.forTokenLocked(mRequest.resultTo);                        final int callingUid = mRequest.realCallingUid == Request.DEFAULT_REAL_CALLING_UID                                ?Binder.getCallingUid() : mRequest.realCallingUid;                        launchingState = mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(                                mRequest.intent, caller, callingUid);                        callerActivityName = caller != null ? caller.info.name : null;                }                if (mRequest.intent != null) {                        mRequest.componentSpecified |= mRequest.intent.getComponent() != null;                }                // If the caller hasn't already resolved the activity, we're willing                // to do so here. If the caller is already holding the WM lock here,                // and we need to check dynamic Uri permissions, then we're forced                // to assume those permissions are denied to avoid deadlocking.                if (mRequest.activityInfo == null) {                        mRequest.resolveActivity(mSupervisor);                }                // Add checkpoint for this shutdown or reboot attempt, so we can record the original                // intent action and package name.                if (mRequest.intent != null) {                        String intentAction = mRequest.intent.getAction();                        String callingPackage = mRequest.callingPackage;                        if (intentAction != null && callingPackage != null                                && (Intent.ACTION_REQUEST_SHUTDOWN.equals(intentAction)                                        || Intent.ACTION_SHUTDOWN.equals(intentAction)                                        || Intent.ACTION_REBOOT.equals(intentAction))) {                                ShutdownCheckPoints.recordCheckPoint(intentAction, callingPackage, null);                        }                }                int res = START_CANCELED;                synchronized (mService.mGlobalLock) {                        final boolean globalConfigWillChange = mRequest.globalConfig != null                                && mService.getGlobalConfiguration().diff(mRequest.globalConfig) != 0;                        final Task rootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();                        if (rootTask != null) {                                rootTask.mConfigWillChange = globalConfigWillChange;                        }                        ProtoLog.v(WM_DEBUG_CONFIGURATION, "Starting activity when config "                                           + "will change = %b", globalConfigWillChange);                        final long origId = Binder.clearCallingIdentity();                        try {                                res = resolveToHeavyWeightSwitcherIfNeeded();                                if (res != START_SUCCESS) {                                        return res;                                }                                res = executeRequest(mRequest); // 1                        } finally {                                Binder.restoreCallingIdentity(origId);                                mRequest.logMessage.append(" result code=").append(res);                                Slog.i(TAG, mRequest.logMessage.toString());                                mRequest.logMessage.setLength(0);                        }                        if (globalConfigWillChange) {                                // If the caller also wants to switch to a new configuration, do so now.                                // This allows a clean switch, as we are waiting for the current activity                                // to pause (so we will not destroy it), and have not yet started the                                // next activity.                                mService.mAmInternal.enforceCallingPermission(                                        android.Manifest.permission.CHANGE_CONFIGURATION,                                        "updateConfiguration()");                                if (rootTask != null) {                                        rootTask.mConfigWillChange = false;                                }                                ProtoLog.v(WM_DEBUG_CONFIGURATION,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>   "Updating to new configuration after starting activity.");                                mService.updateConfigurationLocked(mRequest.globalConfig, null, false);                        }                        // The original options may have additional info about metrics. The mOptions is not                        // used here because it may be cleared in setTargetRootTaskIfNeeded.                        final ActivityOptions originalOptions = mRequest.activityOptions != null                                ? mRequest.activityOptions.getOriginalOptions() : null;                        // Only track the launch time of activity that will be resumed.                        if (mDoResume || (isStartResultSuccessful(res)        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>          && mLastStartActivityRecord.getTask().isVisibleRequested())) {                                launchingRecord = mLastStartActivityRecord;                        }                        // If the new record is the one that started, a new activity has created.                        final boolean newActivityCreated = mStartActivity == launchingRecord;                        // Notify ActivityMetricsLogger that the activity has launched.                        // ActivityMetricsLogger will then wait for the windows to be drawn and populate                        // WaitResult.                        mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>newActivityCreated, launchingRecord, originalOptions);                        if (mRequest.waitResult != null) {                                mRequest.waitResult.result = res;                                res = waitResultIfNeeded(mRequest.waitResult, mLastStartActivityRecord,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                               launchingState);                        }                        return getExternalResult(res);                }        } finally {                // Notify UriGrantsManagerService that activity launch completed. Required for logging                // the ContentOrFileUriEventReported message.                mSupervisor.mService.mUgmInternal.notifyActivityLaunchRequestCompleted(                        mRequest.hashCode(),                        // isSuccessfulLaunch                        launchingRecord != null,                        // Intent action                        mRequest.intent != null ? mRequest.intent.getAction() : null,                        mRequest.realCallingUid,                        callerActivityName,                        // Callee UID                        mRequest.activityInfo != null                        ? mRequest.activityInfo.applicationInfo.uid : INVALID_UID,                        // Callee Activity name                        mRequest.activityInfo != null ? mRequest.activityInfo.name : null,                        // isStartActivityForResult                        launchingRecord != null && launchingRecord.resultTo != null);                onExecutionComplete();        }}由注释1处的代码可知ActivityStarter的executeRequest源码如下:
private int executeRequest(Request request) {        if (TextUtils.isEmpty(request.reason)) {                throw new IllegalArgumentException("Need to specify a reason.");        }        mLastStartReason = request.reason;        mLastStartActivityTimeMs = System.currentTimeMillis();        ...        final ActivityRecord r = new ActivityRecord.Builder(mService)                .setCaller(callerApp)                .setLaunchedFromPid(callingPid)                .setLaunchedFromUid(callingUid)                .setLaunchedFromPackage(callingPackage)                .setLaunchedFromFeature(callingFeatureId)                .setIntent(intent)                .setResolvedType(resolvedType)                .setActivityInfo(aInfo)                .setConfiguration(mService.getGlobalConfiguration())                .setResultTo(resultRecord)                .setResultWho(resultWho)                .setRequestCode(requestCode)                .setComponentSpecified(request.componentSpecified)                .setRootVoiceInteraction(voiceSession != null)                .setActivityOptions(checkedOptions)                .setSourceRecord(sourceRecord)                .build();        mLastStartActivityRecord = r;        if (r.appTimeTracker == null && sourceRecord != null) {                // If the caller didn't specify an explicit time tracker, we want to continue                // tracking under any it has.                r.appTimeTracker = sourceRecord.appTimeTracker;        }        // Only allow app switching to be resumed if activity is not a restricted background        // activity and target app is not home process, otherwise any background activity        // started in background task can stop home button protection mode.        // As the targeted app is not a home process and we don't need to wait for the 2nd        // activity to be started to resume app switching, we can just enable app switching        // directly.        WindowProcessController homeProcess = mService.mHomeProcess;        boolean isHomeProcess = homeProcess != null                && aInfo.applicationInfo.uid == homeProcess.mUid;        if (balVerdict.allows() && !isHomeProcess) {                mService.resumeAppSwitches();        }        // Only do the create here since startActivityInner can abort. If it doesn't abort,        // the requestStart will be sent in handleStartRequest.        final Transition newTransition = r.mTransitionController.isShellTransitionsEnabled()                ? r.mTransitionController.createAndStartCollecting(TRANSIT_OPEN) : null;        // Because startActivity must run immediately, it can get combined with another        // transition meaning it is no-longer independent. This is NOT desirable, but is the        // only option for the time being.        final boolean isIndependent = newTransition != null;        final Transition transition = isIndependent ? newTransition                : mService.getTransitionController().getCollectingTransition();    // 1        mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>          request.voiceInteractor, startFlags, checkedOptions,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>          inTask, inTaskFragment, balVerdict, intentGrants, realCallingUid, transition,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>          isIndependent);        if (request.outActivity != null) {                request.outActivity = mLastStartActivityRecord;        }        return mLastStartActivityResult;}由文档注释可知:
startActivityUnchecked -> startActivityInner
startActivityUnchecked源码如下:
ActivityStarter.java
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, ActivityOptions options, Task inTask, TaskFragment inTaskFragment, BalVerdict balVerdict,NeededUriGrants intentGrants, int realCallingUid, Transition transition,   boolean isIndependentLaunch) {        int result = START_CANCELED;        final Task startedActivityRootTask;        RemoteTransition remoteTransition = r.takeRemoteTransition();        // Create a display snapshot as soon as possible.        if (isIndependentLaunch && mRequest.freezeScreen) {                final TaskDisplayArea tda = mLaunchParams.hasPreferredTaskDisplayArea()                        ? mLaunchParams.mPreferredTaskDisplayArea                        : mRootWindowContainer.getDefaultTaskDisplayArea();                final DisplayContent dc = mRootWindowContainer.getDisplayContentOrCreate(                        tda.getDisplayId());                if (dc != null) {                        transition.collect(dc);                        transition.collectVisibleChange(dc);                }        }        try {                mService.deferWindowLayout();                r.mTransitionController.collect(r);                try {                        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");                        result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor, startFlags, options, inTask, inTaskFragment, balVerdict, intentGrants, realCallingUid);                } catch (Exception ex) {                        Slog.e(TAG, "Exception on startActivityInner", ex);                } finally {                        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);                        startedActivityRootTask = handleStartResult(r, options, result, isIndependentLaunch,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                remoteTransition, transition);                }        } finally {                mService.continueWindowLayout();        }        postStartActivityProcessing(r, result, startedActivityRootTask);        return result;}startActivityInner源码如下:
ActivityStarter.java
/**   * Start an activity and determine if the activity should be adding to the top of an existing   * task or delivered new intent to an existing activity. Also manipulating the activity task   * onto requested or valid root-task/display.   *   * Note: This method should only be called from {@link #startActivityUnchecked}.   */// TODO(b/152429287): Make it easier to exercise code paths through startActivityInner@VisibleForTestingint startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,                                           IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,                                           int startFlags, ActivityOptions options, Task inTask,                                           TaskFragment inTaskFragment, BalVerdict balVerdict,                                           NeededUriGrants intentGrants, int realCallingUid) {        setInitialState(r, options, inTask, inTaskFragment, startFlags, sourceRecord,                                        voiceSession, voiceInteractor, balVerdict.getCode(), realCallingUid);        computeLaunchingTaskFlags();        mIntent.setFlags(mLaunchFlags);        boolean dreamStopping = false;        if (!com.android.window.flags.Flags.removeActivityStarterDreamCallback()) {                for (ActivityRecord stoppingActivity : mSupervisor.mStoppingActivities) {                        if (stoppingActivity.getActivityType()                                == WindowConfiguration.ACTIVITY_TYPE_DREAM) {                                dreamStopping = true;                                break;                        }                }        }        // Get top task at beginning because the order may be changed when reusing existing task.        final Task prevTopRootTask = mPreferredTaskDisplayArea.getFocusedRootTask();        final Task prevTopTask = prevTopRootTask != null ? prevTopRootTask.getTopLeafTask() : null;        final boolean sourceActivityLaunchedFromBubble =                sourceRecord != null && sourceRecord.getLaunchedFromBubble();        // if the flag is enabled, allow reusing bubbled tasks only if the source activity is        // bubbled.        final boolean includeLaunchedFromBubble =                Flags.onlyReuseBubbledTaskWhenLaunchedFromBubble()                ? sourceActivityLaunchedFromBubble : true;        final Task reusedTask = resolveReusableTask(includeLaunchedFromBubble);        // If requested, freeze the task list        if (mOptions != null && mOptions.freezeRecentTasksReordering()                && mSupervisor.mRecentTasks.isCallerRecents(r.launchedFromUid)                && !mSupervisor.mRecentTasks.isFreezeTaskListReorderingSet()) {                mFrozeTaskList = true;                mSupervisor.mRecentTasks.setFreezeTaskListReordering();        }        // Compute if there is an existing task that should be used for.        final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();        final boolean newTask = targetTask == null;        mTargetTask = targetTask;        computeLaunchParams(r, sourceRecord, targetTask);        // Check if starting activity on given task or on a new task is allowed.        int startResult = isAllowedToStart(r, newTask, targetTask);        if (startResult != START_SUCCESS) {                if (r.resultTo != null) {                        r.resultTo.sendResult(INVALID_UID, r.resultWho, r.requestCode, RESULT_CANCELED,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                  null /* data */, null /* callerToken */, null /* dataGrants */);                }                return startResult;        }        if (targetTask != null) {                if (targetTask.getTreeWeight() > MAX_TASK_WEIGHT_FOR_ADDING_ACTIVITY) {                        Slog.e(TAG, "Remove " + targetTask + " because it has contained too many"                                   + " activities or windows (abort starting " + r                                   + " from uid=" + mCallingUid);                        targetTask.removeImmediately("bulky-task");                        return START_ABORTED;                }                // When running transient transition, the transient launch target should keep on top.                // So disallow the transient hide activity to move itself to front, e.g. trampoline.                if (!avoidMoveToFront() && (mService.mHomeProcess == null        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                        || mService.mHomeProcess.mUid != realCallingUid)                        && (prevTopTask != null && prevTopTask.isActivityTypeHomeOrRecents())                        && r.mTransitionController.isTransientHide(targetTask)) {                        mCanMoveToFrontCode = MOVE_TO_FRONT_AVOID_LEGACY;                }                // If the activity is started by sending a pending intent and only its creator has the                // privilege to allow BAL (its sender does not), avoid move it to the front. Only do                // this when it is not a new task and not already been marked as avoid move to front.                // Guarded by a flag: balDontBringExistingBackgroundTaskStackToFg                if (balDontBringExistingBackgroundTaskStackToFg() && !avoidMoveToFront()                        && balVerdict.onlyCreatorAllows()) {                        mCanMoveToFrontCode = MOVE_TO_FRONT_AVOID_PI_ONLY_CREATOR_ALLOWS;                }                mPriorAboveTask = TaskDisplayArea.getRootTaskAbove(targetTask.getRootTask());        }        final ActivityRecord targetTaskTop = newTask                ? null : targetTask.getTopNonFinishingActivity();        if (targetTaskTop != null) {                // Removes the existing singleInstance activity in another task (if any) while                // launching a singleInstance activity on sourceRecord's task.                if (LAUNCH_SINGLE_INSTANCE == mLaunchMode && mSourceRecord != null                        && targetTask == mSourceRecord.getTask()) {                        final ActivityRecord activity = mRootWindowContainer.findActivity(mIntent,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>          mStartActivity.info, false);                        if (activity != null && activity.getTask() != targetTask) {                                activity.destroyIfPossible("Removes redundant singleInstance");                        }                }                if (mLastStartActivityRecord != null) {                        targetTaskTop.mLaunchSourceType = mLastStartActivityRecord.mLaunchSourceType;                }                targetTaskTop.mTransitionController.collect(targetTaskTop);                recordTransientLaunchIfNeeded(targetTaskTop);                // Recycle the target task for this launch.                startResult =                        recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants, balVerdict);                if (startResult != START_SUCCESS) {                        return startResult;                }        } else {                mAddingToTask = true;        }        // 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.        final Task topRootTask = mPreferredTaskDisplayArea.getFocusedRootTask();        if (topRootTask != null) {                startResult = deliverToCurrentTopIfNeeded(topRootTask, intentGrants);                if (startResult != START_SUCCESS) {                        return startResult;                }        }        if (mTargetRootTask == null) {                mTargetRootTask = getOrCreateRootTask(mStartActivity, mLaunchFlags, targetTask,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                                          mOptions);        }        if (newTask) {                final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)                        ? mSourceRecord.getTask() : null;                setNewTask(taskToAffiliate);        } else if (mAddingToTask) {                addOrReparentStartingActivity(targetTask, "adding to task");        }        // After activity is attached to task, but before actual start        recordTransientLaunchIfNeeded(mLastStartActivityRecord);        if (mDoResume) {                if (!avoidMoveToFront()) {                        mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask);                        final boolean launchBehindDream;                        if (com.android.window.flags.Flags.removeActivityStarterDreamCallback()) {                                final TaskDisplayArea tda = mTargetRootTask.getTaskDisplayArea();                                final Task top = (tda != null ? tda.getTopRootTask() : null);                                launchBehindDream = (top != null && top != mTargetRootTask)                                        && top.getActivityType() == WindowConfiguration.ACTIVITY_TYPE_DREAM                                        && top.getTopNonFinishingActivity() != null;                        } else {                                launchBehindDream = !mTargetRootTask.isTopRootTaskInDisplayArea()                                        && mService.isDreaming()                                        && !dreamStopping;                        }                        if (launchBehindDream) {                                // Launching underneath dream activity (fullscreen, always-on-top). Run the                                // launch--behind transition so the Activity gets created and starts                                // in visible state.                                mLaunchTaskBehind = true;                                r.mLaunchTaskBehind = true;                        }                } else {                        logPIOnlyCreatorAllowsBAL();                }        }        mService.mUgmInternal.grantUriPermissionUncheckedFromIntent(intentGrants,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                                mStartActivity.getUriPermissionsLocked());        if (mStartActivity.resultTo != null && mStartActivity.resultTo.info != null) {                // we need to resolve resultTo to a uid as grantImplicitAccess deals explicitly in UIDs                final PackageManagerInternal pmInternal =                        mService.getPackageManagerInternalLocked();                final int resultToUid = pmInternal.getPackageUid(                        mStartActivity.resultTo.info.packageName, 0 /* flags */,                        mStartActivity.mUserId);                pmInternal.grantImplicitAccess(mStartActivity.mUserId, mIntent,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                           UserHandle.getAppId(mStartActivity.info.applicationInfo.uid) /*recipient*/,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                           resultToUid /*visible*/, true /*direct*/);        } else if (mStartActivity.mShareIdentity) {                final PackageManagerInternal pmInternal =                        mService.getPackageManagerInternalLocked();                pmInternal.grantImplicitAccess(mStartActivity.mUserId, mIntent,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                           UserHandle.getAppId(mStartActivity.info.applicationInfo.uid) /*recipient*/,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                           r.launchedFromUid /*visible*/, true /*direct*/);        }        final Task startedTask = mStartActivity.getTask();        if (newTask) {                EventLogTags.writeWmCreateTask(mStartActivity.mUserId, startedTask.mTaskId,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                           startedTask.getRootTaskId(), startedTask.getDisplayId());        }        mStartActivity.logStartActivity(EventLogTags.WM_CREATE_ACTIVITY, startedTask);        mStartActivity.getTaskFragment().clearLastPausedActivity();        mRootWindowContainer.startPowerModeLaunchIfNeeded(                false /* forceSend */, mStartActivity);        final boolean isTaskSwitch = startedTask != prevTopTask;        mTargetRootTask.startActivityLocked(mStartActivity, topRootTask, newTask, isTaskSwitch,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                                mOptions, sourceRecord);        if (mDoResume) {                final ActivityRecord topTaskActivity = startedTask.topRunningActivityLocked();                if (!mTargetRootTask.isTopActivityFocusable()                        || (topTaskActivity != null && topTaskActivity.isTaskOverlay()                                && mStartActivity != topTaskActivity)) {                        // If the activity is not focusable, we can't resume it, but still would like to                        // make sure it becomes visible as it starts (this will also trigger entry                        // animation). An example of this are PIP activities.                        // Also, we don't want to resume activities in a task that currently has an overlay                        // as the starting activity just needs to be in the visible paused state until the                        // over is removed.                        // Passing {@code null} as the start parameter ensures all activities are made                        // visible.                        mTargetRootTask.ensureActivitiesVisible(null /* starting */);                        // Go ahead and tell window manager to execute app transition for this activity                        // since the app transition will not be triggered through the resume channel.                        mTargetRootTask.mDisplayContent.executeAppTransition();                } else {                        // If the target root-task was not previously focusable (previous top running                        // activity on that root-task was not visible) then any prior calls to move the                        // root-task to the will not update the focused root-task.If starting the new                        // activity now allows the task root-task to be focusable, then ensure that we                        // now update the focused root-task accordingly.                        if (mTargetRootTask.isTopActivityFocusable()                                && !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) {                                if (!avoidMoveToFront()) {                                        mTargetRootTask.moveToFront("startActivityInner");                                } else {                                        logPIOnlyCreatorAllowsBAL();                                }                        }                        mRootWindowContainer.resumeFocusedTasksTopActivities(                                mTargetRootTask, mStartActivity, mOptions, mTransientLaunch); // 1                }        }        mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask);        // Update the recent tasks list immediately when the activity starts        mSupervisor.mRecentTasks.add(startedTask);        mSupervisor.handleNonResizableTaskIfNeeded(startedTask,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                                           mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetRootTask);        // If Activity's launching into PiP, move the mStartActivity immediately to pinned mode.        // Note that mStartActivity and source should be in the same Task at this point.        if (mOptions != null && mOptions.isLaunchIntoPip()                && sourceRecord != null && sourceRecord.getTask() == mStartActivity.getTask()                && balVerdict.allows()) {                mRootWindowContainer.moveActivityToPinnedRootTask(mStartActivity,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                  sourceRecord, "launch-into-pip", null /* bounds */);        }        mSupervisor.getBackgroundActivityLaunchController()                .onNewActivityLaunched(mStartActivity);        return START_SUCCESS;}源码中
mStartActivity 是 ActivityStarter对象的ActivityRecord类型的成员变量.
mSupervisor是ActivityTaskSupervisor类型的对象,管理任务栈逻辑.
mRootWindowContainer是RootWindowContainer类型的对象.
我们看下RootWindowContainer类型的对象的resumeFocusedTasksTopActivities方法的源码:
frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean resumeFocusedTasksTopActivities(        Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions, boolean deferPause) {        if (!mTaskSupervisor.readyToResume()) {                return false;        }        boolean result = false;        if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                   || getTopDisplayFocusedRootTask() == targetRootTask)) {                result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                               deferPause);        }        for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {                final DisplayContent display = getChildAt(displayNdx);                final boolean curResult = result;                boolean[] resumedOnDisplay = new boolean;                final ActivityRecord topOfDisplay = display.topRunningActivity();                display.forAllRootTasks(rootTask -> {                        final ActivityRecord topRunningActivity = rootTask.topRunningActivity();                        if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) {                                return;                        }                        if (rootTask == targetRootTask) {                                // Simply update the result for targetRootTask because the targetRootTask                                // had already resumed in above. We don't want to resume it again,                                // especially in some cases, it would cause a second launch failure                                // if app process was dead.                                resumedOnDisplay |= curResult;                                return;                        }                        if (topRunningActivity.isState(RESUMED) && topRunningActivity == topOfDisplay) {                                // Kick off any lingering app transitions form the MoveTaskToFront operation,                                // but only consider the top activity on that display.                                rootTask.executeAppTransition(targetOptions);                        } else {                                resumedOnDisplay |= topRunningActivity.makeActiveIfNeeded(target);                        }                });                result |= resumedOnDisplay;                if (!resumedOnDisplay) {                        // In cases when there are no valid activities (e.g. device just booted or launcher                        // crashed) it's possible that nothing was resumed on a display. Requesting resume                        // of top activity in focused root task explicitly will make sure that at least home                        // activity is started and resumed, and no recursion occurs.                        final Task focusedRoot = display.getFocusedRootTask();                        if (focusedRoot != null) {                                result |= focusedRoot.resumeTopActivityUncheckedLocked(                                        target, targetOptions, false /* skipPause */); // 1                        } else if (targetRootTask == null) {                                result |= resumeHomeActivity(null /* prev */, "no-focusable-task",        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                                       display.getDefaultTaskDisplayArea());                        }                }        }        return result;}focusedRoot是Task类型的对象,接下来查看方法resumeTopActivityUncheckedLocked的源码:
frameworks/base/services/core/java/com/android/server/wm/Task.java
/**   * Ensure that the top activity in the root task is resumed.   *   * @param prev The previously resumed activity, for when in the process   * of pausing; can be null to call from elsewhere.   * @param options Activity options.   * @param deferPause When {@code true}, this will not pause back tasks.   *   * @return Returns true if something is being resumed, or false if   * nothing happened.   *   * NOTE: It is not safe to call this method directly as it can cause an activity in a   *       non-focused root task to be resumed.   *       Use {@link RootWindowContainer#resumeFocusedTasksTopActivities} to resume the   *       right activity for the current system state.   */@GuardedBy("mService")boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options,boolean deferPause) {        if (mInResumeTopActivity) {                // Don't even start recursing.                return false;        }        boolean someActivityResumed = false;        try {                // Protect against recursion.                mInResumeTopActivity = true;                if (isLeafTask()) {                        if (isFocusableAndVisible()) {                                someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);                        }                } else {                        int idx = mChildren.size() - 1;                        while (idx >= 0) {                                final Task child = (Task) getChildAt(idx--);                                if (!child.isTopActivityFocusable()) {                                        continue;                                }                                if (child.getVisibility(null /* starting */)                                        != TASK_FRAGMENT_VISIBILITY_VISIBLE) {                                        if (child.topRunningActivity() == null) {        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>// Skip the task if no running activity and continue resuming next task.        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>continue;                                        }                                        // Otherwise, assuming everything behind this task should also be invisible.                                        break;                                }                                someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>          deferPause);                                // Doing so in order to prevent IndexOOB since hierarchy might changes while                                // resuming activities, for example dismissing split-screen while starting                                // non-resizeable activity.                                if (idx >= mChildren.size()) {                                        idx = mChildren.size() - 1;                                }                        }                }                // When resuming the top activity, it may be necessary to pause the top activity (for                // example, returning to the lock screen. We suppress the normal pause logic in                // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the                // end. We call the {@link ActivityTaskSupervisor#checkReadyForSleepLocked} again here                // to ensure any necessary pause logic occurs. In the case where the Activity will be                // shown regardless of the lock screen, the call to                // {@link ActivityTaskSupervisor#checkReadyForSleepLocked} is skipped.                final ActivityRecord next = topRunningActivity(true /* focusableOnly */);                if (next == null || !next.canTurnScreenOn()) {                        checkReadyForSleep();                }        } finally {                mInResumeTopActivity = false;        }        return someActivityResumed;}继续看Task对象的resumeTopActivityInnerLocked方法:
@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options, boolean deferPause) {
        if (!mAtmService.isBooting() && !mAtmService.isBooted()) {
                // Not ready yet!
                return false;
        }

        final ActivityRecord topActivity = topRunningActivity(true /* focusableOnly */);
        if (topActivity == null) {
                // There are no activities left in this task, let's look somewhere else.
                return resumeNextFocusableActivityWhenRootTaskIsEmpty(prev, options);
        }

        final boolean[] resumed = new boolean;
        final TaskFragment topFragment = topActivity.getTaskFragment();
        resumed = topFragment.resumeTopActivity(prev, options, deferPause);
        forAllLeafTaskFragments(f -> {
                if (topFragment == f) {
                        return;
                }
                if (!f.canBeResumed(null /* starting */)) {
                        return;
                }
                resumed |= f.resumeTopActivity(prev, options, deferPause);
        }, true);
        return resumed;
}TaskFragment的resumeTopActivity源码如下:
frameworks/base/services/core/java/com/android/server/wm/TaskFragment.java
final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options, boolean skipPause) {        ActivityRecord next = topRunningActivity(true /* focusableOnly */);        if (next == null || !next.canResumeByCompat()) {                return false;        }        next.delayedResume = false;        if (!skipPause && !mRootWindowContainer.allPausedActivitiesComplete()) {                // If we aren't skipping pause, then we have to wait for currently pausing activities.                ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivity: Skip resume: some activity pausing.");                return false;        }        final TaskDisplayArea taskDisplayArea = getDisplayArea();        // If the top activity is the resumed one, nothing to do.        if (mResumedActivity == next && next.isState(RESUMED)                && taskDisplayArea.allResumedActivitiesComplete()) {                // Ensure the visibility gets updated before execute app transition.                taskDisplayArea.ensureActivitiesVisible(null /* starting */, true /* notifyClients */);                // Make sure we have executed any pending transitions, since there                // should be nothing left to do at this point.                executeAppTransition(options);                // In a multi-resumed environment, like in a freeform device, the top                // activity can be resumed, but it might not be the focused app.                // Set focused app when top activity is resumed. However, we shouldn't do it for a                // same task because it can break focused state. (e.g. activity embedding)                if (taskDisplayArea.inMultiWindowMode() && taskDisplayArea.mDisplayContent != null) {                        final ActivityRecord focusedApp = taskDisplayArea.mDisplayContent.mFocusedApp;                        if (focusedApp == null || focusedApp.getTask() != next.getTask()) {                                taskDisplayArea.mDisplayContent.setFocusedApp(next);                        }                }                ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Top activity "                                   + "resumed %s", next);                return false;        }        // If we are sleeping, and there is no resumed activity, and the top activity is paused,        // well that is the state we want.        if (mLastPausedActivity == next && shouldSleepOrShutDownActivities()) {                // Make sure we have executed any pending transitions, since there                // should be nothing left to do at this point.                executeAppTransition(options);                ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Going to sleep and"                                   + " all paused");                return false;        }        // Make sure that the user who owns this activity is started.If not,        // we will just leave it as is because someone should be bringing        // another user's activities to the top of the stack.        if (!mAtmService.mAmInternal.hasStartedUserState(next.mUserId)) {                Slog.w(TAG, "Skipping resume of top activity " + next                           + ": user " + next.mUserId + " is stopped");                return false;        }        // The activity may be waiting for stop, but that is no longer        // appropriate for it.        mTaskSupervisor.mStoppingActivities.remove(next);        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);        mTaskSupervisor.setLaunchSource(next.info.applicationInfo.uid);        ActivityRecord lastResumed = null;        final Task lastFocusedRootTask = taskDisplayArea.getLastFocusedRootTask();        if (lastFocusedRootTask != null && lastFocusedRootTask != getRootTaskFragment().asTask()) {                // So, why aren't we using prev here??? See the param comment on the method. prev                // doesn't represent the last resumed activity. However, the last focus stack does if                // it isn't null.                lastResumed = lastFocusedRootTask.getTopResumedActivity();        }        boolean pausing = !skipPause && taskDisplayArea.pauseBackTasks(next);        if (mResumedActivity != null) {                ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Pausing %s", mResumedActivity);                pausing |= startPausing(mTaskSupervisor.mUserLeaving, false /* uiSleeping */,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                next, "resumeTopActivity");        }        if (pausing) {                ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivity: Skip resume: need to"                                   + " start pausing");                // At this point we want to put the upcoming activity's process                // at the top of the LRU list, since we know we will be needing it                // very soon and it would be a waste to let it get killed if it                // happens to be sitting towards the end.                if (next.attachedToProcess()) {                        next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                           true /* activityChange */, false /* updateOomAdj */,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                           false /* addPendingTopUid */);                } else if (!next.isProcessRunning()) {                        // Since the start-process is asynchronous, if we already know the process of next                        // activity isn't running, we can start the process earlier to save the time to wait                        // for the current activity to be paused.                        final boolean isTop = this == taskDisplayArea.getFocusedRootTask();                        mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                                  isTop ? HostingRecord.HOSTING_TYPE_NEXT_TOP_ACTIVITY        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                                  : HostingRecord.HOSTING_TYPE_NEXT_ACTIVITY);                }                if (lastResumed != null) {                        lastResumed.setWillCloseOrEnterPip(true);                }                return true;        } else if (mResumedActivity == next && next.isState(RESUMED)                           && taskDisplayArea.allResumedActivitiesComplete()) {                // It is possible for the activity to be resumed when we paused back stacks above if the                // next activity doesn't have to wait for pause to complete.                // So, nothing else to-do except:                // Make sure we have executed any pending transitions, since there                // should be nothing left to do at this point.                executeAppTransition(options);                ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Top activity resumed "                                   + "(dontWaitForPause) %s", next);                return true;        }        // If the most recent activity was noHistory but was only stopped rather        // than stopped+finished because the device went to sleep, we need to make        // sure to finish it as we're making a new activity topmost.        if (shouldSleepActivities()) {                mTaskSupervisor.finishNoHistoryActivitiesIfNeeded(next);        }        if (prev != null && prev != next && next.nowVisible) {                // The next activity is already visible, so hide the previous                // activity's windows right now so we can show the new one ASAP.                // We only do this if the previous is finishing, which should mean                // it is on top of the one being resumed so hiding it quickly                // is good.Otherwise, we want to do the normal route of allowing                // the resumed activity to be shown so we can decide if the                // previous should actually be hidden depending on whether the                // new one is found to be full-screen or not.                if (prev.finishing) {                        prev.setVisibility(false);                        if (DEBUG_SWITCH) {                                Slog.v(TAG_SWITCH, "Not waiting for visible to hide: " + prev                                           + ", nowVisible=" + next.nowVisible);                        }                } else {                        if (DEBUG_SWITCH) {                                Slog.v(TAG_SWITCH, "Previous already visible but still waiting to hide: " + prev                                           + ", nowVisible=" + next.nowVisible);                        }                }        }        try {                mTaskSupervisor.getActivityMetricsLogger()                        .notifyBeforePackageUnstopped(next.packageName);                mAtmService.getPackageManagerInternalLocked().notifyComponentUsed(                        next.packageName, next.mUserId,                        next.packageName, next.toString()); /* TODO: Verify if correct userid */        } catch (IllegalArgumentException e) {                Slog.w(TAG, "Failed trying to unstop package "                           + next.packageName + ": " + e);        }        // We are starting up the next activity, so tell the window manager        // that the previous one will be hidden soon.This way it can know        // to ignore it when computing the desired screen orientation.        boolean anim = true;        final DisplayContent dc = taskDisplayArea.mDisplayContent;        if (prev != null) {                if (prev.finishing) {                        if (DEBUG_TRANSITION) {                                Slog.v(TAG_TRANSITION, "Prepare close transition: prev=" + prev);                        }                        if (mTaskSupervisor.mNoAnimActivities.contains(prev)) {                                anim = false;                                dc.prepareAppTransition(TRANSIT_NONE);                        } else {                                dc.prepareAppTransition(TRANSIT_CLOSE);                        }                        prev.setVisibility(false);                } else {                        if (DEBUG_TRANSITION) {                                Slog.v(TAG_TRANSITION, "Prepare open transition: prev=" + prev);                        }                        if (mTaskSupervisor.mNoAnimActivities.contains(next)) {                                anim = false;                                dc.prepareAppTransition(TRANSIT_NONE);                        } else {                                dc.prepareAppTransition(TRANSIT_OPEN,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                                next.mLaunchTaskBehind ? TRANSIT_FLAG_OPEN_BEHIND : 0);                        }                }        } else {                if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");                if (mTaskSupervisor.mNoAnimActivities.contains(next)) {                        anim = false;                        dc.prepareAppTransition(TRANSIT_NONE);                } else {                        dc.prepareAppTransition(TRANSIT_OPEN);                }        }        if (anim) {                next.applyOptionsAnimation();        } else {                next.abortAndClearOptionsAnimation();        }        mTaskSupervisor.mNoAnimActivities.clear();        if (next.attachedToProcess()) {                if (DEBUG_SWITCH) {                        Slog.v(TAG_SWITCH, "Resume running: " + next + " stopped=" + next.mAppStopped                                   + " visibleRequested=" + next.isVisibleRequested());                }                // If the previous activity is translucent, force a visibility update of                // the next activity, so that it's added to WM's opening app list, and                // transition animation can be set up properly.                // For example, pressing Home button with a translucent activity in focus.                // Launcher is already visible in this case. If we don't add it to opening                // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a                // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.                final boolean lastActivityTranslucent = inMultiWindowMode()                        || mLastPausedActivity != null && !mLastPausedActivity.occludesParent();                // This activity is now becoming visible.                if (!next.isVisibleRequested() || next.mAppStopped || lastActivityTranslucent) {                        next.app.addToPendingTop();                        next.setVisibility(true);                }                // schedule launch ticks to collect information about slow apps.                next.startLaunchTickingLocked();                ActivityRecord lastResumedActivity =                        lastFocusedRootTask == null ? null                        : lastFocusedRootTask.getTopResumedActivity();                final ActivityRecord.State lastState = next.getState();                mAtmService.updateCpuStats();                ProtoLog.v(WM_DEBUG_STATES, "Moving to RESUMED: %s (in existing)", next);                next.setState(RESUMED, "resumeTopActivity");                // Activity should also be visible if set mLaunchTaskBehind to true (see                // ActivityRecord#shouldBeVisibleIgnoringKeyguard()).                if (shouldBeVisible(next)) {                        // We have special rotation behavior when here is some active activity that                        // requests specific orientation or Keyguard is locked. Make sure all activity                        // visibilities are set correctly as well as the transition is updated if needed                        // to get the correct rotation behavior. Otherwise the following call to update                        // the orientation may cause incorrect configurations delivered to client as a                        // result of invisible window resize.                        // TODO: Remove this once visibilities are set correctly immediately when                        // starting an activity.                        final int originalRelaunchingCount = next.mPendingRelaunchCount;                        mRootWindowContainer.ensureVisibilityAndConfig(next, mDisplayContent,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                   false /* deferResume */);                        if (next.mPendingRelaunchCount > originalRelaunchingCount) {                                // The activity is scheduled to relaunch, then ResumeActivityItem will be also                                // included (see ActivityRecord#relaunchActivityLocked) if it should resume.                                next.completeResumeLocked();                                return true;                        }                }                try {                        final IApplicationThread appThread = next.app.getThread();                        // Deliver all pending results.                        final ArrayList a = next.results;                        if (a != null) {                                final int size = a.size();                                if (!next.finishing && size > 0) {                                        if (DEBUG_RESULTS) {        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>Slog.v(TAG_RESULTS, "Delivering results to " + next + ": " + a);                                        }                                        final ActivityResultItem item = new ActivityResultItem(next.token, a);                                        mAtmService.getLifecycleManager().scheduleTransactionItem(appThread, item);                                }                        }                        if (next.newIntents != null) {                                final NewIntentItem item =                                        new NewIntentItem(next.token, next.newIntents, true /* resume */);                                mAtmService.getLifecycleManager().scheduleTransactionItem(appThread, item);                        }                        // Well the app will no longer be stopped.                        // Clear app token stopped state in window manager if needed.                        next.notifyAppResumed();                        EventLogTags.writeWmResumeActivity(next.mUserId, System.identityHashCode(next),        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>                                           next.getTask().mTaskId, next.shortComponentName);                        mAtmService.getAppWarningsLocked().onResumeActivity(next);                        final int topProcessState = mAtmService.mTopProcessState;                        next.app.setPendingUiCleanAndForceProcessStateUpTo(topProcessState);                        next.abortAndClearOptionsAnimation();                        final ResumeActivityItem resumeActivityItem = new ResumeActivityItem(                                next.token, topProcessState, dc.isNextTransitionForward(),                                next.shouldSendCompatFakeFocus());                        mAtmService.getLifecycleManager().scheduleTransactionItem(                                appThread, resumeActivityItem);                        ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Resumed %s", next);                } catch (Exception e) {                        // Whoops, need to restart this activity!                        ProtoLog.v(WM_DEBUG_STATES, "Resume failed; resetting state to %s: "                                           + "%s", lastState, next);                        next.setState(lastState, "resumeTopActivityInnerLocked");                        // lastResumedActivity being non-null implies there is a lastStack present.                        if (lastResumedActivity != null) {                                lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");                        }                        Slog.i(TAG, "Restarting because process died: " + next);                        if (!next.hasBeenLaunched) {                                next.hasBeenLaunched = true;                        } else if (SHOW_APP_STARTING_PREVIEW && lastFocusedRootTask != null                                           && lastFocusedRootTask.isTopRootTaskInDisplayArea()) {                                next.showStartingWindow(false /* taskSwitch */);                        }                        mTaskSupervisor.startSpecificActivity(next, true, false);                        return true;                }                next.completeResumeLocked();        } else {                // Whoops, need to restart this activity!                if (!next.hasBeenLaunched) {                        next.hasBeenLaunched = true;                } else {                        if (SHOW_APP_STARTING_PREVIEW) {                                next.showStartingWindow(false /* taskSwich */);                        }                        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);                }                ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Restarting %s", next);                mTaskSupervisor.startSpecificActivity(next, true, true);        }        return true;}注意:
记得留意andResume这个参数,此处的值为true,代表的是LifecyclePath的finish状态,即:ActivityLifecycleItem.ON_RESUME.
2处的代码,如果任务栈顶的Activity是处于Resume状态,则先将其置于Pause状态。
代码1处ActivityTaskSupervisor对象调用startSpecificActivity方法启动Activity,源码如下:
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {        // Is this activity's application already running?        final WindowProcessController wpc =                mService.getProcessController(r.processName, r.info.applicationInfo.uid);        boolean knownToBeDead = false;        if (wpc != null && wpc.hasThread()) {                try {                        realStartActivityLocked(r, wpc, andResume, checkConfig);                        return; // 1 如果进程已经存在                } catch (RemoteException e) {                        Slog.w(TAG, "Exception when starting activity "                                   + r.intent.getComponent().flattenToShortString(), e);                }                // If a dead object exception was thrown -- fall through to                // restart the application.                knownToBeDead = true;                // Remove the process record so it won't be considered as alive.                mService.mProcessNames.remove(wpc.mName, wpc.mUid);                mService.mProcessMap.remove(wpc.getPid());        } else if (ActivityTaskManagerService.isSdkSandboxActivityIntent(                mService.mContext, r.intent)) {                Slog.e(TAG, "Abort sandbox activity launching as no sandbox process to host it.");                r.finishIfPossible("No sandbox process for the activity", false /* oomAdj */);                r.launchFailed = true;                r.detachFromProcess();                return;        }        r.notifyUnknownVisibilityLaunchedForKeyguardTransition();        final boolean isTop = andResume && r.isTopRunningActivity();        mService.startProcessAsync(r, knownToBeDead, isTop,        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>           isTop ? HostingRecord.HOSTING_TYPE_TOP_ACTIVITY        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>           : HostingRecord.HOSTING_TYPE_ACTIVITY); // 2}如果Activity所在的应用的进程已经存在,则执行代码1处的代码然后返回,否则执行代码2处的代码,fork新的进程。
代码2处mService是ActivityTaskManagerService类型的示例,调用了其startProcessAsync方法,其源码如下:
void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop, String hostingType) {        if (!mStartingProcessActivities.contains(activity)) {                mStartingProcessActivities.add(activity);                // Let the activity with higher z-order be started first.                if (mStartingProcessActivities.size() > 1) {                        mStartingProcessActivities.sort(null /* by WindowContainer#compareTo */);                }        } else if (mProcessNames.get(                activity.processName, activity.info.applicationInfo.uid) != null) {                // The process is already starting. Wait for it to attach.                return;        }        try {                if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {                        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "dispatchingStartProcess:"        <intent-filter>
               
                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>       + activity.processName);                }                // Post message to start process to avoid possible deadlock of calling into AMS with the                // ATMS lock held.                final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead, isTop, hostingType, activity.intent.getComponent()); // 1                mH.sendMessage(m); // 2        } finally {                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);        }}代码1处接口PooledLambda的obtainMessage静态方法源码如下:
staticMessage obtainMessage(        HeptConsumer
页: [1]
查看完整版本: startActivity到底发生了什么(二)