深入理解 Android:Binder 通信机制

Native 层 Binder 通信:

初始化 ProcessState:

  1. 单例模式,一个进程只能初始化一次;

  2. 构造函数初始化 mDriverFD 参数时,自动调用 open_driver(),打开 /dev/binder 设备,它是用于内核进程间通信的虚拟设备;

  3. open_driver() 返回的 mDriverFD 对象,调用 nmap() 方法,为 Binder 分配内存用于接收数据;

获取 defaultServiceManager:

  1. defaultServiceManager() 函数内部调用了 ProcessStategetContextObject() 函数;

  2. 调用 getStrongProxyForHandle(),根据索引查找对应的资源,返回一个 BpBinder 对象(如果不存在则创建);

BBinder/BpBinder:

  • BBinderBpBinder 都继承自 IBinderBpBinder 是客户端用来与 Server 交互的代理类;

  • Binder 系统通过 handle 标识对应的 BBinder,而 BpBinder 构造函数传入的 handle0,即表示 ServiceManager 对应的 BBinder;

BPServiceManager:

  • 通过 DECLARE_META_INTERFACEIMPLEMENT_META_INTERFACE 宏, 利用 BpBinder 对象创建 BpServiceManager 对象;

  • BpServiceManager 对象的 mRemote 变量指向了 BpBinder;

ServiceManager:

  • 集中管理系统所有服务(支持通过字符串查找),并控制权限: svc_can_register() 判断注册服务的进程是否有权限,allowed 数组定义了具有 root 和 system 权限的进程列表;

  • binder_open():调用 open() 打开 Binder 设备,并调用 mmap() 进行内存映射;

  • binder_become_context_manager():调用负责系统 IO 通道管理的 ioctl() 函数将 handle 设为 0;

  • binder_loop()for(;;) 调用 ioctl()binder_parse() 处理请求;

注册 Service:

  1. 上面 defaultServiceManager() 返回的实际上是 BpServiceManager 对象;

  2. 调用 BpServiceManageraddService() 函数,把请求的数据打包为 Parcel 对象,传给 BpBinder 对象的 transact() 函数 (客户端 Service 需要实现 onTransact() 方法);

  3. BpBinder 对象的 transact() 函数调用了 IPCThreadStatetransact() 函数;

通信 (IPCThreadState):

  1. 每个线程都有唯一的、不共享的 ThreadLocalStorage(TLS);

  2. 每个线程都有一个 IPCThreadState,而每个 IPCThreadState 都有一个接收 Binder 数据的 mIn 对象和一个存储发往 Binder 数据的 mOut 对象;

  3. 调用 writeTransactionData() 写入数据:设置 binder_transaction_datatarget 为传入的 handle,调用 mOut.write() 写入数据;

  4. 调用 waiteForResponse() 等待响应:

    1. while(1) 内部调用 talkWithDriver()binder_write_read 是和 Binder 设备通信的数据结构;

    2. 处理 BR_ERROR、BR_TRANSACTIONBR_DEAD_BINDERBR_SPAWN_LOOPER (需要创建新线程) 等消息;

处理 Dead 事件:

  1. 如果要在 Binder 通信中收到 Dead 通知,需要继承 IBinder::DeathRecipient 类,并实现 binderDied() 函数;

  2. 调用 BpBinderlinkToDeath() 函数可注册通知,调用 unlinkToDeath() 可取消注册;

  3. IPCThreadStateexecuteCommand() 函数在收到 BR_DEAP_BINDER 消息后,调用 BpBindersendObituary() 函数发通知;

开启并加入线程池:

  1. startThreadPool(): 创建一个 PoolThread 对象,它是 IPCThreadState 中定义的 Thread 子类;

  2. joinThreadPool(): 调用 androidSetThreadSchedulingGroup()talkWithDriver();

Java层初始化Binder:

IBinder 接口:

  1. 内部定义了一个整型的 FLAG_ONEWAY 变量,用于 Java 层 Binder 请求的非阻塞调用(不用等待返回),而 Native 层 Binder 请求是阻塞的;

  2. Binder 类和 BinderProxy 均实现了 IBinder 接口;

服务端 Binder 类:

  1. 初始化 gBinderOffsets 对象,它保存了和 Binder 相关的 JNI 信息(MethodID 等);

  2. 注册 JNI 函数;

BinderInternal 类:

  1. 专门用于 Binder,内部定义了一个 GcWatcher 类处理 Binder 相关垃圾回收;

  2. 初始化过程和 Binder 类似,也有 gBinderInternalOffsets 对象;

客户端 BinderProxy 类:

  1. 除了初始化 BinderProxy 类的 JNI 信息,还有 WeakReference 类和 Error 类;

Java 层 Binder 通信:

ServiceManager::addService:

  1. 调用 BinderInternal.getContextObject(), 创建 Java 层 BinderProxy 对象,它通过 JNI 和 Native 层的 BpProxy 挂钩,而 BpProxy 的通信目标就是 ServiceManager;

  2. 调用 IServiceManager.asInterface(),根据上面的 Proxy 对象创建 ServiceManagerProxy 对象,他会将请求打包给 BpProxy,最终由 BpProxy 发给 Binder 驱动;

  3. 调用 ServiceManagerProxy.addService(),内部调用 Parcel.writeStrongBuffer()BinderProxy.transact(), 最终还是会调用 Native 层的 BinderProxy.transact()

  4. Parcel.writeStrongBuffer() 添加的实际上是一个 JavaBBinder 对象;

JavaBBinder/JavaBBinderHolder/Binder:

  1. Native 的 JavaBBinder 通过 mObject 变量指向 Java 层 Binder; 收到请求时调用绑定的 Binder 层 onTransact() 方法;

  2. Java 层 Binder 通过 mObject 变量指向 Native 的 JavaBBinderHolder;

  3. JavaBBinderHolder 通过 mBinder 变量指向 JavaBBinder,它仅从 RefBase 派生;

ServiceManager 响应客户端 Binder 请求:

调用 Binder 类的 execTransact() 方法,内部调用 onTransact() 方法,具体 Sercvice 需实现这个方法;


参考:

《深入理解 Android: 卷 I》