Skip to content

ActivityThread.H 主线程

从 Binder 调度到 ActivityThread.H 处理 EXECUTE_TRANSACTION,追踪应用主线程如何接收、执行和收束系统事务。

基于android-17.0.0_r1
AndroidActivityThreadClientTransactionHandler源码阅读

ActivityThread.H 主线程 ​

应用进程收到系统调度后,并不是 Binder 线程直接调用 Activity 的生命周期方法。Android 17 把远端入口放在 ActivityThread.ApplicationThread,再把事务封装成 Message 投递给 ActivityThread.H;主 Looper 取出消息后,H.handleMessage() 才调用 TransactionExecutor。这条路径把“远程到达”和“主线程执行”分成两个不同阶段。

本文面向已经读过 Handler消息处理、 Handler消息发送、IntentService 请求生命周期 和 HandlerExecutor 提交语义 的读者。本文不 罗列 H 的所有常量,也不重新讲 Activity 的每一个生命周期回调;只沿当前源码的一条主线 回答:谁创建主线程 Handler,Binder 调用如何变成 EXECUTE_TRANSACTION,事务由谁消费, 异常或退出时哪些状态会被清理,以及普通 H 消息与 ClientTransaction 有什么边界。

读完后,读者应能从一个 scheduleTransaction() 入口定位到 H.handleMessage(),解释为什么 生命周期代码在主线程运行,区分 preExecute() 与真正的 execute(),并用测试源码判断事务 执行顺序和失败路径能证明到哪一层。

1. 主线程身份 ​

源码文件:frameworks/base/core/java/android/app/ActivityThread.java

ActivityThread 实例创建时保存当前线程的 Looper,同时创建内部 H 和一个基于该 Handler 的 HandlerExecutor。这里没有创建第二条线程:mH 绑定的是构造它时当前线程的 Looper。

java
final Looper mLooper = Looper.myLooper();
final H mH = new H();
final Executor mExecutor = new HandlerExecutor(mH);

getHandler() 把同一个 mH 暴露给进程内的系统入口;调用方拿到的是主线程 Handler,而不是 一个独立的调度器。

java
@UnsupportedAppUsage
public Handler getHandler() {
    return mH;
}

对象边界是:

对象所有者消费者作用
ActivityThread应用进程主线程ApplicationThread、各 handler 方法保存进程级状态
mHActivityThread主 Looper把消息分派到 ActivityThread 方法
mExecutorActivityThread需要 Executor 的内部调用复用 mH 的队列
mActivitiesActivityThread事务执行和生命周期方法保存 Activity token 到本地记录的映射

因此,“H 是主线程”更精确的说法是:H 的 mLooper 是主 Looper,H 的消息由主 Looper 串行分发;H 类本身不是线程。

2. 启动循环 ​

源码文件:frameworks/base/core/java/android/app/ActivityThread.java

main() 先准备主 Looper,再创建 ActivityThread、连接系统,最后进入 Looper.loop()。 只有进入循环后,后续通过 mH 入队的消息才有消费者。

java
public static void main(String[] args) {
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
    // 解析启动参数和初始化进程环境
    Looper.prepareMainLooper();

    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}

这里的异常行不是正常退出分支:主 Looper 正常应持续运行;如果 Looper.loop() 返回,源码把 它视为不符合进程主线程契约的状态。H 的消息生命周期因此依赖三个前置条件:主 Looper 已 准备、ActivityThread 已构造、Looper.loop() 尚未结束。

3. Binder 转发 ​

源码文件:frameworks/base/core/java/android/app/ActivityThread.java

系统进程通过 IApplicationThread 调用应用进程时,Binder 线程进入 ApplicationThread。 以事务为例,Binder 方法不直接执行事务,而是调用外层 ActivityThread.scheduleTransaction()。

java
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    ActivityThread.this.scheduleTransaction(transaction);
}

源码文件:frameworks/base/core/java/android/app/ClientTransactionHandler.java

