android12 启动普通Activity流程分析

12 阅读23分钟

ContextImpl.startActivity() -> mMainThread.getInstrumentation().execStartActivity( getOuterContext(), mMainThread.getApplicationThread(), null, (Activity) null, intent, -1, options); ->Instrumentation.execStartActivity();

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    Uri referrer = target != null ? target.onProvideReferrer() : null;
    if (referrer != null) {
        intent.putExtra(Intent.EXTRA_REFERRER, referrer);
    }
    if (mActivityMonitors != null) {
        synchronized (mSync) {
            final int N = mActivityMonitors.size();
            for (int i=0; i<N; i++) {
                final ActivityMonitor am = mActivityMonitors.get(i);
                ActivityResult result = null;
                if (am.ignoreMatchingSpecificIntents()) {
                    result = am.onStartActivity(intent);
                }
                if (result != null) {
                    am.mHits++;
                    return result;
                } else if (am.match(who, null, intent)) {
                    am.mHits++;
                    if (am.isBlocking()) {
                        return requestCode >= 0 ? am.getResult() : null;
                    }
                    break;
                }
            }
        }
    }
    try {
        intent.migrateExtraStreamToClipData(who);
        intent.prepareToLeaveProcess(who);
        int result = ActivityTaskManager.getService().startActivity(whoThread,
                who.getOpPackageName(), who.getAttributionTag(), intent,
                intent.resolveTypeIfNeeded(who.getContentResolver()), token,
                target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

ActivityTaskManagerService.startActivity();

public final int startActivity(IApplicationThread caller, String callingPackage,
        String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
        String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
        Bundle bOptions) {
    return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
            resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
            UserHandle.getCallingUserId());
}


public int startActivityAsUser(IApplicationThread caller, String callingPackage,
        String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
        String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
        Bundle bOptions, int userId) {
    return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
            resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
            true /*validateIncomingUser*/);
}

ActivityTaskManagerService.startActivityAsUser

private int startActivityAsUser(IApplicationThread caller, String callingPackage,
        @Nullable String callingFeatureId, Intent intent, String resolvedType,
        IBinder resultTo, String resultWho, int requestCode, int startFlags,
        ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
    assertPackageMatchesCallingUid(callingPackage);
    enforceNotIsolatedCaller("startActivityAsUser");

    userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
            Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

    // TODO: Switch to user app stacks here.
    //ActivityStartController
    return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
            .setCaller(caller)
            .setCallingPackage(callingPackage)
            .setCallingFeatureId(callingFeatureId)
            .setResolvedType(resolvedType)
            .setResultTo(resultTo)
            .setResultWho(resultWho)
            .setRequestCode(requestCode)
            .setStartFlags(startFlags)
            .setProfilerInfo(profilerInfo)
            .setActivityOptions(bOptions)
            .setUserId(userId)
            .execute();

}

ActivityStarter.execute() ->ActivityStarter.executeRequest() 到这里流程跟启动桌面APP一致

int execute() {
    try {
        // Refuse possible leaked file descriptors
        if (mRequest.intent != null && mRequest.intent.hasFileDescriptors()) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        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);
        }

        // 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;
        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();

            res = resolveToHeavyWeightSwitcherIfNeeded();
            if (res != START_SUCCESS) {
                return res;
            }
            res = executeRequest(mRequest);

            Binder.restoreCallingIdentity(origId);

            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,
                            "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;
            // If the new record is the one that started, a new activity has created.
            final boolean newActivityCreated = mStartActivity == mLastStartActivityRecord;
            // 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,
                    newActivityCreated, mLastStartActivityRecord, originalOptions);
            if (mRequest.waitResult != null) {
                mRequest.waitResult.result = res;
                res = waitResultIfNeeded(mRequest.waitResult, mLastStartActivityRecord,
                        launchingState);
            }
            return getExternalResult(res);
        }
    } finally {
        onExecutionComplete();
    }
}





