Service Manager 的工作就是登记功能。服务通过add_service方法将自己的名字和Binder 标识handle 登记在svclist 中。而服务请求者,通过check_service方法,通过服务名字在service list 中获取到service 相关联的Binder 的标识handle,通过这个Handle 作为请求包的目标地址发起请求。
通讯:IPC。Android 设计者在Linux内核中设计了一个叫做Binder 的设备文件,专门用来进行Android 的数据交换。从数据流来看Java 对象从Java 的VM 空间进入到C++空间进行了一次转换,并利用C++空间的函数将转换过的对象通过driver\binder 设备传递到服务进程,从而完成进程间的IPC。
(1)从JVM 空间传到c++空间,这个是靠JNI 使用ENV 来完成对象的映射过程。
(2)从c++空间传入内核Binder 设备,使用ProcessState 类完成工作。
(3) Service 从内核中Binder 设备读取数据。
在ProcessState类中包含了通讯细节,利用open_binder打开Linux设备dev/binder,通过ioctrl建立的基本的通讯框架。利用上层传递下来的servicehandle来确定请求发送到那个Service。Bnbinder,BpBinder的命名含义,Bn-代表Native,而Bp代表Proxy。
在做服务请求时,Android建立一个新的Service Manager Proxy。Service Manager Proxy使用ContexObject作为Binder和Service Manager Service(服务端)进行通讯。
Android代码一般获取Service建立本地代理的用法如下:
IXXX mIxxx=IXXXInterface.Stub.asInterface(ServiceManager.getService("xxx"));
例如:使用输入法服务:
IInputMethodManager mImm=IInputMethodManager.Stub.asInterface(ServiceManager.getService("input_method"));
这些服务代理获取过程分解如下:
(1)通过调用GetContextObject调用获取设备上下对象。
BinderInternal.getContextObject() @BinderInteral.java
NATIVEJNI:getContextObject() @android_util_Binder.cpp
Android_util_getConextObject @android_util_Binder.cpp
ProcessState::self()->getCotextObject(0) @processState.cpp
getStrongProxyForHandle(0)
NEW BpBinder(0)
注意ProcessState::self()->getCotextObject(0)@processtate.cpp,就是该函数在进程空间建立了ProcessState对象,打开了Binder设备dev/binder,并且传递了参数0,这个0代表了与Service Manager这个服务绑定。
(2)通过调用ServiceManager.asInterface(ContextObject)建立一个代理ServiceManger。mRemote=ContextObject(Binder)
这样就建立起来ServiceManagerProxy通讯框架。
(3)客户端通过调用ServiceManager的getService的方法建立一个相关的代理Binder。
ServiceMangerProxy.remote.transact(GET_SERVICE)
IBinder=ret.ReadStrongBinder() //这个就是JVM空间的代理Binder
JNI Navite:android_os_Parcel_readStrongBinder() @android_util_binder.cpp
Parcel->readStrongBinder() @pacel.cpp
unflatten_binder @pacel.cpp
getStrongProxyForHandle(flat_handle)
NEW BpBinder(flat_handle) //这个就是底层c++空间新建的代理Binder。
Activity为了建立一个IPC,需要建立两个连接:访问Servicemanager Service的连接,具体XXX Service的代理对象IXXX与XXXService的连接。这两个连接对应c++空间ProcessState中BpBinder。对IXXX的操作最后就是对BpBinder的操作。由于我们在写一个Service时,在一个Package中写了Service Native部分和Service Proxy部分,而Native和Proxy都实现相同的接口:IXXX Interface,但是一个在服务端,一个在客服端。客户端调用的方式是使用remote->transact方法向Service发出请求,而在服务端的OnTransact中则是处理这些请求。所以在Android Client空间就看到这个效果:只需要调用代理对象方法就达到了对远程服务的调用目的,实际上这个调用路径好长好长。