ActivityThread 继承的 ClientTransactionHandler 负责通用的“预处理再投递”步骤:先调用 事务的 preExecute(),再用 ActivityThread.H.EXECUTE_TRANSACTION 作为消息类型发送。

java
void scheduleTransaction(ClientTransaction transaction) {
    transaction.preExecute(this);
    sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}

preExecute() 所在的 Binder 线程和之后 TransactionExecutor.execute() 所在的主线程不是 同一个阶段。事务对象可能在预处理阶段准备数据、注册待销毁记录或执行 item 的前置动作, 但 Activity 生命周期的实际消费要等到 H 消息被主 Looper 取出。

这条链路的关键不是“Binder 调 Handler”这一句,而是 preExecute() 与 handleMessage() 之间存在真实的 MessageQueue 边界。消息可能延迟、被队列退出清理,或者在主线程忙碌时等待; Binder 方法返回并不表示 Activity 已经创建或恢复。

4. 消息目录 ​

源码文件:frameworks/base/core/java/android/app/ActivityThread.java

H 用整数常量标识不同的进程级操作,例如绑定应用、创建服务、执行事务、清理资源和退出。 这些常量是协议编号,不是 Java 类型系统;真正的参数类型由 handleMessage() 中每个 case 对 msg.obj 的转换决定。

java
public static final int BIND_APPLICATION = 110;
public static final int CREATE_SERVICE = 114;
public static final int GC_WHEN_IDLE = 120;
public static final int LOW_MEMORY = 124;
public static final int EXECUTE_TRANSACTION = 159;
public static final int PURGE_RESOURCES = 161;
public static final int SCHEDULE_CRASH = 134;
public static final int EXIT_APPLICATION = 111;

codeToString() 只在 DEBUG_MESSAGES 打开时把编号转换为可读名称;关闭调试时返回数字。 因此日志中的 159 是否代表事务,必须结合固定版本的常量表或 codeToString(),不能凭 记忆套用其他 Android 版本的编号。

java
String codeToString(int code) {
    if (DEBUG_MESSAGES) {
        switch (code) {
            case EXECUTE_TRANSACTION: return "EXECUTE_TRANSACTION";
            case PURGE_RESOURCES: return "PURGE_RESOURCES";
            case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
        }
    }
    return Integer.toString(code);
}

消息目录的学习重点是“编号—payload—消费者”三元组,而不是背下所有常量:

whatmsg.obj 形态处理方法
BIND_APPLICATIONAppBindDatahandleBindApplication
CREATE_SERVICECreateServiceDatahandleCreateService
EXECUTE_TRANSACTIONClientTransactionmTransactionExecutor.execute
GC_WHEN_IDLE通常无 payloadscheduleGcIdler
PURGE_RESOURCES通常无 payloadschedulePurgeIdler

5. 事务消费 ​

源码文件:frameworks/base/core/java/android/app/ActivityThread.java

EXECUTE_TRANSACTION case 不直接展开 Activity 的每一个回调,而是把事务交给 mTransactionExecutor。执行前后通知 ClientTransactionListenerController,并用 try/finally 保证“事务结束”通知即使执行器抛异常也会发生。

java
case EXECUTE_TRANSACTION:
    final ClientTransaction transaction = (ClientTransaction) msg.obj;
    final ClientTransactionListenerController controller =
            ClientTransactionListenerController.getInstance();
    controller.onClientTransactionStarted();
    try {
        mTransactionExecutor.execute(transaction);
    } finally {
        controller.onClientTransactionFinished();
    }
    break;

这里有两个消费者层次:H 消费 Message,TransactionExecutor 消费事务中的 ClientTransactionItem。H 的职责是把协议消息路由到 executor;它不拥有 Activity 生命周期 路径本身。

源码文件:frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java

事务执行器会按事务项顺序执行 callbacks,并在需要时执行目标生命周期状态请求。测试源码 将 callback 的顺序作为可观察契约,而不是只验证“某个方法最终被调用”。

