Activity 启动流程(五)—— Activity 启动阶段

765 阅读5分钟

前言

Activity 启动过程文章系列会按阶段拆开分析。上一篇已经把应用进程初始化完成;本文只聚焦 Activity 启动阶段:system_server 如何把等待中的 Activity 启动事务发给客户端,以及客户端如何依次走到 onCreate()onStart()onResume()

启动流程梳理:

  1. Activity 启动流程(一)—— Launcher 阶段
  2. Activity 启动流程(二)—— AMS 处理阶段
  3. Activity 启动流程(三)—— 应用程序进程启动阶段
  4. Activity 启动流程(四)—— ActivityThread 初始化阶段
  5. Activity 启动流程(五)—— Activity 启动阶段

代码基于 android-14.0.0_r9

本文关注的是 “目标 Activity 实例如何在客户端被真正创建并进入前台”。进程创建、Application 初始化这些事情,已经在前两篇完成了。

1. 一句话总览

这一阶段的核心是:应用进程完成 attachApplication 之后,system_server 重新找到这个进程里等待启动的 ActivityRecord,通过 realStartActivityLocked() 构造 LaunchActivityItemResumeActivityItem,再用 ClientTransaction 发给客户端;客户端收到事务后,依次执行 handleLaunchActivity()performLaunchActivity()handleStartActivity()handleResumeActivity(),最终把 Activity 推到可见且 resumed 的状态。

主链路如下:

finishAttachApplicationInner()mAtmInternal.attachApplication()RootWindowContainer.attachApplication()AttachApplicationHelper.process()ActivityTaskSupervisor.realStartActivityLocked()LaunchActivityItem + ResumeActivityItemClientTransaction.schedule()ActivityThread.scheduleTransaction()TransactionExecutor.executeTransactionItems()LaunchActivityItem.execute()handleLaunchActivity()performLaunchActivity()handleStartActivity()handleResumeActivity()

flowchart LR
    A[AMS.finishAttachApplicationInner]
    B[ATMS.attachApplication]
    C[realStartActivityLocked]
    D[LaunchActivityItem + ResumeActivityItem]
    E[ClientTransaction]
    F[ActivityThread.scheduleTransaction]
    G[handleLaunchActivity]
    H[performLaunchActivity / onCreate]
    I[handleStartActivity / onStart]
    J[handleResumeActivity / onResume]

    A --> B --> C --> D --> E --> F --> G --> H --> I --> J

这条链路的终点不是“请求已经发出”,而是 客户端 Activity 已经完成首次创建并进入 resumed/visible 状态

2. Activity 启动阶段源码分析

2.1 重新接回等待中的 Activity:attachApplication 完成后 ATMS 开始真实启动

应用进程完成 bindApplication 之后,AMS 会继续执行 finishAttachApplicationInner()

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
private void finishAttachApplicationInner(long startSeq, int uid, int pid) {
    ...
    synchronized (this) {
        ...
        if (normalMode) {
            try {
                didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }
        ...
    }
}

这一步的意义非常直接:现在进程已经可用,system_server 可以回过头来继续处理之前因为“进程还没起来”而挂起的 Activity 启动请求。

ATMS 接手之后,会继续走到 RootWindowContainer.attachApplication(),再由内部 helper 找出哪些 ActivityRecord 正在等这个进程:

// frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean attachApplication(WindowProcessController app) throws RemoteException {
    try {
        return mAttachApplicationHelper.process(app);
    } finally {
        mAttachApplicationHelper.reset();
    }
}

它内部最终会命中 realStartActivityLocked()

// RootWindowContainer.AttachApplicationHelper
public boolean test(ActivityRecord r) {
    if (r.finishing || !r.showToCurrentUser() || !r.visibleIgnoringKeyguard
            || r.app != null || mApp.mUid != r.info.applicationInfo.uid
            || !mApp.mName.equals(r.processName)) {
        return false;
    }

    if (mTaskSupervisor.realStartActivityLocked(r, mApp,
            mTop == r && r.getTask().canBeResumed(r),
            true /* checkConfig */)) {
        mHasActivityStarted = true;
    }
    return false;
}

