简介
替换libbinder, 也被称为Stable AIDL,在 Android 10 中引入的 官方推荐 Binder 后端。
- ABI 稳定: 它通过一套精简的 C API(即 android/binder_... 系列函数)屏蔽了底层原生 libbinder 的复杂实现。
- 跨分区通信: 它是 /vendor 分区与 /system 分区进行跨层通信(VINTF)的唯一标准。
- 现代 C++ 体验: 虽然底层是 C API,但它在 ndk:: 命名空间下提供了一套极其丝滑的 C++ 包装(RAII 指针、SharedRefBase 等)。
关键组成部分
- C API 层 :最底层的函数,如 AIBinder_transact。它们是跨版本兼容的"硬通货"。
- C++ 辅助类 :练习的重心:SpAIBinder (强指针)、WpAIBinder (弱指针)、ScopedAStatus (错误管理)。
- 接口辅助类:提供 SharedRefBase,解决 C++ 对象与 Binder 驱动引用计数同步的难题。
AIDL 工具生成的 Bn...(服务端)和 Bp...(客户端代理)。
实现与使用
服务端
- 定义AIDL文件,文件名字和定义里面"类"名字保持一致,且以I开头
- 服务端实现BnXxx基类,去掉AIDL名字的开头I
- 生成binder对象(SharedRefBase::make)
- 添加到服务中(AServiceManager_addService),或者转换给java层(AIBinder_toJavaBinder)
- C/C++程序,设置binder线程模式参数
- 普通模式:设置线程数,启动线程并加入循环
- 单线程或者集成模式:获取文件描述符、监听文件处理、自循环处理
客户端
- 获取服务Binder(AServiceManager_getService/AIBinder_fromJavaBinder)
- 转换对象: AIDL文件名::fromBinder(binder)
四种指针
- SharedRefBase:确保 C++ 对象在还有远程 Binder 调用时不会被销毁,而在没人使用时能自动释放内存。
- 对象实例化:ndk::SharedRefBase::make
- 类内部安全获取:ref(),返回shared_ptr; weak_ref(), 返回weak_ptr
- 转换binder: asBinder(), 换成NDK层的SpAIBinder
- SpAIBinder:对应于AIDL定义中的IBinder, 用于传递IBinder对象;get方法获取裸指针
- WpAIBinder:破解循环使用,缓存对象且不占用资源; 使用promote提升为SpAIBinder;构造时可以接受裸指针,也可以是SpAIBinder,建议是SpAIBinder
- 自动管理句柄:ScopedAResource实现类,专门用于管理那些需要手动删除的辅助对象;get/set/release/构造,其它方法看各个实现类,常用有下面三个类
- ScopedAStatus-->AStatus
- ScopedAIBinder_DeathRecipient-->AIBinder_DeathRecipient
- ScopedAParcel-->AParcel
AStatus
binder_status头文件中,负责创建、检查和销毁binder的执行结果
- 创建状态
- AStatus_newOk(): 创建一个表示"成功"的状态。
- AStatus_fromExceptionCode(exception_code): 从标准异常码(如 EX_SECURITY, EX_NULL_POINTER)创建。
- AStatus_fromServiceSpecificError(error_code): 创建自定义业务错误码(比如 CarPlay 连接失败返回 404)。
- AStatus_fromStatus(status): 将底层的 binder_status_t(如 STATUS_NO_MEMORY)转换为 AStatus。
- 检查状态
- AStatus_isOk(const AStatus* status): 判断是否成功。
- AStatus_getExceptionCode(const AStatus* status): 获取异常码。
- AStatus_getServiceSpecificError(const AStatus* status): 获取你定义的业务错误码。
- AStatus_getMessage(const AStatus* status): 获取错误详情字符串。
- 销毁状态
- AStatus_delete(AStatus* status): 非常重要。所有通过 AStatus_new... 或 AStatus_from... 创建的裸指针,都必须手动调用此函数释放,否则会造成严重的内存泄漏。
AIBinder_DeathRecipient
一个死亡通知监听器。它并不属于 Binder 通信的主流数据通道,而是一个侧向的监控机制:当被监听的 Binder 句柄所在的进程意外终止(死亡)时,系统会回调你预设的函数。
- 创建监听器对象 AIBinder_DeathRecipient_new(AIBinder_DeathRecipient_onBinderDied onBinderDied), AIBinder_DeathRecipient_onBinderDied其原型为void onBinderDied(void* cookie)
- 绑定到 Binder 对象 AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie)
- 解除绑定 AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie)
- 销毁监听器 AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient)
注意
- 生存期陷阱: AIBinder_DeathRecipient 对象本身必须比被监听的 Binder 活得久。如果你的 ScopedAIBinder_DeathRecipient 是函数内的局部变量,函数执行完它就析构了,死亡通知也就永远收不到了。
- 线程上下文: onBinderDied 回调通常发生在一个专门的 Binder 线程中。如果回调里涉及修改 UI 或复杂的资源竞争,记得加锁(比如 std::mutex)。
- Cookie 安全: 传入的 cookie(如 this)必须确保在回调发生时依然有效。如果你的服务对象已经析构了才收到死亡通知,就会发生 Use-after-free。
AParcel
Android 系统中用于跨进程传输(IPC)的数据容器。
- 数据打包: 支持基础类型(int, long, float)、字符串、数组。
- 传输对象: 支持传输其他的 AIBinder 对象(实现嵌套通信)。
- 传输资源: 支持传输文件描述符(File Descriptor)。 方法有:
- 写入数据:AParcel_writeXxx(AParcel* parce, Xxx data)
- 读取数据:AParcel_readXxx(AParcel* parcel, &Xxx data)
- 状态管理:
- AParcel_delete/AParcel_create,手动创建删除;使用ScopedAParcel处理
- AParcel_getDataSize: 获取当前 Parcel 中已存储的数据大小。
- AParcel_setDataPosition: 移动读写指针。
Xxx数据类型
- int32,int64,float,double
- string,byteArray
- parcelFileDescriptor:文件描述符
- strongBinder:binder
ABinderProcess
管理binder线程池,在binder_process头文件内;有两种模式
- 标准线程池模式:有三个方法
- AServiceManager_setThreadPoolMaxThreadCount(uint32_t maxThreads),设置 Binder 线程池的最大并发线程数。默认值15,一般选择4;有可能失败,必须在所有 Binder 行为发生之前调用。
- AServiceManager_startThreadPool(),非阻塞,启动binder线程池
- AServiceManager_joinThreadPool(),阻塞当前主线程,加入线程池并进入无限循环等待。
- 单线程/集成模式:两个方法
- ABinderProcess_setupPolling(int* fd):配置当前进程,使其支持"轮询"模式。它会返回一个文件描述符。就可以配合epoll、select 或者 Android 系统的 ALooper使用了
- ABinderProcess_handlePolledCommands():真正执行处理命令。当检测到fd有数据可读时,告诉binder驱动读取数据并分发给对应的AIDL实现类处理
AServiceManager
与系统服务管家打交道,是服务注册与获取的核心。头文件 binder_manager中
- 服务注册类(服务端使用)
- binder_status_t AServiceManager_addService(AIBinder* binder, const char* instance)
- 服务获取类(客户端使用)
- AIBinder* AServiceManager_getService(const char* instance)
- AIBinder* AServiceManager_checkService(const char* instance)
- AIBinder* AServiceManager_waitForService(const char* instance);
- 生命周期与枚举类(高级用途)
-
bool AServiceManager_isDeclared(const char* instance):在 VINTF(供应商接口对象)中检查服务是否已声明。这通常用于动态判断当前硬件平台是否支持某个功能。
-
AServiceManager_registerForServiceNotifications:注册一个监听器。当某个服务状态发生变化(比如重启了)时,你会收到通知。这对于中间件的断线重连逻辑至关重要。
如果在此文章中您有所收获,请给作者一个鼓励,点个赞,谢谢支持
技术变化都很快,但基础技术、理论知识永远都是那些;作者希望在余后的生活中,对常用技术点进行基础知识分享;如果你觉得文章写的不错,请给予关注和点赞;如果文章存在错误,也请多多指教!