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;  
}
相关推荐
天蓝色的鱼鱼2 分钟前
Vue重复提交防御体系从入门到精通
前端·vue.js
海的诗篇_1 小时前
前端开发面试题总结-vue2框架篇(四)
前端·css·面试·vue·html
用户426670591691 小时前
为什么说不可信的Wi-Fi不要随便连接?
前端
玺同学1 小时前
从卡顿到流畅:前端渲染性能深度解析与实战指南
前端·javascript·性能优化
光影少年1 小时前
vuex中的辅助函数怎样使用
前端·javascript
teeeeeeemo2 小时前
JS数据类型检测方法总结
开发语言·前端·javascript·笔记
木木黄木木2 小时前
HTML5 火焰字体效果教程
前端·html·html5
云墨-款哥的博客2 小时前
失业学习-前端工程化-webpack基础
前端·学习·webpack
MAOX7892 小时前
基于python的web系统界面登录
前端·python
懒大王、2 小时前
Vue添加图片作为水印
前端·javascript·vue.js