也就是说,这一阶段的真正起点不是 Launcher,也不是 startActivityAsUser(),而是:system_server 确认目标进程已经 attach 完成,然后把等待中的 ActivityRecord 真正发往客户端。

2.2 构造启动事务:realStartActivityLocked() 把 launch 和 resume 打包

realStartActivityLocked() 是 system_server 侧把 Activity 启动事务发给客户端的关键方法:

// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
        boolean andResume, boolean checkConfig) throws RemoteException {
    ...
    final LaunchActivityItem launchActivityItem = LaunchActivityItem.obtain(r.token,
            r.intent, System.identityHashCode(r), r.info,
            mergedConfiguration.getGlobalConfiguration(),
            mergedConfiguration.getOverrideConfiguration(), deviceId,
            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);

    final ActivityLifecycleItem lifecycleItem;
    if (andResume) {
        lifecycleItem = ResumeActivityItem.obtain(r.token, isTransitionForward,
                r.shouldSendCompatFakeFocus());
    } else {
        lifecycleItem = PauseActivityItem.obtain(r.token);
    }

    mService.getLifecycleManager().scheduleTransactionAndLifecycleItems(
            proc.getThread(), launchActivityItem, lifecycleItem);
    ...
}

这里有一个很重要的设计点:Activity 的首次启动不是一个单独动作,而是一组事务项。

  • LaunchActivityItem 负责把 Activity 创建出来;
  • ResumeActivityItem 决定它最后要进入什么生命周期状态。

也就是说,system_server 在这一层做的是 “生命周期事务编排”,而不是直接执行客户端代码。

2.3 事务入客户端:ClientTransaction 把 system_server 的决策送到主线程

这些事务最终会通过 ClientTransaction 发给客户端:

// frameworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.java
void scheduleTransactionAndLifecycleItems(@NonNull IApplicationThread client,
        @NonNull ClientTransactionItem transactionItem,
        @NonNull ActivityLifecycleItem lifecycleItem) throws RemoteException {
    ...
    final ClientTransaction clientTransaction = ClientTransaction.obtain(client);
    clientTransaction.addCallback(transactionItem);
    clientTransaction.setLifecycleStateRequest(lifecycleItem);
    scheduleTransaction(clientTransaction);
}
// frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
public void schedule() throws RemoteException {
    mClient.scheduleTransaction(this);
}

客户端的 ActivityThread 收到它以后,不会在 Binder 线程里直接执行,而是转到主线程消息循环:

// frameworks/base/core/java/android/app/ClientTransactionHandler.java
void scheduleTransaction(ClientTransaction transaction) {
    transaction.preExecute(this);
    sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
// frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
public void executeTransactionItems(@NonNull ClientTransaction transaction) {
    final List<ClientTransactionItem> items = transaction.getTransactionItems();
    for (int i = 0; i < items.size(); i++) {
        final ClientTransactionItem item = items.get(i);
        if (item.isActivityLifecycleItem()) {
            executeLifecycleItem(transaction, (ActivityLifecycleItem) item);
        } else {
            executeNonLifecycleItem(transaction, item,
                    shouldExcludeLastLifecycleState(items, i));
        }
    }
}

这个顺序很关键:先执行非生命周期项(launch),再执行生命周期项(resume/pause)。这样客户端才能先有 Activity 实例,再去推进状态机。

2.4 客户端真正创建 Activity:performLaunchActivity() 走到 onCreate()

非生命周期项里最关键的是 LaunchActivityItem.execute()

// frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java
public void execute(@NonNull ClientTransactionHandler client,
        @NonNull PendingTransactionActions pendingActions) {
    ActivityClientRecord r = new ActivityClientRecord(mActivityToken, mIntent, mIdent, mInfo,
            mOverrideConfig, mReferrer, mVoiceInteractor, mState, mPersistentState,
            mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
            client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
            mTaskFragmentToken);
    client.handleLaunchActivity(r, pendingActions, mDeviceId, null /* customIntent */);
}

然后进入 ActivityThread.handleLaunchActivity()

// frameworks/base/core/java/android/app/ActivityThread.java
public Activity handleLaunchActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, int deviceId, Intent customIntent) {
    ...
    final Activity a = performLaunchActivity(r, customIntent);
    ...
    return a;
}

