说起binder我们貌似在一个地方用过,就是service中用到的,里面有一个重写的方法onBind,这个方法返回的就是一个binder对象,我们的activity和services就是通过这个binder对象实现通信的,除了这点以外,binder还有一个重要的地方,那就是进程间通信,AIDL正是基于binder机制来实现的,所以搞清楚binder机制是很重要的。

1.要实现夸进程通讯,会采用C/S架构,即客户端服务端模式,这种针对于android进程间通讯的机制就叫做binder机制。针对于这套机制,从大的方面来说,我们把这套机制分成三层:
                 

  java层(上层)         BinderProxy (client)            Binder(server)
                                                |                                                       ^
                                                V                                                       |
                                      -----------------------                       ----------------------------
  native层(中间层)     BpBinder                                    javaBBinder
                                                |                                                       ^
                                                V                                                       |
                                          -----------------------                     ----------------------------
                                                       |                                               ^
                                                       V                                               |

binder驱动层(底层)                               Binder驱动






通过上面这个图表我们看到有三层:java层,native层,binder驱动层,如图表中的箭头所示,当我们开始夸进程通讯的时候,我们的信息会从client端发出,经过client的native层,然后来到了binder驱动,随后这个信息又给到了server的native层,最后在把这个信息给到了server的java层,这样就完成了一个夸进程通讯。疑问来了,这个native层和这个java层是什么关系呢,其实java层的binder架构是native层binder架构的一个镜像,这个镜像最终还是需要借助native层的binder系统来开展工作。

首先,我们先来说说java层中的binder成员,在这一层中定义了两个接口三个类,分别是IBinder接口,DeathRecepient接口,BinderInternal类,Binder类,BinderProxy类。那他们是什么关系呢?
     (1)DeathRecepient接口是在IBinder接口内部定义的一个接口
      (2)Binder类和BinderProxy类implements自IBinder接口
     (3)BinderInternal类相当于binder架构的一个辅助类,例如处理类似垃圾回收这样的工作。
     除此之外,在IBinder接口中还定义了一个叫做FLAG_ONEWAY的整形变量,这个变量的作用是什么呢?在此说明一下,当进行一次跨进程通讯的时候,但我们指明了这个变量后,客户端只需要把请求发送到Binder驱动即可,不用等待服务端的返回结果,这就是一种非阻塞的方式;如果不指明,客户端会一直阻塞,直到有返回结果。

然后,来说一下java层binder框架的初始化,在java层初创时期,系统会提前注册一些JNI函数,有一个函数专门负责搭建Java Binder和Native Binder的交互关系,这个函数是register_android_os_Binder(),这里面总共又调用了三个函数,分别是int_register_android_os_Binder(env),int_register_android_os_BinderInternal(env),int_register_android_os_BinderProxy(env),从这个三个函数的名字可以看出来,他们分别映射了和java层Binder,BinderInternal,BinderProxy的关系,其实就是建立java层对象和与其对应的jni层对象的联系,所谓的注册其实就是获取jclass对象,并且获取有用的methodId,并将获取的methodID保存到相关的Offsets静态类对象中。

下面通过两个例子来说明一下,如何进行进程间通信的,第一个例子是AMS将自己注册到ServiceManager,第二个例子是AMS如何响应客户端Binder请求。
先说第一个:
ActivityManagerService m=self;
通过调用ServiceManager.addService("activity",m);将需要的service注册到ServiceManager中,现在进入到addService()方法中,里面有一个getIserviceManager.addService(name,service);所以先看看getIserviceManager,在这个方法中是一个sServiceManger=ServiceMangerNative.asInterface(BinderInternal.getContextObject());这个方法中的asInterface方法看起来似乎很眼熟,因为在AIDL中经常会见到这个方法,他的参数BinderInternal.getContextObject()是一个native方法,这个方法里面就是创建一个java层的BinderProxy对象,并且将这个对象与一个jni层的BpBinder对象关联,这里面还有一个BpProxy对象,这里面认为BpBinder对象和BpProxy对象就是一个,所以总的来说BinderInternal.getContextObject()方法就是返回一个BinderProxy对象,然后我们通过操纵BinderProxy对象来镜像控制jni层的BpBinder对象,BpBinder对象和BpProxy对象关联,BpProxy对象的通信目标就是ServiceManager.接下来ServiceMangerNative.asInterface(。。。obj)通过组合obj返回了一个ServiceManagerProxy对象(sServiceManger),在调用ServiceManagerProxy对象的addServices()方法,那么接下来我们进入到这个方法里面看看,这里面有两个重要的方法,一个是data.writeStrongBinder();另一个是mRemote.transact();这个mRemote其实就是前面所产生的BinderProxy对象,transact()方法是个native方法,该方法调用之前与之相关联的BpBinder方法的transact()方法,最后总的来说就是调用BpBinder的transact()方法。这样就完成了把请求传递到binder驱动了。那前面说的data.writeStrongBinder()这个方法呢?这个方法其实就是完成了一个替换工作或者说是建立了一种连接,建立了和谁的连接呢,其实就是JavaBBinder和Binder的连接,所以真正传递到binder驱动的就是这个JavaBBinder对象,当驱动收到这个JavaBBinder对象的时候,就会调用他的onTransact()方法,这个方法又会调用与之相关联的java层的binder对象的exeTranscat()方法,这个方法里面又调用了onTransact()方法,这个onTransact()里面会实现具体的业务逻辑。