BpBinder代理对象
BpBinder 是 native 进程中代表远程 Binder node 的代理对象。它的关键身份不是 C++ 指针,而是驱动分配给当前进程的 handle;ProcessState 用 handle 表缓存代理的裸指针和弱引用控制块,避免同一 handle 被无故创建多个代理。代理的强引用、弱引用、死亡通知和析构都会回到 IPCThreadState,最终产生对应 Binder 命令。
本文面向已经读过 ProcessState初始化、IPCThreadState线程绑定、transact发送 和 Binder远程引用 的读者。本文回答代理从哪里来、何时复用、强弱引用何时通知驱动、死亡后为什么不复活,以及析构如何与 handle 表并发协作。不展开 Java BinderProxy 的包装层。
1. 代理入口
1.1 Handle查找
源码文件:frameworks/native/libs/binder/ProcessState.cpp
相关函数:getStrongProxyForHandle()、lookupHandleLocked()
ProcessState::handle_entry*
ProcessState::lookupHandleLocked(int32_t handle) {
const size_t N = mHandleToObject.size();
if (N <= static_cast<size_t>(handle)) {
handle_entry e{.binder = nullptr, .refs = nullptr};
status_t err = mHandleToObject.insertAt(
e, N, handle + 1 - N);
if (err < NO_ERROR) return nullptr;
}
return &mHandleToObject.editItemAt(handle);
}handle 表按整数下标扩展;新槽位初始化为空 Binder 和弱引用。mLock 由调用者持有,保证查找、复用和替换不会与代理析构同时修改同一槽位。
1.2 复用或创建
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) {
std::unique_lock<std::mutex> lock(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != nullptr) {
IBinder* b = e->binder;
if (b == nullptr || !e->refs->attemptIncWeak(this)) {
sp<BpBinder> bp = BpBinder::PrivateAccessor::create(
handle, &postTask);
e->binder = bp.get();
if (bp) e->refs = bp->getWeakRefs();
result = bp;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
...
}已有代理且弱引用仍可提升时直接复用;代理已析构或弱控制块不可提升时创建新 BpBinder。锁内只准备对象和 post task,解锁后才执行 task,避免构造期间回调再次取得同一把锁。
1.3 Context句柄
handle 0 通常代表 context manager。若当前进程已经设置了本地 the_context_object,直接返回本地对象;否则驱动为 handle 0 提供特殊引用。ServiceManager 启动和普通客户端获取 context object 因此共享同一个 handle 表入口,但本地 context object 分支不创建 BpBinder。
2. 引用生命周期
2.1 构造弱引用
源码文件:frameworks/native/libs/binder/BpBinder.cpp
相关函数:BpBinder::BpBinder()
BpBinder::BpBinder(BinderHandle&& handle, int32_t trackedUid)
: BpBinder(Handle(handle)) {
mTrackedUid = trackedUid;
IPCThreadState::self()->incWeakHandle(
this->binderHandle(), this);
}创建代理时先向当前线程状态登记 handle 的弱引用。此时还不代表应用持有强 sp,但保证驱动返回该 handle 时,代理生命周期可以被安全观察。
2.2 首个强引用
void BpBinder::onFirstRef() {
IPCThreadState* ipc = IPCThreadState::self();
if (ipc) ipc->incStrongHandle(
binderHandle(), this);
}第一次强引用会把 handle 的 strong acquire 交给 IPCThreadState;后续复制 sp<BpBinder> 不重复发送 acquire。驱动引用计数因此与本进程代理的强引用边沿对应。
2.3 最后强引用
void BpBinder::onLastStrongRef(const void* /*id*/) {
IPCThreadState* ipc = IPCThreadState::self();
if (ipc && !kDecStrongLast) {
ipc->decStrongHandle(binderHandle());
}
...
}最后一个强引用释放时发送 strong decrement(具体时机受 kDecStrongLast 配置影响),并处理死亡 obituary。强引用归零不一定立即析构,因为 BpBinder 采用弱生命周期;真正析构还要等弱引用控制块也结束。
2.4 析构清理
BpBinder::~BpBinder() {
IPCThreadState* ipc = IPCThreadState::self();
if (ipc) {
ipc->expungeHandle(binderHandle(), this);
ipc->decWeakHandle(binderHandle());
}
}析构先从 ProcessState/IPCThreadState 的 handle 表移除自己,再减少驱动弱引用。expungeHandle() 只在槽位仍指向当前对象时清空,防止旧代理析构覆盖并发期间已经替换的新代理。
3. 事务与死亡
3.1 代理发送
源码文件:frameworks/native/libs/binder/BpBinder.cpp
相关函数:BpBinder::transact()
status_t BpBinder::transact(uint32_t code,
const Parcel& data, Parcel* reply, uint32_t flags) {
if (mAlive) {
flags &= ~static_cast<uint32_t>(FLAG_PRIVATE_VENDOR);
status_t status = IPCThreadState::self()->transact(
binderHandle(), code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}代理把 handle 转交给 IPCThreadState::transact()。一旦返回 DEAD_OBJECT,mAlive 置零;之后即使远端进程后来启动同名服务,这个旧代理也不会复活,调用者必须重新取得新的 Binder。
3.2 死亡通知
status_t BpBinder::linkToDeath(
const sp<DeathRecipient>& recipient,
void* cookie, uint32_t flags) {
LOG_ALWAYS_FATAL_IF(recipient == nullptr,
"recipient must be non-NULL");
if (!mObitsSent && !mObituaries) {
mObituaries = new Vector<Obituary>;
getWeakRefs()->incWeak(this);
IPCThreadState* self = IPCThreadState::self();
self->requestDeathNotification(
binderHandle(), this);
self->flushCommands();
}
mObituaries->add({recipient, cookie, flags});
return NO_ERROR;
}第一次 linkToDeath() 才向驱动申请死亡通知;多个 recipient 共享一次驱动请求。死亡到达后 reportOneDeath() 以弱 BpBinder 调用 recipient,通知对象的 owner 是 DeathRecipient,不是发送线程本身。
4. 代理失效
4.1 同名服务重启
服务进程死亡让旧 BpBinder 进入 mAlive=false;ServiceManager 删除旧表项并可能重新注册新 Binder。旧代理的 handle 不能指向新 node,新的查询会通过 handle 表的弱引用状态决定复用或创建新的代理。
4.2 代理数量
BpBinder::create() 维护全局 proxy count,并可按 UID 统计和触发高水位/限制回调。数量统计是资源保护机制,不改变单个 handle 代理的强弱引用语义。
4.3 RPC分支
BpBinder 也可以携带 RpcSession 地址,但本文只讲 kernel Binder handle。RPC 构造函数不调用 incWeakHandle(),析构也不走 kernel handle 清理;不能把两类 BpBinder 生命周期混写。
5. 测试边界
5.1 死亡通知
源码文件:frameworks/native/libs/binder/tests/binderLibTest.cpp
DeathNotificationStrongRef 注册 DeathRecipient、让服务退出、等待事件并断言之后 unlinkToDeath() 返回 DEAD_OBJECT;DeathNotificationMultiple 验证多个进程/recipient 的通知和线程池消费边界。这些测试直接覆盖代理死亡状态与 obituary,不等同于 ServiceManager 的服务表清理。
5.2 代理计数
BinderProxyCount 创建多个代理并逐个销毁,断言全局 proxy count 增减;BinderProxyCountCallback 设置 UID 水位,验证 warning/limit callback。它们证明统计 owner 在 BpBinder,而不是 ProcessState handle 表。
5.3 可执行阅读
rg -n "getStrongProxyForHandle|lookupHandleLocked|expungeHandle" \
frameworks/native/libs/binder/ProcessState.cpp
rg -n "BpBinder::create|BpBinder::transact|onFirstRef|onLastStrongRef|BpBinder::~BpBinder" \
frameworks/native/libs/binder/BpBinder.cpp
rg -n "DeathNotificationStrongRef|DeathNotificationMultiple|BinderProxyCount" \
frameworks/native/libs/binder/tests/binderLibTest.cpp排查“同一个服务出现多个代理”或“旧代理无法恢复”时,先看 handle 表弱引用是否仍可提升,再区分代理 mAlive、远端 node 死亡和 ServiceManager 重新注册;不要用服务名相同推断 handle 或 BpBinder 对象必然相同。