private int executeRequest(Request request) {
    if (TextUtils.isEmpty(request.reason)) {
        throw new IllegalArgumentException("Need to specify a reason.");
    }
    mLastStartReason = request.reason;
    mLastStartActivityTimeMs = System.currentTimeMillis();
    mLastStartActivityRecord = null;

    final IApplicationThread caller = request.caller;
    Intent intent = request.intent;
    NeededUriGrants intentGrants = request.intentGrants;
    String resolvedType = request.resolvedType;
    ActivityInfo aInfo = request.activityInfo;
    ResolveInfo rInfo = request.resolveInfo;
    final IVoiceInteractionSession voiceSession = request.voiceSession;
    final IBinder resultTo = request.resultTo;
    String resultWho = request.resultWho;
    int requestCode = request.requestCode;
    int callingPid = request.callingPid;
    int callingUid = request.callingUid;
    String callingPackage = request.callingPackage;
    String callingFeatureId = request.callingFeatureId;
    final int realCallingPid = request.realCallingPid;
    final int realCallingUid = request.realCallingUid;
    final int startFlags = request.startFlags;
    final SafeActivityOptions options = request.activityOptions;
    Task inTask = request.inTask;

    int err = ActivityManager.START_SUCCESS;
    // Pull the optional Ephemeral Installer-only bundle out of the options early.
    final Bundle verificationBundle =
            options != null ? options.popAppVerificationBundle() : null;

    WindowProcessController callerApp = null;
    if (caller != null) {
        callerApp = mService.getProcessController(caller);
        if (callerApp != null) {
            callingPid = callerApp.getPid();
            callingUid = callerApp.mInfo.uid;
        } else {
            Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + callingPid
                    + ") when starting: " + intent.toString());
            err = ActivityManager.START_PERMISSION_DENIED;
        }
    }

    final int userId = aInfo != null && aInfo.applicationInfo != null
            ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
    if (err == ActivityManager.START_SUCCESS) {
        Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
                + "} from uid " + callingUid);
    }
 
   //sourceRecord 发起请求的Activity,resultRecord是要接收onResult的Activity
    ActivityRecord sourceRecord = null;
    ActivityRecord resultRecord = null;
    if (resultTo != null) {
        sourceRecord = mRootWindowContainer.isInAnyTask(resultTo);
        if (DEBUG_RESULTS) {
            Slog.v(TAG_RESULTS, "Will send result to " + resultTo + " " + sourceRecord);
        }
        if (sourceRecord != null) {
            if (requestCode >= 0 && !sourceRecord.finishing) {
                resultRecord = sourceRecord;
            }
        }
    }


  //启动模式判断
    final int launchFlags = intent.getFlags();
    if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
        // Transfer the result target from the source activity to the new one being started,
        // including any failures.
        if (requestCode >= 0) {
            SafeActivityOptions.abort(options);
            return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
        }
        resultRecord = sourceRecord.resultTo;
        if (resultRecord != null && !resultRecord.isInRootTaskLocked()) {
            resultRecord = null;
        }
        resultWho = sourceRecord.resultWho;
        requestCode = sourceRecord.requestCode;
        sourceRecord.resultTo = null;
        if (resultRecord != null) {
            resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
        }
        if (sourceRecord.launchedFromUid == callingUid) {
            // The new activity is being launched from the same uid as the previous activity
            // in the flow, and asking to forward its result back to the previous.  In this
            // case the activity is serving as a trampoline between the two, so we also want
            // to update its launchedFromPackage to be the same as the previous activity.
            // Note that this is safe, since we know these two packages come from the same
            // uid; the caller could just as well have supplied that same package name itself
            // . This specifially deals with the case of an intent picker/chooser being
            // launched in the app flow to redirect to an activity picked by the user, where
            // we want the final activity to consider it to have been launched by the
            // previous app activity.
            callingPackage = sourceRecord.launchedFromPackage;
            callingFeatureId = sourceRecord.launchedFromFeatureId;
        }
    }
    
     //检查err

    if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
        // We couldn't find a class that can handle the given Intent.
        // That's the end of that!
        err = ActivityManager.START_INTENT_NOT_RESOLVED;
    }

    if (err == ActivityManager.START_SUCCESS && aInfo == null) {
        // We couldn't find the specific class specified in the Intent.
        // Also the end of the line.
        err = ActivityManager.START_CLASS_NOT_FOUND;
    }

    if (err == ActivityManager.START_SUCCESS && sourceRecord != null
            && sourceRecord.getTask().voiceSession != null) {
        // If this activity is being launched as part of a voice session, we need to ensure
        // that it is safe to do so.  If the upcoming activity will also be part of the voice
        // session, we can only launch it if it has explicitly said it supports the VOICE
        // category, or it is a part of the calling app.
        if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
                && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
            try {
                intent.addCategory(Intent.CATEGORY_VOICE);
                if (!mService.getPackageManager().activitySupportsIntent(
                        intent.getComponent(), intent, resolvedType)) {
                    Slog.w(TAG, "Activity being started in current voice task does not support "
                            + "voice: " + intent);
                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                }
            } catch (RemoteException e) {
                Slog.w(TAG, "Failure checking voice capabilities", e);
                err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
            }
        }
    }


    if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
        // If the caller is starting a new voice session, just make sure the target
        // is actually allowing it to run this way.
        try {
            if (!mService.getPackageManager().activitySupportsIntent(intent.getComponent(),
                    intent, resolvedType)) {
                Slog.w(TAG,
                        "Activity being started in new voice task does not support: " + intent);
                err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
            }
        } catch (RemoteException e) {
            Slog.w(TAG, "Failure checking voice capabilities", e);
            err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
        }
    }

    final Task resultRootTask = resultRecord == null
            ? null : resultRecord.getRootTask();

    if (err != START_SUCCESS) {
        if (resultRecord != null) {
            resultRecord.sendResult(INVALID_UID, resultWho, requestCode, RESULT_CANCELED,
                    null /* data */, null /* dataGrants */);
        }
        SafeActivityOptions.abort(options);
        return err;
    }

