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()
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 远程对照
| 对象 | owner | localBinder() | 存活判断 |
|---|---|---|---|
BBinder | 当前进程 | 返回自身 | 默认 true |
BpBinder | 代理进程 | 返回远程代理 | mAlive,死亡后 false |
2. 分发入口
2.1 transact准备
源码文件:frameworks/native/libs/binder/Binder.cpp
相关函数:BBinder::transact()
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 默认分发
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请求
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 本地死亡通知
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 可执行阅读
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 当成服务已死亡。