java
public void execute(ClientTransaction transaction) {
    Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "clientTransactionExecuted");
    try {
        executeTransactionItems(transaction);
    } catch (Exception e) {
        Slog.e(TAG, "Failed to execute the transaction: "
                + transactionToString(transaction, mTransactionHandler));
        throw e;
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
    }
    mPendingActions.clear();
}

如果执行某个 item 抛异常,H 的 finally 仍会调用 onClientTransactionFinished(),但后续 事务项是否执行取决于异常是否被上层捕获。finally 只保证 listener 收束,不保证生命周期 事务具有数据库式回滚。

6. 本地路径 ​

源码文件:frameworks/base/core/java/android/app/ClientTransactionHandler.java

同一个抽象类还提供 executeTransaction(),用于本地请求直接执行事务。它设置 mIsExecutingLocalTransaction,调用 preExecute() 和 getTransactionExecutor().execute(), 最后清除标志;这条路径不经过 H 消息。

java
@VisibleForTesting
public void executeTransaction(ClientTransaction transaction) {
    mIsExecutingLocalTransaction = true;
    try {
        transaction.preExecute(this);
        getTransactionExecutor().execute(transaction);
    } finally {
        mIsExecutingLocalTransaction = false;
    }
}

因此不能把所有 ClientTransaction 都描述成“先变成 EXECUTE_TRANSACTION 消息”。远程 调度通常走 scheduleTransaction(),本地测试或本地请求可以直接执行。阅读调用方时必须先 确认它调用的是 scheduleTransaction 还是 executeTransaction。

7. 生命周期测试 ​

源码文件:frameworks/base/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java

TransactionExecutorTests 不启动完整应用进程,而是用 mock ClientTransactionHandler、 ActivityClientRecord 和生命周期 item,验证状态路径。例如从 ON_CREATE 到 ON_RESUME, 期望经过 ON_START 再到 ON_RESUME。

java
@Test
public void testLifecycleFromOnCreate() {
    mClientRecord.setState(ON_CREATE);
    assertArrayEquals(new int[] {}, path(ON_CREATE));
    assertArrayEquals(new int[] {ON_START}, path(ON_START));
    assertArrayEquals(new int[] {ON_START, ON_RESUME}, path(ON_RESUME));
    assertArrayEquals(new int[] {ON_START, ON_RESUME, ON_PAUSE}, path(ON_PAUSE));
}

这个测试证明的是 TransactionExecutor 的状态路径推导,不证明真实 H 已经从主队列取出 消息。它把事务消费层从进程启动、Binder 和 MessageQueue 中隔离出来,正好说明本文主线中 “H 路由”和“executor 生命周期算法”是两个可以单独验证的层次。

源码文件:frameworks/base/core/tests/coretests/src/android/app/servertransaction/ClientTransactionTests.java

ClientTransactionTests.testPreExecute 建立两个 callback 和一个 lifecycle item,调用 transaction.preExecute(clientTransactionHandler),然后分别验证三个 item 的 preExecute 都收到同一个 handler。

java
final ClientTransactionItem callback1 = mock(ClientTransactionItem.class);
final ClientTransactionItem callback2 = mock(ClientTransactionItem.class);
final ActivityLifecycleItem stateRequest = mock(ActivityLifecycleItem.class);
doReturn(true).when(stateRequest).isActivityLifecycleItem();

final ClientTransactionHandler clientTransactionHandler =
        mock(ClientTransactionHandler.class);
final ClientTransaction transaction = new ClientTransaction();
transaction.addTransactionItem(callback1);
transaction.addTransactionItem(callback2);
transaction.addTransactionItem(stateRequest);

transaction.preExecute(clientTransactionHandler);

verify(callback1).preExecute(clientTransactionHandler);
verify(callback2).preExecute(clientTransactionHandler);
verify(stateRequest).preExecute(clientTransactionHandler);

它证明的是 Binder 线程阶段的 item 预处理顺序,不证明 H.handleMessage() 的主线程执行 已经发生。把这两个测试合起来,才能看到 preExecute 与 execute 之间的真实边界。

8. 普通消息 ​