//权限检查
    boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
            requestCode, callingPid, callingUid, callingPackage, callingFeatureId,
            request.ignoreTargetSecurity, inTask != null, callerApp, resultRecord,
            resultRootTask);
    abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
            callingPid, resolvedType, aInfo.applicationInfo);
    abort |= !mService.getPermissionPolicyInternal().checkStartActivity(intent, callingUid,
            callingPackage);

    boolean restrictedBgActivity = false;
    if (!abort) {
        try {
            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER,
                    "shouldAbortBackgroundActivityStart");
            restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid,
                    callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,
                    request.originatingPendingIntent, request.allowBackgroundActivityStart,
                    intent);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
        }
    }

    // Merge the two options bundles, while realCallerOptions takes precedence.
    ActivityOptions checkedOptions = options != null
            ? options.getOptions(intent, aInfo, callerApp, mSupervisor) : null;
    if (request.allowPendingRemoteAnimationRegistryLookup) {
        checkedOptions = mService.getActivityStartController()
                .getPendingRemoteAnimationRegistry()
                .overrideOptionsIfNeeded(callingPackage, checkedOptions);
    }
    if (mService.mController != null) {
        try {
            // The Intent we give to the watcher has the extra data stripped off, since it
            // can contain private information.
            Intent watchIntent = intent.cloneFilter();
            abort |= !mService.mController.activityStarting(watchIntent,
                    aInfo.applicationInfo.packageName);
        } catch (RemoteException e) {
            mService.mController = null;
        }
    }

    mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage,
            callingFeatureId);
    if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid,
            callingUid, checkedOptions)) {
        // activity start was intercepted, e.g. because the target user is currently in quiet
        // mode (turn off work) or the target application is suspended
        intent = mInterceptor.mIntent;
        rInfo = mInterceptor.mRInfo;
        aInfo = mInterceptor.mAInfo;
        resolvedType = mInterceptor.mResolvedType;
        inTask = mInterceptor.mInTask;
        callingPid = mInterceptor.mCallingPid;
        callingUid = mInterceptor.mCallingUid;
        checkedOptions = mInterceptor.mActivityOptions;

        // The interception target shouldn't get any permission grants
        // intended for the original destination
        intentGrants = null;
    }

    if (abort) {
        if (resultRecord != null) {
            resultRecord.sendResult(INVALID_UID, resultWho, requestCode, RESULT_CANCELED,
                    null /* data */, null /* dataGrants */);
        }
        // We pretend to the caller that it was really started, but they will just get a
        // cancel result.
        ActivityOptions.abort(checkedOptions);
        return START_ABORTED;
    }

    // If permissions need a review before any of the app components can run, we
    // launch the review activity and pass a pending intent to start the activity
    // we are to launching now after the review is completed.
    if (aInfo != null) {
        if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
                aInfo.packageName, userId)) {
            final IIntentSender target = mService.getIntentSenderLocked(
                    ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, callingFeatureId,
                    callingUid, userId, null, null, 0, new Intent[]{intent},
                    new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
                            | PendingIntent.FLAG_ONE_SHOT, null);

            Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);

            int flags = intent.getFlags();
            flags |= Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;

            /*
             * Prevent reuse of review activity: Each app needs their own review activity. By
             * default activities launched with NEW_TASK or NEW_DOCUMENT try to reuse activities
             * with the same launch parameters (extras are ignored). Hence to avoid possible
             * reuse force a new activity via the MULTIPLE_TASK flag.
             *
             * Activities that are not launched with NEW_TASK or NEW_DOCUMENT are not re-used,
             * hence no need to add the flag in this case.
             */
            if ((flags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NEW_DOCUMENT)) != 0) {
                flags |= Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
            }
            newIntent.setFlags(flags);

            newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
            newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
            if (resultRecord != null) {
                newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
            }
            intent = newIntent;

            // The permissions review target shouldn't get any permission
            // grants intended for the original destination
            intentGrants = null;

            resolvedType = null;
            callingUid = realCallingUid;
            callingPid = realCallingPid;

            rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 0,
                    computeResolveFilterUid(
                            callingUid, realCallingUid, request.filterCallingUid));
            aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
                    null /*profilerInfo*/);

            if (DEBUG_PERMISSIONS_REVIEW) {
                final Task focusedRootTask =
                        mRootWindowContainer.getTopDisplayFocusedRootTask();
                Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
                        true, false) + "} from uid " + callingUid + " on display "
                        + (focusedRootTask == null ? DEFAULT_DISPLAY
                                : focusedRootTask.getDisplayId()));
            }
        }
    }

    // If we have an ephemeral app, abort the process of launching the resolved intent.
    // Instead, launch the ephemeral installer. Once the installer is finished, it
    // starts either the intent we resolved here [on install error] or the ephemeral
    // app [on install success].
    if (rInfo != null && rInfo.auxiliaryInfo != null) {
        intent = createLaunchIntent(rInfo.auxiliaryInfo, request.ephemeralIntent,
                callingPackage, callingFeatureId, verificationBundle, resolvedType, userId);
        resolvedType = null;
        callingUid = realCallingUid;
        callingPid = realCallingPid;

        // The ephemeral installer shouldn't get any permission grants
        // intended for the original destination
        intentGrants = null;

        aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
    }
    // TODO (b/187680964) Correcting the caller/pid/uid when start activity from shortcut
    // Pending intent launched from systemui also depends on caller app
    if (callerApp == null && realCallingPid > 0) {
        final WindowProcessController wpc = mService.mProcessMap.getProcess(realCallingPid);
        if (wpc != null) {
            callerApp = wpc;
        }
    }
    
    //通过层层判断OK则创建ActivityRecord
    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 (!restrictedBgActivity && !isHomeProcess) {
        mService.resumeAppSwitches();
    }

 //开始启动startActivity
    mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
            request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
            restrictedBgActivity, intentGrants);

    if (request.outActivity != null) {
        request.outActivity[0] = mLastStartActivityRecord;
    }

    return mLastStartActivityResult;
}


ActivityStarter.startActivityUnchecked()

/**
 * Start an activity while most of preliminary checks has been done and caller has been
 * confirmed that holds necessary permissions to do so.
 * Here also ensures that the starting activity is removed if the start wasn't successful.
 */
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, Task inTask,
            boolean restrictedBgActivity, NeededUriGrants intentGrants) {
    int result = START_CANCELED;
    final Task startedActivityRootTask;

    // Create a transition now to record the original intent of actions taken within
    // startActivityInner. Otherwise, logic in startActivityInner could start a different
    // transition based on a sub-action.
    // Only do the create here (and defer requestStart) since startActivityInner might abort.
    final Transition newTransition = (!mService.getTransitionController().isCollecting()
            && mService.getTransitionController().getTransitionPlayer() != null)
            ? mService.getTransitionController().createTransition(TRANSIT_OPEN) : null;
    IRemoteTransition remoteTransition = r.takeRemoteTransition();
    if (newTransition != null && remoteTransition != null) {
        newTransition.setRemoteTransition(remoteTransition);
    }
    mService.getTransitionController().collect(r);
    try {
        mService.deferWindowLayout();
        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
        result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
        startedActivityRootTask = handleStartResult(r, result);
        mService.continueWindowLayout();
        mSupervisor.mUserLeaving = false;

        // Transition housekeeping
        if (!ActivityManager.isStartResultSuccessful(result)) {
            if (newTransition != null) {
                newTransition.abort();
            }
        } else {
            if (!mAvoidMoveToFront && mDoResume
                    && mRootWindowContainer.hasVisibleWindowAboveButDoesNotOwnNotificationShade(
                        r.launchedFromUid)) {
                // If the UID launching the activity has a visible window on top of the
                // notification shade and it's launching an activity that's going to be at the
                // front, we should move the shade out of the way so the user can see it.
                // We want to avoid the case where the activity is launched on top of a
                // background task which is not moved to the front.
                StatusBarManagerInternal statusBar = mService.getStatusBarManagerInternal();
                if (statusBar != null) {
                    // This results in a async call since the interface is one-way
                    statusBar.collapsePanels();
                }
            }
            if (result == START_SUCCESS || result == START_TASK_TO_FRONT) {
                // The activity is started new rather than just brought forward, so record
                // it as an existence change.
                mService.getTransitionController().collectExistenceChange(r);
            }
            if (newTransition != null) {
                mService.getTransitionController().requestStartTransition(newTransition,
                        mTargetTask, remoteTransition);
            } else {
                // Make the collecting transition wait until this request is ready.
                mService.getTransitionController().setReady(false);
            }
        }
    }

    postStartActivityProcessing(r, result, startedActivityRootTask);

    return result;
}

ActivityStarter.startActivityInner()

