Skip to content

BBinder本地对象

追踪 BBinder 本地对象的 transact、onTransact 分发、稳定性边界和本地死亡通知语义。

基于android-17.0.0_r1
AndroidBinderBBinderNative框架源码阅读

BBinder本地对象 ​

BBinder 是本进程拥有的 Binder 实体。远程进程看到它时会得到 BpBinder,但事务最终仍回到拥有 BBinder 的进程,由 BBinder::transact() 准备 Parcel、执行稳定性检查和调用虚函数 onTransact()。默认 onTransact() 只处理接口描述符和 dump;具体服务通常由 BnInterface 子类覆盖它。

本文面向已经读过 BpBinder代理对象、transact发送 和 Binder事务发送 的读者。本文聚焦本地对象的 owner、分发入口、默认命令、错误和死亡通知边界,不重复讲驱动如何创建 binder_node。

1. 本地对象 ​

1.1 基本身份 ​

源码文件:frameworks/native/libs/binder/Binder.cpp

相关函数:BBinder::BBinder()、isBinderAlive()、localBinder()

cpp
BBinder::BBinder() : mExtras(nullptr) {}

bool BBinder::isBinderAlive() const { return true; }

BBinder* BBinder::localBinder() { return this; }

本地对象永远报告存活,localBinder() 返回自身;这是和远程 BpBinder::mAlive 的根本区别。对象是否已被 Parcel 发送、稳定性是否设置、SID 是否请求,都由 BBinder 的 extras/packed state 另行记录。

1.2 远程对照 ​

对象ownerlocalBinder()存活判断
BBinder当前进程返回自身默认 true
BpBinder代理进程返回远程代理mAlive,死亡后 false

2. 分发入口 ​

2.1 transact准备 ​

源码文件:frameworks/native/libs/binder/Binder.cpp

相关函数:BBinder::transact()

cpp
status_t BBinder::transact(uint32_t code,
        const Parcel& data, Parcel* reply,
        uint32_t flags) {
    data.setDataPosition(0);
    if (reply != nullptr && (flags & FLAG_CLEAR_BUF)) {
        reply->markSensitive();
    }
    status_t err = onTransact(code, data, reply, flags);
    return err;
}

真实源码还会围绕这段路径执行 trace、录制和耗时日志;核心不变量是把输入位置归零,再把事务交给 onTransact()。FLAG_CLEAR_BUF 影响 reply 清理敏感数据,不改变目标方法选择。

2.2 默认分发 ​

cpp
status_t BBinder::onTransact(uint32_t code,
        const Parcel& data, Parcel* reply,
        uint32_t /*flags*/) {
    switch (code) {
    case INTERFACE_TRANSACTION:
        LOG_ALWAYS_FATAL_IF(reply == nullptr,
                            "reply == nullptr");
        reply->writeString16(getInterfaceDescriptor());
        return NO_ERROR;
    case DUMP_TRANSACTION:
        return dump(data.readFileDescriptor(), {});
    default:
        return UNKNOWN_TRANSACTION;
    }
}

默认实现处理接口描述符查询和 dump;业务 transaction code 若未被子类覆盖则返回 UNKNOWN_TRANSACTION。接口描述符是协商对象身份的协议命令,不是业务方法。

3. 对象配置 ​

3.1 SID请求 ​

cpp
void BBinder::setRequestingSid(bool requestingSid) {
    LOG_ALWAYS_FATAL_IF(wasParceled(),
            "setRequestingSid() should not be called after a binder object is parceled");
    getOrCreateExtras()->mRequestingSid = requestingSid;
}

本地对象发送到其他进程后不能再修改这类初始化属性。ServiceManager 在自注册前设置 requesting SID,就是利用了这个生效时机。

3.2 稳定性 ​

稳定性等级保存在 PackedData,由 AIDL/接口实现和事务发送校验使用。稳定性设置不是 onTransact() 的业务返回值;它决定该 Binder 是否允许被某类接口或 Parcel 传输。

3.3 本地死亡通知 ​

cpp
status_t BBinder::linkToDeath(
        const sp<DeathRecipient>&, void*, uint32_t) {
    return INVALID_OPERATION;
}

本地对象 owner 就是当前进程,不能在同一进程对它注册“远程 owner 死亡”通知。死亡 recipient 应注册在远程进程持有的 BpBinder 上;把 BBinder::linkToDeath() 当成可用接口会得到 INVALID_OPERATION。

4. 生命周期 ​

4.1 发送标记 ​

BBinder 被写入 Parcel 后会标记 wasParceled()。析构函数在未发送状态下会检查 extension、SID、调度策略等是否被设置但未使用;这些 warning 用于发现对象初始化顺序错误。

4.2 扩展对象 ​

attachObject()、lookupOrCreateWeak() 等对象管理器状态由 BBinder::Extras 持有,并使用内部锁。对象管理器清理不等于 Binder node 的驱动释放;前者是用户态附加对象,后者由 Binder 引用生命周期负责。

4.3 调用结果 ​

子类 onTransact() 可以返回 NO_ERROR、业务 status 或 UNKNOWN_TRANSACTION。BBinder::transact() 负责把这个 status 返回给 IPCThreadState,随后由对端看到 reply 或 failed transaction;返回值不自动转换成 Java exception,转换发生在上层接口代码。

5. 测试边界 ​

5.1 本地对象 ​

源码文件:frameworks/native/libs/binder/tests/binderLibTest.cpp

PromoteLocal 使用 BBinder 的强/弱引用验证本地对象生命周期;WasParceled 在 Parcel 写入强 Binder 前后断言 wasParceled() 变化;ValidateReadBinders 等测试验证本地 Binder 在 Parcel 中的对象格式和读取边界。

5.2 业务分发 ​

测试服务类继承 BBinder 并覆盖 onTransact(),对已知 code 返回结果,对未知 code 返回 UNKNOWN_TRANSACTION。这些测试证明子类分发契约,不证明每种稳定性、调度策略或 RPC server 配置。

5.3 可执行阅读 ​

bash
rg -n "BBinder::transact|BBinder::onTransact|BBinder::linkToDeath|localBinder" \
  frameworks/native/libs/binder/Binder.cpp

rg -n "class BBinder|onTransact|setRequestingSid|wasParceled" \
  frameworks/native/libs/binder/include/binder/Binder.h

rg -n "PromoteLocal|WasParceled|UNKNOWN_TRANSACTION|onTransact" \
  frameworks/native/libs/binder/tests/binderLibTest.cpp

遇到“远端调用返回 UNKNOWN_TRANSACTION”,先确认目标对象是否真的是预期的 BBinder 子类、code 是否进入覆盖的 onTransact(),再检查接口描述符和 Parcel 读取位置;不要把 BBinder::linkToDeath() 的 INVALID_OPERATION 当成服务已死亡。