源码文件:frameworks/base/core/java/android/app/ActivityThread.java

并非所有 H 消息都使用 ClientTransaction。例如 GC_WHEN_IDLE 只触发 IdleHandler 注册, PURGE_RESOURCES 只调度资源清理,REMOVE_PROVIDER 则是带延迟的普通 Message。

java
case GC_WHEN_IDLE:
    scheduleGcIdler();
    break;
case PURGE_RESOURCES:
    schedulePurgeIdler();
    break;
case REMOVE_PROVIDER:
    completeRemoveProvider((ProviderRefCount) msg.obj);
    break;

这解释了为什么 H 不能被概括成“Activity 生命周期 Handler”:它还是应用进程级的统一 入口,承载 Provider、资源、GC、广播、Service 和调试命令等不同协议。文章选择 EXECUTE_TRANSACTION 作为主线,是为了讲清一条完整调用链,不是声称其他 case 都走同一 executor。

9. 延迟清理 ​

源码文件:frameworks/base/core/java/android/app/ActivityThread.java

Provider 引用释放时,ActivityThread 把真正移除延迟到 CONTENT_PROVIDER_RETAIN_TIME 之后, 消息的 obj 保存 ProviderRefCount。消息到达时 completeRemoveProvider() 先再次检查 removePending,以处理延迟期间 provider 被重新获取的竞态。

java
if (lastRef) {
    if (!prc.removePending) {
        prc.removePending = true;
        Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, prc);
        mH.sendMessageDelayed(msg, CONTENT_PROVIDER_RETAIN_TIME);
    } else {
        Slog.w(TAG, "Duplicate remove pending of provider " + prc.holder.info.name);
    }
}

消息到达后,消费者还要在 provider 引用表锁内重新确认是否仍然允许移除:

java
void completeRemoveProvider(ProviderRefCount prc) {
    synchronized (mProviderMap) {
        if (!prc.removePending) {
            // A client acquired the provider again before removal completed.
            return;
        }
        prc.removePending = false;
        // 从 provider 引用表和 provider map 中移除
    }
}

这是 H 消息“成功到达但不一定执行原计划”的一个具体例子:延迟消息只是触发再次检查, completeRemoveProvider 的状态判断决定清理是否真的生效。取消或恢复逻辑属于消费者状态, 不是 MessageQueue 的时间排序自动提供的。

10. 消息异常 ​

源码文件:frameworks/base/core/java/android/app/ActivityThread.java

handleMessage() 对不同 case 采用不同异常边界。有些 case 用 try/finally 结束 Trace, 有些 case 直接调用处理方法;EXECUTE_TRANSACTION 额外用 listener 的 finally,但没有把 所有异常转换为普通返回值。

java
case RECEIVER:
    if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
    }
    ReceiverData receiverData = (ReceiverData) msg.obj;
    try {
        handleReceiver(receiverData);
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }
    break;

事务 case 的清理对象不同:它围绕 ClientTransactionListenerController 建立执行边界。

java
case EXECUTE_TRANSACTION:
    final ClientTransaction transaction = (ClientTransaction) msg.obj;
    final ClientTransactionListenerController controller =
            ClientTransactionListenerController.getInstance();
    controller.onClientTransactionStarted();
    try {
        mTransactionExecutor.execute(transaction);
    } finally {
        controller.onClientTransactionFinished();
    }
    break;

Trace 收尾和事务 listener 收尾是“清理动作”,不是异常恢复。若生命周期 item 抛出异常, 外层 Looper 的异常策略仍然参与;不能因为看到 finally 就推导出应用会继续处理下一条消息。

11. 退出消息 ​

源码文件:frameworks/base/core/java/android/app/ActivityThread.java

EXIT_APPLICATION 的 case 先调用 Application.onTerminate()(如果存在初始 Application), 然后让当前 Looper 退出。这个路径说明 H 既能驱动业务生命周期,也能结束自身的消息消费者。

java
case EXIT_APPLICATION:
    if (mInitialApplication != null) {
        mInitialApplication.onTerminate();
    }
    Looper.myLooper().quit();
    break;