int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, Task inTask,
        boolean restrictedBgActivity, NeededUriGrants intentGrants) {
    setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
            voiceInteractor, restrictedBgActivity);

    computeLaunchingTaskFlags();

    computeSourceRootTask();

    mIntent.setFlags(mLaunchFlags);

    final Task reusedTask = getReusableTask();

    // 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) {
        return startResult;
    }

    final ActivityRecord targetTaskTop = newTask
            ? null : targetTask.getTopNonFinishingActivity();
    if (targetTaskTop != null) {
        // Recycle the target task for this launch.
        startResult = recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants);
        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 = getLaunchRootTask(mStartActivity, mLaunchFlags, targetTask, mOptions);
    }
    if (newTask) {
        final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
                ? mSourceRecord.getTask() : null;
        setNewTask(taskToAffiliate);
    } else if (mAddingToTask) {
        addOrReparentStartingActivity(targetTask, "adding to task");
    }

    if (!mAvoidMoveToFront && mDoResume) {
        mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask);
        if (mOptions != null) {
            if (mOptions.getTaskAlwaysOnTop()) {
                mTargetRootTask.setAlwaysOnTop(true);
            }
        }
        if (!mTargetRootTask.isTopRootTaskInDisplayArea() && mService.mInternal.isDreaming()) {
            // 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;
        }
    }

    mService.mUgmInternal.grantUriPermissionUncheckedFromIntent(intentGrants,
            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,
                UserHandle.getAppId(mStartActivity.info.applicationInfo.uid) /*recipient*/,
                resultToUid /*visible*/, true /*direct*/);
    }
    if (newTask) {
        EventLogTags.writeWmCreateTask(mStartActivity.mUserId,
                mStartActivity.getTask().mTaskId);
    }
    mStartActivity.logStartActivity(
            EventLogTags.WM_CREATE_ACTIVITY, mStartActivity.getTask());

    mTargetRootTask.mLastPausedActivity = null;

    mRootWindowContainer.startPowerModeLaunchIfNeeded(
            false /* forceSend */, mStartActivity);

    mTargetRootTask.startActivityLocked(mStartActivity,
            topRootTask != null ? topRootTask.getTopNonFinishingActivity() : null, newTask,
            mKeepCurTransition, mOptions, sourceRecord);
    if (mDoResume) {
        final ActivityRecord topTaskActivity =
                mStartActivity.getTask().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 */,
                    0 /* configChanges */, !PRESERVE_WINDOWS);
            // 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)) {
                mTargetRootTask.moveToFront("startActivityInner");
            }
            mRootWindowContainer.resumeFocusedTasksTopActivities(
                    mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
        }
    }
    mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask);

    // Update the recent tasks list immediately when the activity starts
    mSupervisor.mRecentTasks.add(mStartActivity.getTask());
    mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(),
            mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetRootTask);

    return START_SUCCESS;
}

Activty需要创建 mTargetRootTask.startActivityLocked(mStartActivity, topRootTask != null ? topRootTask.getTopNonFinishingActivity() : null, newTask, mKeepCurTransition, mOptions, sourceRecord);

Activity存在只需resume RootWindowContainer.resumeFocusedTasksTopActivities ->RootWindowContainer.resumeTopActivityUncheckedLocked

boolean resumeFocusedTasksTopActivities(
        Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,
        boolean deferPause) {
    if (!mTaskSupervisor.readyToResume()) {
        return false;
    }

    boolean result = false;
    if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
            || getTopDisplayFocusedRootTask() == targetRootTask)) {
        result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,
                deferPause);
    }

    for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
        final DisplayContent display = getChildAt(displayNdx);
        final boolean curResult = result;
        boolean[] resumedOnDisplay = new boolean[1];
        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[0] |= curResult;
                return;
            }
            if (rootTask.getDisplayArea().isTopRootTask(rootTask)
                    && topRunningActivity.isState(RESUMED)) {
                // Kick off any lingering app transitions form the MoveTaskToFront
                // operation, but only consider the top task and root-task on that
                // display.
                rootTask.executeAppTransition(targetOptions);
            } else {
                resumedOnDisplay[0] |= topRunningActivity.makeActiveIfNeeded(target);
            }
        });
        result |= resumedOnDisplay[0];
        if (!resumedOnDisplay[0]) {
            // 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);
            } else if (targetRootTask == null) {
                result |= resumeHomeActivity(null /* prev */, "no-focusable-task",
                        display.getDefaultTaskDisplayArea());
            }
        }
    }

    return result;
}


//////resumeTopActivityUncheckedLocked
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_VISIBILITY_VISIBLE) {
                    break;
                }

                someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options,
                        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;
}





