realStartActivity 是由哪里触发的?

有两处可能触发 attach 和 pauseCompleted。 realStartActivity 需要两个条件触发。

  1. 进程已经创建好了。
  2. 其他 Activity 都 Paused 完了。

所以两者谁进行完之后,都可以对另一项进行检查,通过了就可以进行 realStartActivity。

场景 1:先 pause 完成

  • 栈顶 Activity 已经 pause 完成(activityPaused()activityPauseComplete()
  • 此时目标 Activity 对应的进程可能还没 attach,系统会等待 attach 发生
  • 一旦 attachApplicationLocked() 发生,就进入 resume 流程,调用 realStartActivityLocked()

场景 2:先 attach 完成

  • 系统收到 App attach(attachApplicationLocked()mAtmInternal.attachApplication()
  • 系统检测到目标 Activity 栈顶尚未 resumed
  • 如果之前已经 pause 完成,就可以立刻 resume → realStartActivityLocked()

以下为场景2过程: 可以看到在调用 startActivity 时会先让 activity Pause。

java 复制代码
schedulePauseActivity:1764, TaskFragment (com.android.server.wm)
startPausing:1708, TaskFragment (com.android.server.wm)
startPausing:1616, TaskFragment (com.android.server.wm)
lambda$pauseBackTasks$5:1286, TaskDisplayArea (com.android.server.wm)
$r8$lambda$m5XHJk9c1RGMj6XWeVM475WcQIg:-1, TaskDisplayArea (com.android.server.wm)
accept:-1, TaskDisplayArea$$ExternalSyntheticLambda9 (com.android.server.wm)
forAllLeafTaskFragments:1943, TaskFragment (com.android.server.wm)
lambda$pauseBackTasks$6:1283, TaskDisplayArea (com.android.server.wm)
$r8$lambda$Bbr_9JIpdvMngBiuBSXkHUu4nwk:-1, TaskDisplayArea (com.android.server.wm)
accept:-1, TaskDisplayArea$$ExternalSyntheticLambda6 (com.android.server.wm)
forAllLeafTasks:3170, Task (com.android.server.wm)
forAllLeafTasks:3158, Task (com.android.server.wm)
forAllLeafTasks:2033, WindowContainer (com.android.server.wm)
pauseBackTasks:1269, TaskDisplayArea (com.android.server.wm)
resumeTopActivity:1293, TaskFragment (com.android.server.wm)
resumeTopActivityInnerLocked:5017, Task (com.android.server.wm)
resumeTopActivityUncheckedLocked:4947, Task (com.android.server.wm)
resumeFocusedTasksTopActivities:2264, RootWindowContainer (com.android.server.wm)
startActivityInner:1971, ActivityStarter (com.android.server.wm)
startActivityUnchecked:1671, ActivityStarter (com.android.server.wm)
executeRequest:1224, ActivityStarter (com.android.server.wm)
execute:710, ActivityStarter (com.android.server.wm)
startActivityAsUser:1292, ActivityTaskManagerService (com.android.server.wm)
startActivityAsUser:1233, ActivityTaskManagerService (com.android.server.wm)
startActivity:1208, ActivityTaskManagerService (com.android.server.wm)
onTransact:896, IActivityTaskManager$Stub (android.app)
onTransact:5323, ActivityTaskManagerService (com.android.server.wm)
execTransactInternal:1280, Binder (android.os)
execTransact:1244, Binder (android.os)

上一个 Activity Paused 之后,回来到 startSpecificActivity 会判断线程是否存在。存在就热启动,直接寻找 Activity 打开。不存在就冷启动,fork 线程。 Is this activity's application already running?

java 复制代码
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;  
        // Remove the process record so it won't be considered as alive.  
        mService.mProcessNames.remove(wpc.mName, wpc.mUid);  
        mService.mProcessMap.remove(wpc.getPid());  
    }  
  
    r.notifyUnknownVisibilityLaunchedForKeyguardTransition();  
  
    final boolean isTop = andResume && r.isTopRunningActivity();  
    mService.startProcessAsync(r, knownToBeDead, isTop,  
            isTop ? HostingRecord.HOSTING_TYPE_TOP_ACTIVITY  
                    : HostingRecord.HOSTING_TYPE_ACTIVITY);  
}
java 复制代码
final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,  
                                boolean deferPause) {  
    ActivityRecord next = topRunningActivity(true /* focusableOnly */);

启动新的进程。

java 复制代码
startSpecificActivity:1065, ActivityTaskSupervisor (com.android.server.wm)
resumeTopActivity:1581, TaskFragment (com.android.server.wm)
resumeTopActivityInnerLocked:5017, Task (com.android.server.wm)
resumeTopActivityUncheckedLocked:4947, Task (com.android.server.wm)
resumeFocusedTasksTopActivities:2264, RootWindowContainer (com.android.server.wm)
resumeFocusedTasksTopActivities:2250, RootWindowContainer (com.android.server.wm)
completePause:1839, TaskFragment (com.android.server.wm)
activityPaused:6197, ActivityRecord (com.android.server.wm)
activityPaused:190, ActivityClientController (com.android.server.wm)
onTransact:609, IActivityClientController$Stub (android.app)
onTransact:127, ActivityClientController (com.android.server.wm)
execTransactInternal:1280, Binder (android.os)
execTransact:1244, Binder (android.os)

首次启动的 realStartActivity。FallbackHome Paused 到 launcher Launch 。 下面是线程存在的情况。

java 复制代码
realStartActivityLocked:929, ActivityTaskSupervisor (com.android.server.wm)
startSpecificActivity:1047, ActivityTaskSupervisor (com.android.server.wm)
resumeTopActivity:1581, TaskFragment (com.android.server.wm)
resumeTopActivityInnerLocked:5017, Task (com.android.server.wm)
resumeTopActivityUncheckedLocked:4947, Task (com.android.server.wm)
resumeTopActivityUncheckedLocked:4966, Task (com.android.server.wm)
resumeFocusedTasksTopActivities:2264, RootWindowContainer (com.android.server.wm)
resumeFocusedTasksTopActivities:2250, RootWindowContainer (com.android.server.wm)
completePause:1839, TaskFragment (com.android.server.wm)
activityPaused:6197, ActivityRecord (com.android.server.wm)
activityPaused:190, ActivityClientController (com.android.server.wm)  //ActivityRecord{cc65ede u0 com.android.settings/.FallbackHome} t5 f}}
onTransact:609, IActivityClientController$Stub (android.app)
onTransact:127, ActivityClientController (com.android.server.wm)
execTransactInternal:1280, Binder (android.os)
execTransact:1244, Binder (android.os)

LaunchActivityItem,ResumeActivityItem 都在这个方法中创建。

![[RealStartActivity 中创建 TranslationItem 的过程.png]]

java 复制代码
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());  
  
            final TaskFragment organizedTaskFragment = r.getOrganizedTaskFragment();  
            if (organizedTaskFragment != null) {  
                // Sending TaskFragmentInfo to client to ensure the info is updated before  
                // the activity creation.                mService.mTaskFragmentOrganizerController.dispatchPendingInfoChangedEvent(  
                        organizedTaskFragment);  
            }  
  
            // Create activity launch transaction.  
            final ClientTransaction clientTransaction = ClientTransaction.obtain(  
                    proc.getThread(), r.token);  
  
            final boolean isTransitionForward = r.isTransitionForward();  
            final IBinder fragmentToken = r.getTaskFragment().getFragmentToken();  
            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.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,  
                    proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),  
                    results, newIntents, r.takeOptions(), isTransitionForward,  
                    proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,  
                    r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken));  
  
            // Set desired final state.  
            final ActivityLifecycleItem lifecycleItem;  
            if (andResume) {  
                lifecycleItem = ResumeActivityItem.obtain(isTransitionForward,  
                        r.shouldSendCompatFakeFocus());  
            } 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;  
            r.detachFromProcess();  
            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;  
}
相关推荐
m0_471199636 分钟前
【小程序】订单数据缓存 以及针对海量库存数据的 懒加载+数据分片 的具体实现方式
前端·vue.js·小程序
编程大师哥7 分钟前
Java web
java·开发语言·前端
A小码哥8 分钟前
Vibe Coding 提示词优化的四个实战策略
前端
Murrays8 分钟前
【React】01 初识 React
前端·javascript·react.js
大喜xi12 分钟前
ReactNative 使用百分比宽度时,aspectRatio 在某些情况下无法正确推断出高度,导致图片高度为 0,从而无法显示
前端
helloCat12 分钟前
你的前端代码应该怎么写
前端·javascript·架构
电商API_1800790524713 分钟前
大麦网API实战指南:关键字搜索与详情数据获取全解析
java·大数据·前端·人工智能·spring·网络爬虫
康一夏14 分钟前
CSS盒模型(Box Model) 原理
前端·css
web前端12314 分钟前
React Hooks 介绍与实践要点
前端·react.js
我是小疯子6615 分钟前
JavaScriptWebAPI核心操作全解析
前端