这不是所有异常的通用清理路径。进程被 SUICIDE 或 native 级终止路径结束时,可能没有机会 走 EXIT_APPLICATION;而主 Looper 退出后,后续发送给 mH 的消息也不能获得正常消费者。

12. 事务监听 ​

源码文件:frameworks/base/core/java/android/app/servertransaction/ClientTransactionListenerController.java

H 在事务前后通知 listener controller,controller 负责把事务期间发生的配置变化等事件 延后到事务完成后再处理。测试专门覆盖“事务进行中不立即触发,事务结束后才触发”的顺序。

java
public void onClientTransactionStarted() {
    synchronized (mLock) {
        mIsClientTransactionExecuting = true;
    }
}

public void onClientTransactionFinished() {
    synchronized (mLock) {
        mIsClientTransactionExecuting = false;
        // 收集事务期间延后的配置变化
    }
    // 锁外派发 display changed callbacks
}

源码文件:frameworks/base/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java

java
mController.onClientTransactionStarted();
mController.onContextConfigurationPreChanged(mActivity);
mConfiguration.windowConfiguration.setMaxBounds(new Rect(0, 0, 100, 200));
mController.onContextConfigurationPostChanged(mActivity);

verify(mController, never()).onDisplayChanged(anyInt());

mController.onClientTransactionFinished();
verify(mController).onDisplayChanged(123);

这里的测试输入不是直接测试 Handler,而是测试 H 的 finally 所保护的事务边界消费者。 它能证明 listener 的延后顺序,不能证明所有 Activity 生命周期回调都被该 controller 监听。

13. 复查命令 ​

源码文件:

  • frameworks/base/core/java/android/app/ActivityThread.java
  • frameworks/base/core/java/android/app/ClientTransactionHandler.java
  • frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
  • frameworks/base/core/java/android/app/servertransaction/ClientTransactionListenerController.java
  • frameworks/base/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
  • frameworks/base/core/tests/coretests/src/android/app/servertransaction/ClientTransactionTests.java
  • frameworks/base/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java
bash
rg -n "final H mH|class H extends Handler|getHandler\(\)|prepareMainLooper|Looper.loop" \
  frameworks/base/core/java/android/app/ActivityThread.java

rg -n "scheduleTransaction|preExecute|EXECUTE_TRANSACTION|executeTransaction" \
  frameworks/base/core/java/android/app/ClientTransactionHandler.java \
  frameworks/base/core/java/android/app/ActivityThread.java

rg -n "case EXECUTE_TRANSACTION|onClientTransactionStarted|mTransactionExecutor.execute" \
  frameworks/base/core/java/android/app/ActivityThread.java

rg -n "testPreExecute|testLifecycleFromOnCreate|onClientTransactionStarted" \
  frameworks/base/core/tests/coretests/src/android/app/servertransaction

复述主线时,至少要区分:Binder 线程的 preExecute()、主线程的 H.handleMessage()、 TransactionExecutor 的 item 执行,以及 listener finally 的结束通知。把它们压缩成“AMS 发消息,ActivityThread 执行生命周期”会丢失最重要的线程和状态边界。

14. 适用边界 ​

ActivityThread.H 是应用进程主 Looper 上的协议分派器,不是通用业务 Handler,也不是所有 生命周期算法的 owner。它负责将整数 what 和 payload 路由到 ActivityThread 的处理方法; 事务顺序、Activity 状态路径、Provider 延迟清理和 IdleHandler 清理分别由各自消费者维护。

当排查“系统调用已到达但 Activity 尚未变化”时,按源码顺序检查:Binder 是否进入 ApplicationThread,事务是否完成 preExecute(),EXECUTE_TRANSACTION 是否成功入队,主 Looper 是否取出消息,TransactionExecutor 是否在 item 处抛异常,以及 listener/清理状态是否 改变了后续观察。这样才能把远端到达、主线程排队、事务执行和最终 UI 状态区分开。