////resumeTopActivityInnerLocked
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
        boolean deferPause) {
    if (!mAtmService.isBooting() && !mAtmService.isBooted()) {
        // Not ready yet!
        return false;
    }

    // Find the next top-most activity to resume in this root task that is not finishing and is
    // focusable. If it is not focusable, we will fall into the case below to resume the
    // top activity in the next focusable task.
    ActivityRecord next = topRunningActivity(true /* focusableOnly */);

    final boolean hasRunningActivity = next != null;

    // TODO: Maybe this entire condition can get removed?
    if (hasRunningActivity && !isAttached()) {
        return false;
    }

    mRootWindowContainer.cancelInitializingActivities();

    if (!hasRunningActivity) {
        // There are no activities left in the root task, let's look somewhere else.
        return resumeNextFocusableActivityWhenRootTaskIsEmpty(prev, options);
    }

    next.delayedResume = false;
    final TaskDisplayArea taskDisplayArea = getDisplayArea();

    // If the top activity is the resumed one, nothing to do.
    if (mResumedActivity == next && next.isState(RESUMED)
            && taskDisplayArea.allResumedActivitiesComplete()) {
        // Make sure we have executed any pending transitions, since there
        // should be nothing left to do at this point.
        executeAppTransition(options);
        // For devices that are not in fullscreen mode (e.g. freeform windows), it's possible
        // we still want to check if the visibility of other windows have changed (e.g. bringing
        // a fullscreen window forward to cover another freeform activity.)
        if (taskDisplayArea.inMultiWindowMode()) {
            taskDisplayArea.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
                    false /* preserveWindows */, true /* notifyClients */);
        }
        ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Top activity "
                + "resumed %s", next);
        return false;
    }

    if (!next.canResumeByCompat()) {
        return false;
    }

    // If we are currently pausing an activity, then don't do anything until that is done.
    final boolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete();
    if (!allPausedComplete) {
        ProtoLog.v(WM_DEBUG_STATES,
                "resumeTopActivityLocked: Skip resume: some activity pausing.");

        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, "resumeTopActivityLocked: 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 != getRootTask()) {
        // 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.getResumedActivity();
    }

    boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);
    if (mResumedActivity != null) {
        ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Pausing %s", mResumedActivity);
        pausing |= startPausingLocked(false /* uiSleeping */, next,
                "resumeTopActivityInnerLocked");
    }
    if (pausing) {
        ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivityLocked: 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 */,
                    true /* activityChange */, false /* updateOomAdj */,
                    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,
                    isTop ? "pre-top-activity" : "pre-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, "resumeTopActivityLocked: 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);
        }

    }

    // Launching this app's activity, make sure the app is no longer
    // considered stopped.
    try {
        mTaskSupervisor.getActivityMetricsLogger()
                .notifyBeforePackageUnstopped(next.packageName);
        mAtmService.getPackageManager().setPackageStoppedState(
                next.packageName, false, next.mUserId); /* TODO: Verify if correct userid */
    } catch (RemoteException e1) {
    } 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,
                        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.stopped
                + " visibleRequested=" + next.mVisibleRequested);

        // 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 = lastFocusedRootTask != null
                && (lastFocusedRootTask.inMultiWindowMode()
                || (lastFocusedRootTask.mLastPausedActivity != null
                && !lastFocusedRootTask.mLastPausedActivity.occludesParent()));

        // This activity is now becoming visible.
        if (!next.mVisibleRequested || next.stopped || lastActivityTranslucent) {
            next.setVisibility(true);
        }

        // schedule launch ticks to collect information about slow apps.
        next.startLaunchTickingLocked();

        ActivityRecord lastResumedActivity =
                lastFocusedRootTask == null ? null : lastFocusedRootTask.getResumedActivity();
        final ActivityState lastState = next.getState();

        mAtmService.updateCpuStats();

        ProtoLog.v(WM_DEBUG_STATES, "Moving to RESUMED: %s (in existing)", next);

        next.setState(RESUMED, "resumeTopActivityInnerLocked");

        // Have the window manager re-evaluate the orientation of
        // the screen based on the new activity order.
        boolean notUpdated = true;

        // 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.
            notUpdated = !mRootWindowContainer.ensureVisibilityAndConfig(next, getDisplayId(),
                    true /* markFrozenIfConfigChanged */, false /* deferResume */);
        }

        if (notUpdated) {
            // The configuration update wasn't able to keep the existing
            // instance of the activity, and instead started a new one.
            // We should be all done, but let's just make sure our activity
            // is still at the top and schedule another run if something
            // weird happened.
            ActivityRecord nextNext = topRunningActivity();
            ProtoLog.i(WM_DEBUG_STATES, "Activity config changed during resume: "
                    + "%s, new next: %s", next, nextNext);
            if (nextNext != next) {
                // Do over!
                mTaskSupervisor.scheduleResumeTopActivities();
            }
            if (!next.mVisibleRequested || next.stopped) {
                next.setVisibility(true);
            }
            next.completeResumeLocked();
            return true;
        }

        try {
            final ClientTransaction transaction =
                    ClientTransaction.obtain(next.app.getThread(), next.appToken);
            // Deliver all pending results.
            ArrayList<ResultInfo> a = next.results;
            if (a != null) {
                final int N = a.size();
                if (!next.finishing && N > 0) {
                    if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                            "Delivering results to " + next + ": " + a);
                    transaction.addCallback(ActivityResultItem.obtain(a));
                }
            }

            if (next.newIntents != null) {
                transaction.addCallback(
                        NewIntentItem.obtain(next.newIntents, true /* resume */));
            }

            // Well the app will no longer be stopped.
            // Clear app token stopped state in window manager if needed.
            next.notifyAppResumed(next.stopped);

            EventLogTags.writeWmResumeActivity(next.mUserId, System.identityHashCode(next),
                    next.getTask().mTaskId, next.shortComponentName);

            mAtmService.getAppWarningsLocked().onResumeActivity(next);
            next.app.setPendingUiCleanAndForceProcessStateUpTo(mAtmService.mTopProcessState);
            next.abortAndClearOptionsAnimation();
            transaction.setLifecycleStateRequest(
                    ResumeActivityItem.obtain(next.app.getReportedProcState(),
                            dc.isNextTransitionForward()));
            mAtmService.getLifecycleManager().scheduleTransaction(transaction);

            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: 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;
        }

        // From this point on, if something goes wrong there is no way
        // to recover the activity.
        try {
            next.completeResumeLocked();
        } catch (Exception e) {
            // If any exception gets thrown, toss away this
            // activity and try the next one.
            Slog.w(TAG, "Exception thrown during resume of " + next, e);
            next.finishIfPossible("resume-exception", true /* oomAdj */);
            return true;
        }
    } 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, "resumeTopActivityLocked: Restarting %s", next);
        mTaskSupervisor.startSpecificActivity(next, true, true);
    }

    return true;
}

ActivityTaskSupervisor.startSpecificActivity -> ActivityTaskSupervisor.realStartActivityLocked

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;
        } 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;
    }

    r.notifyUnknownVisibilityLaunchedForKeyguardTransition();

    final boolean isTop = andResume && r.isTopRunningActivity();
    // 创建进程
    mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}



boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
        boolean andResume, boolean checkConfig) throws RemoteException {

    if (!mRootWindowContainer.allPausedActivitiesComplete()) {
        // While there are activities pausing we skipping starting any new activities until
        // pauses are complete. NOTE: that we also do this for activities that are starting in
        // the paused state because they will first be resumed then paused on the client side.
        ProtoLog.v(WM_DEBUG_STATES,
                "realStartActivityLocked: Skipping start of r=%s some activities pausing...",
                r);
        return false;
    }

    final Task task = r.getTask();
    final Task rootTask = task.getRootTask();

    beginDeferResume();
    // The LaunchActivityItem also contains process configuration, so the configuration change
    // from WindowProcessController#setProcess can be deferred. The major reason is that if
    // the activity has FixedRotationAdjustments, it needs to be applied with configuration.
    // In general, this reduces a binder transaction if process configuration is changed.
    proc.pauseConfigurationDispatch();

    try {
        r.startFreezingScreenLocked(proc, 0);

        // schedule launch ticks to collect information about slow apps.
        r.startLaunchTickingLocked();

        r.setProcess(proc);

        // Ensure activity is allowed to be resumed after process has set.
        if (andResume && !r.canResumeByCompat()) {
            andResume = false;
        }

        r.notifyUnknownVisibilityLaunchedForKeyguardTransition();

        // Have the window manager re-evaluate the orientation of the screen based on the new
        // activity order.  Note that as a result of this, it can call back into the activity
        // manager with a new orientation.  We don't care about that, because the activity is
        // not currently running so we are just restarting it anyway.
        if (checkConfig) {
            // Deferring resume here because we're going to launch new activity shortly.
            // We don't want to perform a redundant launch of the same record while ensuring
            // configurations and trying to resume top activity of focused root task.
            mRootWindowContainer.ensureVisibilityAndConfig(r, r.getDisplayId(),
                    false /* markFrozenIfConfigChanged */, true /* deferResume */);
        }

        if (mKeyguardController.checkKeyguardVisibility(r) && r.allowMoveToFront()) {
            // We only set the visibility to true if the activity is not being launched in
            // background, and is allowed to be visible based on keyguard state. This avoids
            // setting this into motion in window manager that is later cancelled due to later
            // calls to ensure visible activities that set visibility back to false.
            r.setVisibility(true);
        }

        final int applicationInfoUid =
                (r.info.applicationInfo != null) ? r.info.applicationInfo.uid : -1;
        if ((r.mUserId != proc.mUserId) || (r.info.applicationInfo.uid != applicationInfoUid)) {
            Slog.wtf(TAG,
                    "User ID for activity changing for " + r
                            + " appInfo.uid=" + r.info.applicationInfo.uid
                            + " info.ai.uid=" + applicationInfoUid
                            + " old=" + r.app + " new=" + proc);
        }

        // Send the controller to client if the process is the first time to launch activity.
        // So the client can save binder transactions of getting the controller from activity
        // task manager service.
        final IActivityClientController activityClientController =
                proc.hasEverLaunchedActivity() ? null : mService.mActivityClientController;
        r.launchCount++;
        r.lastLaunchTime = SystemClock.uptimeMillis();
        proc.setLastActivityLaunchTime(r.lastLaunchTime);

        if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r);

        final LockTaskController lockTaskController = mService.getLockTaskController();
        if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
                || task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV
                || (task.mLockTaskAuth == LOCK_TASK_AUTH_ALLOWLISTED
                        && lockTaskController.getLockTaskModeState()
                                == LOCK_TASK_MODE_LOCKED)) {
            lockTaskController.startLockTaskMode(task, false, 0 /* blank UID */);
        }

        try {
            if (!proc.hasThread()) {
                throw new RemoteException();
            }
            List<ResultInfo> results = null;
            List<ReferrerIntent> newIntents = null;
            if (andResume) {
                // We don't need to deliver new intents and/or set results if activity is going
                // to pause immediately after launch.
                results = r.results;
                newIntents = r.newIntents;
            }
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                    "Launching: " + r + " savedState=" + r.getSavedState()
                            + " with results=" + results + " newIntents=" + newIntents
                            + " andResume=" + andResume);
            EventLogTags.writeWmRestartActivity(r.mUserId, System.identityHashCode(r),
                    task.mTaskId, r.shortComponentName);
            if (r.isActivityTypeHome()) {
                // Home process is the root process of the task.
                updateHomeProcess(task.getBottomMostActivity().app);
            }
            mService.getPackageManagerInternalLocked().notifyPackageUse(
                    r.intent.getComponent().getPackageName(), NOTIFY_PACKAGE_USE_ACTIVITY);
            r.forceNewConfig = false;
            mService.getAppWarningsLocked().onStartActivity(r);
            r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);

            // Because we could be starting an Activity in the system process this may not go
            // across a Binder interface which would create a new Configuration. Consequently
            // we have to always create a new Configuration here.
            final Configuration procConfig = proc.prepareConfigurationForLaunchingActivity();
            final MergedConfiguration mergedConfiguration = new MergedConfiguration(
                    procConfig, r.getMergedOverrideConfiguration());
            r.setLastReportedConfiguration(mergedConfiguration);

            logIfTransactionTooLarge(r.intent, r.getSavedState());


            // Create activity launch transaction.
            final ClientTransaction clientTransaction = ClientTransaction.obtain(
                    proc.getThread(), r.appToken);

            final boolean isTransitionForward = r.isTransitionForward();
            clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                    System.identityHashCode(r), r.info,
                    // TODO: Have this take the merged configuration instead of separate global
                    // and override configs.
                    mergedConfiguration.getGlobalConfiguration(),
                    mergedConfiguration.getOverrideConfiguration(), r.compat,
                    r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
                    r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
                    r.takeOptions(), isTransitionForward,
                    proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
                    r.createFixedRotationAdjustmentsIfNeeded(), r.shareableActivityToken,
                    r.getLaunchedFromBubble()));

            // Set desired final state.
            final ActivityLifecycleItem lifecycleItem;
            if (andResume) {
                lifecycleItem = ResumeActivityItem.obtain(isTransitionForward);
            } else {
                lifecycleItem = PauseActivityItem.obtain();
            }
            clientTransaction.setLifecycleStateRequest(lifecycleItem);

            // Schedule transaction.
            mService.getLifecycleManager().scheduleTransaction(clientTransaction);

            if (procConfig.seq > mRootWindowContainer.getConfiguration().seq) {
                // If the seq is increased, there should be something changed (e.g. registered
                // activity configuration).
                proc.setLastReportedConfiguration(procConfig);
            }
            if ((proc.mInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0
                    && mService.mHasHeavyWeightFeature) {
                // This may be a heavy-weight process! Note that the package manager will ensure
                // that only activity can run in the main process of the .apk, which is the only
                // thing that will be considered heavy-weight.
                if (proc.mName.equals(proc.mInfo.packageName)) {
                    if (mService.mHeavyWeightProcess != null
                            && mService.mHeavyWeightProcess != proc) {
                        Slog.w(TAG, "Starting new heavy weight process " + proc
                                + " when already running "
                                + mService.mHeavyWeightProcess);
                    }
                    mService.setHeavyWeightProcess(r);
                }
            }

        } catch (RemoteException e) {
            if (r.launchFailed) {
                // This is the second time we failed -- finish activity and give up.
                Slog.e(TAG, "Second failure launching "
                        + r.intent.getComponent().flattenToShortString() + ", giving up", e);
                proc.appDied("2nd-crash");
                r.finishIfPossible("2nd-crash", false /* oomAdj */);
                return false;
            }

            // This is the first time we failed -- restart process and
            // retry.
            r.launchFailed = true;
            proc.removeActivity(r, true /* keepAssociation */);
            throw e;
        }
    } finally {
        endDeferResume();
        proc.resumeConfigurationDispatch();
    }

    r.launchFailed = false;

    // TODO(lifecycler): Resume or pause requests are done as part of launch transaction,
    // so updating the state should be done accordingly.
    if (andResume && readyToResume()) {
        // As part of the process of launching, ActivityThread also performs
        // a resume.
        rootTask.minimalResumeActivityLocked(r);
    } else {
        // This activity is not starting in the resumed state... which should look like we asked
        // it to pause+stop (but remain visible), and it has done so and reported back the
        // current icicle and other state.
        ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSED: %s "
                + "(starting in paused state)", r);
        r.setState(PAUSED, "realStartActivityLocked");
        mRootWindowContainer.executeAppTransitionForAllDisplay();
    }
    // Perform OOM scoring after the activity state is set, so the process can be updated with
    // the latest state.
    proc.onStartActivity(mService.mTopProcessState, r.info);

    // Launch the new version setup screen if needed.  We do this -after-
    // launching the initial activity (that is, home), so that it can have
    // a chance to initialize itself while in the background, making the
    // switch back to it faster and look better.
    if (mRootWindowContainer.isTopDisplayFocusedRootTask(rootTask)) {
        mService.getActivityStartController().startSetupActivity();
    }

    // Update any services we are bound to that might care about whether
    // their client may have activities.
    if (r.app != null) {
        r.app.updateServiceConnectionActivities();
    }

    return true;
}

