今天这篇文章是通过看源码的方式做总结:
- 从客户端的应用层到binder驱动,然后从binder驱动在到服务端的应用层
- Binder的协议通信流程
还是根据这幅图,我们来看下源码,从客户端到服务端的流程:
1、客户端Proxy调用fromwork的是java层BinderProxy
2、fromwork的是java层BinderProxy调用 native的Bpbinder
3、native的Bpbinder调用IPCThreadState的transact
3.1Pracel数据转换成Binder识别的数据,Binder_transaction
3.2 先在驱动里面写数 ,然后通过驱动的回复标记,处理操作,收到REPLY后,在mIn中读出来转成Parcle返回回去
3.3由此可以看出,最终与驱动的数据是binder_write_read 不是parcel 不是binder_transaction,最终调用iocl写出去。但是注意代码看出,写的优先级 高于读的优先级
至此 客户端的操作看完了,我们接着看下服务端的操作
继续看BBinder怎么传到java层的
调用transact()
2.调用Framwork层的binderProxy 的tranceNative()
3.然后通过Parcel转换成BpBinder,再次transact()
4.此时会调用IPCThreadState的tansact(), 注意和驱动打交道的是IPCThreadState,不是BinderProxy,也不是BpBinder。
- 着重介绍一个IPCThreadState的tansact方法第一个参数mHandle:和Binder驱动交互的时候,只传mHandler,驱动和mHandle知道对应的binder引用,也就会找到对应的binder实例
5.IPCThreadState的tansact, 注意:IPCThreadState中由两个引用mOut: 我们在驱动写东西的时候,先这里面。 mIn:我们在驱动中读数据的时候, 先读到mIn中
- a.第一件事:是先把java层的数据转换数据格式parcel转换成binder_transaction.
- b.第二件事:在一个循环中,先与驱动交互把数据写出去,然后不断接收驱动指令。(这里注意最终和Binder数据格式事binder_write_read,不是parcel也不是binder_transaction)
- BC_TRANSACTION: 表示驱动已经接收到客户端的请求了
- BC_REPLY: 表示服务端已经接收到请求,可以退出了
- c.收到BC_REPLY指令后,从mIn中binder_trancasion在转成Parcle,返回上层
服务端流程:
1、new 一个普通线程,然后传入Binder驱动,成为binder线程池
- BC_ENTER_LOOPER : 表示这个线程主动注册到Binder驱动
- BC_REGISTER_LOOPER: 被动处理,由Binder驱动先申请,然后应用再来注册
2、进入循环里面操作
- a、从驱动中取数据(mIn中取出来转成对应的数据格式)
- b、从mIn中不断的读取指令,进入case操作。(根据不同指令,走不通的case,流程:client请求发给驱动,驱动发给Server,Server的binder线程中就会收到这个指令)
- c、case中接收指令BR_TRANSACTION,读出数据转成parcel转给上层(java层)
- d、传到上层以后,往驱动写一跳数据指令为BC_REPLY,客户端接收到这个标记以后,就可以退出返回了,然后我们发送请求的时候waitForResponse(null,null), 表示不用等待请求返回结果
3、BBinder怎么传到java层的?
- a、在native通过JNI调用,调用Binder对象的onTransact()方法。 Binder对象就是AIDL生成的Stub类
- b、调用本地函数publishBinder,调用本地函数,把binder存起来
4、解释一下asInterface(): 先从客户端发过来的数据中把binder读出来,然后在转化成业务接口的对象,Binder到server端就binderProxy了