简单来说,Binder就是规定了客户端和服务端通信的一堆API,这些API被定义在一个接口当中。假设名字为IMyName,注意,一定是I+名字的结构。这个接口一定要继承IInterface。现在,这个IMyName就是Binder的client端与server端通信的协议了。
然后,我们通过IMyName扩展出分别用于client端和server端的接口,BpInterface和 BnInterface。通过这两个接口,client端和server端分别实现了两个类BpMyName和 BnMyName。
最后,BpMyName和BnMyName中都对每个IMyName中的接口做了实现。
BpMyName中实现每个接口时,都是调用IBinder.transact()并传入相应方法的ID来做到。
而BnMyName就要复杂一些。首先,定义一个类SomeClass来继承并实现BnMyName,这个类在命名上没有要求。在 SomeClass中对IMyName中每个接口都做了实现。在BnMyName中有一个onTransact方法,它与BpMyName中调用 IBinder.transact方法是对应的。这样,在BnMyName的onTransact方法中,根据不同的code调用不同的IMyName中的方法,而这些方法都是在SomeClass中实现的。
下面的图示意一下,可能更清楚:
IInterface
|
IMyName
| |
BpInterface BnInterface
| |
BpMyName BnMyName
|
SomeClass
当某个类使用到了IMyName中的API时,你会发现IMyName仅是个接口,里面的API全是抽象的。要找到这个API的实现,就需要根据上面示意的层次找到这个SomeClass类,这个类在命名上没有什么特征,只有一点儿,它继承了BnMyName。
声明一个服务时,一般该服务都要继承BinderService<xxx>和Bnxxx。
它是Binder服务模块要继承的基类,主要用于将该Binder服务注册到ServiceManager中。如CameraService。
当然也不是服务模块必须继承BinderService,如MediaPlayerService。
要成为一个服务端,最重要的是往ServiceManager注册。
Bnxxx是Service要继承的基类,它负责和客户端通信。所有的Bnxxx都只有一个函数onTransact,它是根据收到的消息码调用相应的Service函数进行处理。
Bnxxx继承Ixxx和BBinder,Ixxx定义的服务端和客户端之间的通信接口;BBinder定义了onTransact。
Ixxx规定的是服务端提供的接口,客户端要通过这些接口来向服务端请求,所以客户端保存的服务端标识都是Ixxx mXxx型的变量。客户端不可能直接调用Xxx类,因为它们在两个进程。
上面的描述有一点不合适,客户端有时也定义了Ixxx的接口,它一般是服务端对客户端的回调。所以Ixxx更准确的表达是本模块向外提供的接口,本模块既可以是服务端也可以是客户端。
下面我们以Camera为例进行说明。
当Binder服务端出现异常时,对客户端的通知。用户要实现DeathRecipient定义的binderDied虚函数,一般是对某些资源的释放。每个客户端都有自己的DeathRecipient对象,需要将这个对象注册到自己的服务端,代码如下defaultServiceManager()->getService(String16("media.camera"))->linkToDeath(mDeathNotifier),当服务端异常后,会掉用相应的binderDied通知。
当然如果客户端异常或者提前释放时,也要将这个DeathRecipient对象从服务端注销,代码如下defaultServiceManager()->getService(String16("media.camera"))->unlinkToDeath(mDeathNotifier)。
之前我们说到的服务都是要注册到defaultServiceManager的服务,还有很多服务没有进行注册,也可以使用。下面我们以Camera客户端Connect到CameraService后,CameraService要创建一个Client来服务Camera客户端,而这个Client其实就是一个未注册的Service。
sp<ICameraClient> cameraClient =interface_cast<ICameraClient>(data.readStrongBinder());
sp<ICamera> camera =connect(cameraClient, data.readInt32());
reply->writeStrongBinder(camera->asBinder());
首先获得客户端cameraClient,然后创建Client服务camera,然后通过writeStrongBinder将camera设为服务。
以Camera为例说明,共三种关系。
ICameraService
客户端要请求Service完成拍照的功能,首先要让Service创建一个子项专门处理该客户端的请求,这个子项就是CameraService::Client。
该接口主要提供获得摄像头的个数、创建CameraService::Client等功能。如下图:
ICamera
定义摄像头的功能接口,如设置参数、拍照、停止等操作。框架如下图:
ICameraClient
客户端提供的回调函数接口,也可见,不一定Service才能够向外提供服务,客户端照样可以,框架如下图:
函数 |
功能说明 |
使用方法 |
|
|
|
DECLARE_META_INTERFACE |
对I**的声明 声明接口的构造和析构函数 |
DECLARE_META_INTERFACE(Camera)等同于 static const android::String16 descriptor; static android::sp<ICamera> asInterface(const android::sp<android::IBinder>& obj); virtual const android::String16& getInterfaceDescriptor() const; ICamera (); \ virtual ~ICamera (); |
IMPLEMENT_META_INTERFACE |
对Bp**的建立 1. asInterface:新建Bp**** 2. 构造和析构函数的实现 |
IMPLEMENT_META_INTERFACE(Camera, "android.hardware.ICamera");等同于 const android::String16 ICamera::descriptor("android.hardware.ICamera"); const android::String16&ICamera::getInterfaceDescriptor() const { return ICamera::descriptor; } android::sp< ICamera> ICamera::asInterface(const android::sp<android::IBinder>& obj) { android::sp<ICamera> intr; if (obj != NULL) { intr = static_cast< ICamera *>(obj->queryLocalInterface(ICamera::descriptor).get()); if (intr == NULL) { intr = new BpCamera (obj); } } return intr; } ICamera:: ICamera () { } ICamera::~ ICamera () { } |