Java-IBinder接口
Java IBinder 是应用和 framework 代码可见的低层 Binder 契约。它同时由本地 Binder 与远程 BinderProxy 实现,因此同一个 transact() 调用可能直接进入本进程 onTransact(),也可能经 JNI、native BpBinder 和驱动到达另一进程。接口只规定语义,不拥有线程池、Parcel buffer 或 native handle。
本文承接 Binder基类详解、BinderProxy详解 和 IBinder接口。本文聚焦 Java API 契约及其本地/远程差异,不重复两个实现类的内部字段。
1. 协议常量
1.1 事务区间
源码文件:frameworks/base/core/java/android/os/IBinder.java
int FIRST_CALL_TRANSACTION = 0x00000001;
int LAST_CALL_TRANSACTION = 0x00ffffff;
int PING_TRANSACTION = ('_'<<24)|('P'<<16)|('N'<<8)|'G';
int DUMP_TRANSACTION = ('_'<<24)|('D'<<16)|('M'<<8)|'P';
int INTERFACE_TRANSACTION = ('_'<<24)|('N'<<16)|('T'<<8)|'F';业务方法使用 FIRST/LAST 区间,接口查询、dump 和 ping 使用标准协议 code。AIDL 生成器为业务方法分配 code,调用者不应把标准 code 当普通业务编号。
1.2 事务flags
int FLAG_ONEWAY = 0x00000001;
int FLAG_CLEAR_BUF = 0x00000020;
int FLAG_COLLECT_NOTED_APP_OPS = 0x00000002;FLAG_ONEWAY 只在跨进程时提供异步语义;同进程调用可以直接执行本地 onTransact(),不能假设一定异步。相同 Binder 对象上的连续 oneway 事务按提交顺序串行分发,但不同对象、同步与异步混合不提供相同顺序保证。
1.3 建议大小
int MAX_IPC_SIZE = 64 * 1024;
static int getSuggestedMaxIpcSizeBytes() {
return MAX_IPC_SIZE;
}64 KiB 是安全建议,不是驱动真实上限。共享 transaction buffer、并发事务和对象 offsets 都会影响可用空间,业务数据应更小。
2. 对象识别
2.1 Descriptor
@Nullable String getInterfaceDescriptor()
throws RemoteException;
@Nullable IInterface queryLocalInterface(
@NonNull String descriptor);descriptor 是接口身份,不是 ServiceManager 服务名。AIDL Stub.asInterface() 先调用 queryLocalInterface();本地 Binder 返回 owner 时直接使用实现,远程 BinderProxy 通常返回 null,随后创建 Proxy。
2.2 存活探测
boolean pingBinder();
boolean isBinderAlive();isBinderAlive() 只表示最后已知状态;返回 true 后远端仍可能立即死亡。pingBinder() 会进行协议探测,但也不能形成未来存活保证。真正调用仍需处理 RemoteException。
3. transact契约
3.1 方法签名
源码文件:frameworks/base/core/java/android/os/IBinder.java
boolean transact(int code, @NonNull Parcel data,
@Nullable Parcel reply, int flags)
throws RemoteException;data 不能为空,即使没有参数也要传空 Parcel。同步调用通常传 reply;oneway 可以传 null。返回 false 通常表示目标不理解 code,而 RemoteException 表示传输或远端进程失败。
3.2 本地路径
Java Binder.transact() 重置 data 位置,直接调用本地 onTransact() 并重置 reply。即使设置 FLAG_ONEWAY,本地调用也不经过驱动异步队列。
3.3 远程路径
BinderProxy.transact() 执行大小、blocking、work source 和 AppOps 前处理后调用 transactNative()。同步调用等待 native reply;oneway 返回不代表服务端业务已经执行。
4. 死亡通知
4.1 注册
void linkToDeath(@NonNull DeathRecipient recipient,
int flags) throws RemoteException;
boolean unlinkToDeath(@NonNull DeathRecipient recipient,
int flags);只对远程 Binder 有意义。本地 Binder 与调用者同进程,默认不产生远程 owner 死亡通知。目标已死时 link 抛 RemoteException。
4.2 回调线程
binderDied() 可在任意 Binder 线程执行,libbinder 调用时不持有内部锁;业务共享状态仍需同步。回调参数是已失效的 IBinder,不能把它当作可恢复服务。
4.3 unlink结果
unlink 返回 true 表示成功保证 recipient 不再回调;返回 false 表示目标已死亡,回调已经或即将发生。仍存活但 recipient 从未注册时可能抛 NoSuchElementException。
5. 冻结回调
5.1 状态语义
FrozenStateChangeCallback 报告远程进程 frozen/unfrozen。冻结时同步事务返回错误,异步事务可缓存到解冻后;事件可能合并,不能用 callback 次数统计冻结次数。
5.2 Executor
公开 API 接受 Executor,BinderProxy 将 native callback 包装后投递到指定 executor;隐藏 overload 可直接在 Binder 线程执行。回调线程模型是 API 契约的一部分。
6. 调试能力
6.1 dump
dump() 请求同步输出对象状态;dumpAsync() 强制异步,若对象本地则创建新线程执行。二者都需要调用者管理传入 fd 生命周期和权限。
6.2 shellCommand
shell 命令传入 stdin/stdout/stderr、参数、ShellCallback 和 ResultReceiver;实现必须最终调用 resultReceiver。方法可能对调用者异步完成,不能用 transact 返回代替命令完成信号。
6.3 Extension
getExtension() 允许返回独立扩展 Binder,不修改原接口 descriptor。默认接口实现抛 IllegalStateException,只有支持 extension 的实现才返回对象。
7. 测试边界
7.1 死亡分发
源码文件:frameworks/base/core/tests/coretests/src/android/os/BinderDeathRecipientTest.java
测试启动远程 Binder、注册一个或多个 DeathRecipient、杀死远程进程并等待回调;另有 unlink 测试验证注销后不再接收通知。这些测试覆盖 Java API 的远程死亡路径,不覆盖本地 Binder 的空实现。
7.2 本地接口
源码文件:frameworks/base/core/tests/coretests/src/android/os/AidlTest.java
测试替身实现 queryLocalInterface(),用于验证 AIDL Stub 本地接口选择。大量 framework 单元测试也通过 mock Binder 控制 local/remote 分叉,但不能替代真实驱动 transaction。
7.3 可执行阅读
rg -n "FIRST_CALL_TRANSACTION|FLAG_ONEWAY|MAX_IPC_SIZE|transact\(" \
frameworks/base/core/java/android/os/IBinder.java
rg -n "queryLocalInterface|linkToDeath|FrozenStateChangeCallback|dumpAsync|shellCommand" \
frameworks/base/core/java/android/os/IBinder.java
rg -n "BinderDeathRecipientTest|queryLocalInterface" \
frameworks/base/core/tests/coretests/src/android/os排查 Java Binder 调用时,先区分对象是本地 Binder 还是 BinderProxy,再区分 false、RemoteException、死亡回调和冻结错误;不要用 isBinderAlive()==true 或 oneway 的立即返回作为业务成功证明。