realStartActivityLocked 方法本身并不直接调用 Activity 的生命周期函数,它的核心工作是构造并发送一个启动事务。你可以将它看作系统服务为此次启动创建并发送的一份“执行计划书”

1. 构造事务 (在 realStartActivityLocked 中)

在 ActivityTaskSupervisor.realStartActivityLocked 方法中,系统会做两件关键的事

  • 创建 ClientTransaction 对象:这是一个事务容器,用来承载所有需要执行的操作。
  • 向事务中添加执行项 (Callback) :通过 clientTransaction.addCallback(LaunchActivityItem.obtain(...)),向事务中添加一个 LaunchActivityItem。这个 LaunchActivityItem 指明了要执行的动作——在目标应用进程中创建并启动 Activity
  • 设置最终状态 (LifecycleState)clientTransaction.setLifecycleStateRequest(ResumeActivityItem.obtain(...))ResumeActivityItem 指明了事务执行完毕后,Activity 应该达到的最终生命周期状态——RESUMED

2. 调度与执行 (事务的跨进程传递)

事务构造完成后,系统会通过以下路径将其调度到应用进程:

  • mService.getLifecycleManager().scheduleTransaction(clientTransaction) 这个方法通过 ClientLifecycleManager 将事务发送出去。
  • 事务最终会通过 Binder 调用,传递到目标应用进程的 ActivityThread 内部类 ApplicationThread 的 scheduleTransaction 方法。到这里,流程就从系统服务进程跨到了应用进程。

3. 应用进程处理事务 (回到 ActivityThread)

在应用进程这边,ActivityThread 的主线程 Handler (H) 会收到一个 EXECUTE_TRANSACTION 消息,然后由 TransactionExecutor 来负责真正执行事务里的

  • 执行 LaunchActivityItemTransactionExecutor 会按顺序执行事务中的 CallbackLaunchActivityItem 的 execute 方法会调用 ActivityThread 的 handleLaunchActivity 

    1. 通过反射创建 Activity 实例。
    2. 初始化 PhoneWindow 和 ContextImpl
    3. 回调 onCreate()
    4. 回调 onStart()
  • 执行 ResumeActivityItem:在 LaunchActivityItem 执行完毕后,TransactionExecutor 会处理事务的最终状态请求,即执行 ResumeActivityItem。它的 execute 方法最终会调用到 ActivityThread 的 handleResumeActivity 方法。在这里,系统会:

    1. 回调 onResume()

    2. 将 DecorView 添加到 WindowManager,使 Activity 的界面真正变得可见并可交互。

进程没有创建,则需要创建进程,等进程创建完再启动Activity ActivityTaskManagerService.startProcessAsync

void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
        String hostingType) {
    try {
        if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "dispatchingStartProcess:"
                    + 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());
        mH.sendMessage(m);
    } finally {
        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
    }
}

ActivityManagerService.startProcess

public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead,
        boolean isTop, String hostingType, ComponentName hostingName) {
    try {
        if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "startProcess:"
                    + processName);
        }
        synchronized (ActivityManagerService.this) {
            // If the process is known as top app, set a hint so when the process is
            // started, the top priority can be applied immediately to avoid cpu being
            // preempted by other processes before attaching the process of top app.
            startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
                    new HostingRecord(hostingType, hostingName, isTop),
                    ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,
                    false /* isolated */);
        }
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }
}

ProcessList.startProcessLocked -> ProcessList.startProcess ->Process.start()

boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app,
        int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal,
        String seInfo, String requiredAbi, String instructionSet, String invokeWith,
        long startTime) {
    app.setPendingStart(true);
    app.setRemoved(false);
    synchronized (mProcLock) {
      .....

   
        try {
            final Process.ProcessStartResult startResult = startProcess(hostingRecord,
                    entryPoint, app,
                    uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,
                    requiredAbi, instructionSet, invokeWith, startTime);
            handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
                    startSeq, false);
        } catch (RuntimeException e) {
            Slog.e(ActivityManagerService.TAG, "Failure starting process "
                    + app.processName, e);
            app.setPendingStart(false);
            mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
                    false, false, true, false, false, app.userId, "start failure");
        }
        return app.getPid() > 0;
    }
}