真正创建实例和调用 onCreate() 的地方在 performLaunchActivity()

// frameworks/base/core/java/android/app/ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ActivityInfo aInfo = r.activityInfo;
    if (r.packageInfo == null) {
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                Context.CONTEXT_INCLUDE_CODE);
    }
    ...
    ContextImpl appContext = createBaseContextForActivity(r);
    Activity activity = mInstrumentation.newActivity(
            cl, component.getClassName(), r.intent);
    ...
    Application app = r.packageInfo.makeApplication(false, mInstrumentation);
    ...
    activity.attach(appContext, this, getInstrumentation(), r.token,
            r.ident, app, r.intent, r.activityInfo, title, r.parent,
            r.embeddedID, r.lastNonConfigurationInstances, config,
            r.referrer, r.voiceInteractor, window, r.configCallback,
            r.assistToken, r.shareableActivityToken);
    ...
    mInstrumentation.callActivityOnCreate(activity, r.state);
    ...
    r.activity = activity;
    r.setState(ON_CREATE);
    ...
    return activity;
}

这一段才真正把服务端的 ActivityRecord 变成客户端里的 Activity 实例。到 callActivityOnCreate(...) 为止,首次 onCreate() 就已经发生了。

2.5 生命周期收尾:handleStartActivity()handleResumeActivity() 把 Activity 推到前台

Activity 创建完之后,事务执行器继续处理生命周期项。

先是 handleStartActivity()

// frameworks/base/core/java/android/app/ActivityThread.java
public void handleStartActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, ActivityOptions activityOptions) {
    final Activity activity = r.activity;
    ...
    activity.performStart("handleStartActivity");
    r.setState(ON_START);
    ...
    updateVisibility(r, true /* show */);
}

这一步把 Activity 从 ON_CREATE 推到 ON_START

再往后是 handleResumeActivity()

// frameworks/base/core/java/android/app/ActivityThread.java
public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
        boolean isForward, boolean shouldSendCompatFakeFocus, String reason) {
    ...
    if (!performResumeActivity(r, finalStateRequest, reason)) {
        return;
    }
    ...
    if (r.window == null && !a.mFinished && willBeVisible) {
        r.window = r.activity.getWindow();
        View decor = r.window.getDecorView();
        ...
        if (a.mVisibleFromClient) {
            if (!a.mWindowAdded) {
                a.mWindowAdded = true;
                wm.addView(decor, l);
            }
        }
    }
    ...
}

这里有两件事同时发生:

  1. performResumeActivity(...) 推进 Activity 到 resume 路径;
  2. Window / DecorView 被真正加入窗口系统,Activity 开始进入“对用户可见”的状态。

所以本文的收口点不是单纯的 onResume() 回调,而是:客户端 Activity 完成创建、启动、恢复,窗口也进入可见路径。

3. 关键设计点

3.1 system_server 负责编排,客户端负责执行

realStartActivityLocked() 决定要发哪些事务项,但它不直接调用客户端生命周期;真正执行 onCreate()onStart()onResume() 的,是 ActivityThread

3.2 LaunchActivityItemResumeActivityItem 是分层设计

首次启动并没有把所有动作揉成一个大方法,而是拆成“创建实例”和“推进状态”两个事务项。这样生命周期顺序更清楚,也更利于事务系统复用。

3.3 ActivityThread 是客户端执行器,不是决策者

客户端只是按事务执行:创建 ActivityClientRecord、实例化 Activity、调用生命周期、把窗口加到 WindowManager。至于该启动哪个 Activity、以什么状态启动,决策都已经在 system_server 完成了。

4. 总结

Activity 启动阶段的本质,是 system_server 把等待中的 ActivityRecord 编排成客户端事务,客户端再按顺序执行创建、启动、恢复和显示流程

handleLaunchActivity()performLaunchActivity()handleStartActivity()handleResumeActivity() 这一整条链跑完,目标 Activity 才算真正以一个前台可见组件的形式完成首次启动。