通过熟悉Android系统的框架知道,Android应用程序之间通信主要是通过JNI调用C/C++语言的Binder运行库来实现java应用程序之间的通信的.
其实Binder机制的在应用程序的java接口,主要是通过ServiceManager ,Server,Client三个角色之间的实现.在应用程序中,我们通常把Server实现为Service形式,通过IServiceManager.addService把Service添加到ServiceManager进去,而Client通过IServiceManager.getService来获取Service的接口,就可以使用这个Service接口了.这个与运行的Binder运行机制一样.
ServiceManager 的java远程接口主要是一个ServiceManagerProxy对象的IServiceManger接口.
接下来我们看看流程图:
通过以上我们知道,ServiceManagerProxy.java主要实现了IServiceManager接口.IServiceManager有getService和addService方法,从ServiceManagerProxy构造函数可以看出需要传递一个BinderProxy对象.
接下来具体分析下BinderProxy对象是如何获得的.
在分析BinderProxy之前,我们先分析下ServiceManager是什么养子的.
ServiceManager类有一个静态成员函数getIServiceManager,它的作用就是用来获取Service Manager的Java远程接口了,而这个函数又是通过ServiceManagerNative来获取Service Manager的Java远程接口的。
接下来,我们就看一下ServiceManager.getIServiceManager这个函数的实现,这个函数定义在frameworks/base/core/java/android/os/ServiceManager.java文件中:
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
通过以上代码可以看出,sServiceManager如果没有创建,会通过ServiceManagerNative.asInterface去创建.但是在创建之前先要BinderInternal.getContextObject()这个binder对象.
还有其实创建
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
就相当于创建
sServiceManager = ServiceManagerNative.asInterface(new BinderProxy());
接下去就是调用ServiceManagerNative.asInterface函数了,这个函数定义在frameworks/base/core/java/android/os/ServiceManagerNative.java文件中:
public abstract class ServiceManagerNative extends Binder implements IServiceManager
{
/**
* Cast a Binder object into a service manager interface, generating
* a proxy if needed.
*/
static public IServiceManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ServiceManagerProxy(obj);
}
这里的obj是一个binder对象,通过以上就是创建了一个ServiceManagerProxy对象.
总结一下,其实在拥有了一个ServiceManager远程接口ServiceManagerProxy,而这个ServiceManagerProxy在JNI层有一个句柄值为0的Binder对象与之通过gBinderProxyOffsets关联起来了.这样获取java层远程接口就完成了.