private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
        ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags,
        int mountExternal, String seInfo, String requiredAbi, String instructionSet,
        String invokeWith, long startTime) {
    try {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                app.processName);
        checkSlow(startTime, "startProcess: asking zygote to start proc");
        final boolean isTopApp = hostingRecord.isTopApp();
        if (isTopApp) {
            // Use has-foreground-activities as a temporary hint so the current scheduling
            // group won't be lost when the process is attaching. The actual state will be
            // refreshed when computing oom-adj.
            app.mState.setHasForegroundActivities(true);
        }

        Map<String, Pair<String, Long>> pkgDataInfoMap;
        Map<String, Pair<String, Long>> allowlistedAppDataInfoMap;
        boolean bindMountAppStorageDirs = false;
        boolean bindMountAppsData = mAppDataIsolationEnabled
                && (UserHandle.isApp(app.uid) || UserHandle.isIsolated(app.uid))
                && mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info);

        // Get all packages belongs to the same shared uid. sharedPackages is empty array
        // if it doesn't have shared uid.
        final PackageManagerInternal pmInt = mService.getPackageManagerInternal();
        final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
                app.info.packageName, app.userId);
        final String[] targetPackagesList = sharedPackages.length == 0
                ? new String[]{app.info.packageName} : sharedPackages;

        pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, targetPackagesList, uid);
        if (pkgDataInfoMap == null) {
            // TODO(b/152760674): Handle inode == 0 case properly, now we just give it a
            // tmp free pass.
            bindMountAppsData = false;
        }

        // Remove all packages in pkgDataInfoMap from mAppDataIsolationAllowlistedApps, so
        // it won't be mounted twice.
        final Set<String> allowlistedApps = new ArraySet<>(mAppDataIsolationAllowlistedApps);
        for (String pkg : targetPackagesList) {
            allowlistedApps.remove(pkg);
        }

        allowlistedAppDataInfoMap = getPackageAppDataInfoMap(pmInt,
                allowlistedApps.toArray(new String[0]), uid);
        if (allowlistedAppDataInfoMap == null) {
            // TODO(b/152760674): Handle inode == 0 case properly, now we just give it a
            // tmp free pass.
            bindMountAppsData = false;
        }

        int userId = UserHandle.getUserId(uid);
        StorageManagerInternal storageManagerInternal = LocalServices.getService(
                StorageManagerInternal.class);
        if (needsStorageDataIsolation(storageManagerInternal, app)) {
            // We will run prepareStorageDirs() after we trigger zygote fork, so it won't
            // slow down app starting speed as those dirs might not be cached.
            if (pkgDataInfoMap != null && storageManagerInternal.isFuseMounted(userId)) {
                bindMountAppStorageDirs = true;
            } else {
                // Fuse is not mounted or inode == 0,
                // so we won't mount it in zygote, but resume the mount after unlocking device.
                app.setBindMountPending(true);
                bindMountAppStorageDirs = false;
            }
        }

        // If it's an isolated process, it should not even mount its own app data directories,
        // since it has no access to them anyway.
        if (app.isolated) {
            pkgDataInfoMap = null;
            allowlistedAppDataInfoMap = null;
        }

        final Process.ProcessStartResult startResult;
        boolean regularZygote = false;
        if (hostingRecord.usesWebviewZygote()) {
            startResult = startWebView(entryPoint,
                    app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                    app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                    app.info.dataDir, null, app.info.packageName,
                    app.getDisabledCompatChanges(),
                    new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
        } else if (hostingRecord.usesAppZygote()) {
            final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);

            // We can't isolate app data and storage data as parent zygote already did that.
            startResult = appZygote.getProcess().start(entryPoint,
                    app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                    app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                    app.info.dataDir, null, app.info.packageName,
                    /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
                    app.getDisabledCompatChanges(), pkgDataInfoMap, allowlistedAppDataInfoMap,
                    false, false,
                    new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
        } else {
            regularZygote = true;
            startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                    app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                    app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
                    isTopApp, app.getDisabledCompatChanges(), pkgDataInfoMap,
                    allowlistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
                    new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
        }

        if (!regularZygote) {
            // webview and app zygote don't have the permission to create the nodes
            if (Process.createProcessGroup(uid, startResult.pid) < 0) {
                Slog.e(ActivityManagerService.TAG, "Unable to create process group for "
                        + app.processName + " (" + startResult.pid + ")");
            }
        }

        // This runs after Process.start() as this method may block app process starting time
        // if dir is not cached. Running this method after Process.start() can make it
        // cache the dir asynchronously, so zygote can use it without waiting for it.
        if (bindMountAppStorageDirs) {
            storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(),
                    app.processName);
        }
        checkSlow(startTime, "startProcess: returned from zygote!");
        return startResult;
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }
}

进程创建完以后会调用ActivityThread.main() ->ActivityThread.atach(false) ->ActivityManagerService.attachApplication()

public final void attachApplication(IApplicationThread thread, long startSeq) {
    if (thread == null) {
        throw new SecurityException("Invalid application interface");
    }
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        Binder.restoreCallingIdentity(origId);
    }
}

ActivityTaskManagerService.attachApplication()

public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
    synchronized (mGlobalLockWithoutBoost) {
        if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "attachApplication:" + wpc.mName);
        }
        try {
            return mRootWindowContainer.attachApplication(wpc);
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }
}

RootWindowContainer.attachApplication ->RootWindowContainer.startActivityForAttachedApplicationIfNeeded ->ActivityTaskSupervisor.realStartActivityLocked

boolean attachApplication(WindowProcessController app) throws RemoteException {
    boolean didSomething = false;
    for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
        mTmpRemoteException = null;
        mTmpBoolean = false; // Set to true if an activity was started.
        final DisplayContent display = getChildAt(displayNdx);
        display.forAllRootTasks(rootTask -> {
            if (mTmpRemoteException != null) {
                return;
            }

            if (rootTask.getVisibility(null /*starting*/) == TASK_VISIBILITY_INVISIBLE) {
                return;
            }

            final PooledFunction c = PooledLambda.obtainFunction(
                    RootWindowContainer::startActivityForAttachedApplicationIfNeeded, this,
                    PooledLambda.__(ActivityRecord.class), app,
                    rootTask.topRunningActivity());
            rootTask.forAllActivities(c);
            c.recycle();
        });
        if (mTmpRemoteException != null) {
            throw mTmpRemoteException;
        }
        didSomething |= mTmpBoolean;
    }
    if (!didSomething) {
        ensureActivitiesVisible(null, 0, false /* preserve_windows */);
    }
    return didSomething;
}



private boolean startActivityForAttachedApplicationIfNeeded(ActivityRecord r,
        WindowProcessController app, ActivityRecord top) {
    if (r.finishing || !r.okToShowLocked() || !r.visibleIgnoringKeyguard || r.app != null
            || app.mUid != r.info.applicationInfo.uid || !app.mName.equals(r.processName)) {
        return false;
    }

    try {
    //调用realStartActivityLocked回到文章上面
        if (mTaskSupervisor.realStartActivityLocked(r, app,
                top == r && r.isFocusable() /*andResume*/, true /*checkConfig*/)) {
            mTmpBoolean = true;
        }
    } catch (RemoteException e) {
        Slog.w(TAG, "Exception in new application when starting activity "
                + top.intent.getComponent().flattenToShortString(), e);
        mTmpRemoteException = e;
        return true;
    }
    return false;
}