Binder是Android进程间通信的一种方式。要明白binder首先要对进程间通信有个概念。所谓进程间通信就是两个进程互相通信,通信需要有通信协议,不然通信双方都不明白对方意图,通信同样需要信息载体来传输信息,不然信息无法到达目的地。

  就好比我们和朋友之间写信,通信的规则就是:1.你要有对方的地址,这样邮局能够找到对方;2.需要信纸作为载体;3.朋友家需要有邮箱才能收到信件。在邮局送信的过程中有可能你的朋友已经搬家了,你又希望邮局遇到这种情况能给你通知,那么你就要用挂号信,这个时候邮局就会在查无此人的情况下会给你一个通知。人类之间的这种交流抽象在程序中就变成了进程之间的通信。在android中就提供binder这一套协议来完成了上面的这个功能。
  我们将上面的过程抽象到程序设计中,假设有这样的一个场景:
  进程A需要和进程B通信,A需要B完成一个功能c。那么A需要传递一个标记给B,明确自己想要B完成的功能,我们可以为这个标记编号。同时A申明:如果B不存在了希望收到通知。通信的第一步:B要让A能找到自己,于是B会向管理部门注册自己所拥有的功能模块。这里管理部门在binder中是ServiceManager,我们简称为SM。A通过向SM查询得到B的功能模块的地址,然后通过这个地址给B发送功能编号,这个编号信息通过binder驱动传递给B。B收到这个编号后调用相应的函数完成请求,然后返回结果给A。如果binder驱动在转发信息的时候发现B已经不存在了,就会通知A,你请求的对象已经死亡啦,A会收到B的死亡通知。B进程中提供功能的模块称为Service,A可以称为Client。Client请求SM得到的地址实际上是Service的一个代理proxy,这个代理类封装了发送请求的过程。所以我们只需要得到一个Service的代理就可以去调用Service的功能而不用去关心消息是如何的封装与传递的。这样一来,Client取得代理类之后,通过调用代理类的函数,最终这个函数的会发请求给Service,由Service来完成对应的功能。
  整理上面的过程:进程间的通信模型为Client/Service。一次通信的完成需要四个角色:Service(提供服务),Client(发送请求),ServiceManager(管理所有Service的部门),binder驱动(传递信息)。下面是一张简图:描述它们之间的关系


  在Android中,用什么来表示Service?Client取得的Service的代理又具体是什么呢?ServiceManager是个怎么实现的呢,为什么Client一定可以找到它的地址,然后给它发送查询服务的请求呢?带着这些疑问,我们来看一张类图。

 

在上面途中MediaPlayerService就是一个Service,途中也显示了它的继承关系。右边框中的BpMediaPlayerService是它的代理类。IMediaPlayerService是这两者的接口类,它定义了一些函数接口,表示MediaPlayerService所能提供的功能,在上面的例子中我们假设有一个功能是play()。在MediaPlayerService和BpMediaPlayerService都分别实现了这个虚函数,不过,BpMediaPlayerService中的play()只是将函数参数和参数所对应的编号打包,然后调用BpBinder的transact函数将这些信息透过binder驱动发送给MediaPlayerService,最终由MediaPlayerService去完成对应的功能。

BpBinder和BBinder这两个类都是和binder驱动通信相关的类,它们负责通信数据在应用层之间的传递,并不明白这些数据是什么含义,可以称他们为应用层的通信媒介。BpMediaPlayerService负责通信数据打包,BnMediaPlayerService负责通信数据的解析,MediaPlayerService负责完成通信请求的功能。BpInterface和BnInterface继承了通信媒介类和业务接口类,然后BpMediaPlayerService和BnMediaPlayerService分别继承这两个类,完美的将通信层和业务层结合到了一起,所以对于client来说,调用BpMediaPlayerService的函数play()就好像调用本地函数一样,因为BpMediaPlayerService封装了数据传输的过程。

讲到这里还有几个问题没有涉及:
1.client端如何取得BpMediaPlayerService?

2.BpMediaPlayerService将通信数据传递给binder驱动之后,binder驱动如何决定这些数据传递给哪一个Service来处理呢?

3.如果MediaPlayerService死掉了,BpMediaPlayerService如何收到通知呢?

这三个问题留待下一节。