通常,应用程序框架中基于Java语言的Binder接口是通过JNI来调用基于C/C++语言的Binder运行库来为Java应用程序提供进程间通信服务的。在应用程序中,Server被实现为Service的形式,并通过IServiceManager.addService接口来把这个Service添加到Service Manager中;Client也是通过IServiceManager.getService接口来获得Service接口,这样就可以使用这个Service提供的功能了。
这里,我们以XXXService代表XXX的Service服务为例,把整个交互的过程分为如下几个部分来分析:
5.1 Binder framework层的初始化
在java层工作前,需建立与Native层的关系,建立这个关系的函数是 android_util_Binder.cpp::register_android_os_Binder(),流程如下:
作用:初始化其实就是提前获取一些JNI层的使用信息,这样可以节省每次使用时获取这些信息的时间
5.2 Binder framework层构架总览
这里解释一下Java Binder, Java Internal, Java Proxy,以及IBinder的关系:
5.3 C/S获得ServiceManager的Java远程接口过程
我们要获取的ServiceManager的Java远程接口是一个ServiceManagerProxy对象的IServiceManager接口,如上图。IServiceManager接口提供了getService()和addService()两个函数来管理Service。从serviceManagerProxy的构造函数中发现,它需要一个BinderProxy对象的IBinder接口作为参数;所以得先获得BinderProxy对象。
上图中,我们可以看到获取SM的Java远程接口ServiceManagerProxy的路径,是通过ServiceManager.getIServiceManager()来获取,而该函数又是通过ServiceManagerNative来获取。
我们先来分析getIServiceManager()
5.3.1 ServiceManager.getIServiceManager()
这个函数定义在frameworks/base/core/java/android/os/ServiceManager.java文件中,里面的核心代码:
如果其静态成员变量sServiceManager尚未创建,首先要通过BinderInternal.getContextObject()来获得一个BinderProxy对象,再调用ServiceManagerNative.asInterface()来创建对应的ServiceManagerProxy对象
接下来通过BinderInternal.getContextObject() 和ServiceManagerNative.asInterface()两个部分来分析。
5.3.1.1 BinderInternal.getContextObject()
BinderInternal.getContextObject()这个函数定义在frameworks/base/core/java/com/android/internal/os/BinderInternal.java文件中,调用了JNI层的android_os_BinderInternal_getContextObject()。android_os_BinderInternal_getContextObject()是一个JNI方法,在frameworks/base/core/jni/android_util_Binder.cpp文件中,核心代码为:
5.3.1.2 ServiceManagerNative.java::asInterface()
接下来调用asInterface(),定义在frameworks/base/core/java/android/os/ServiceManagerNative.java 文件中:
这样,在getIServiceManager()中:sServiceManager = ServiceManagerNative.asInterface(new BinderProxy()); 相当于:sServiceManager =new ServiceManagerProxy(new BinderProxy());
5.3.2 获得SM的Java远端接口整体流程
这样,申请者在Java层拥有了一个Service Manager远程接口ServiceManagerProxy,这个ServiceManagerProxy对象在JNI层有一个handle值为0的BpBinder对象与之通过gBinderProxyOffsets关联起来,整体流程如下:
5.4 Service启动过程
XXXService继承了IXXXService.Stub类,并通过本地方法实现了Stub类的业务函数,有了XXXService之后,我们就会把它的Server类SystemServer启动起来。
定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中,SystemServer对象是在系统启动时创建的,创建后会启动一个线程来创建XXXService,并把它添加到SM中去
在serverThread extends Thread中:ServiceManager.addService("XXX", new XXXService());
下面我们会进行new XXXService() 和 ServiceManager.addService()两部分的分析
5.4.1 new XXXService()
New XXXService()会调用XXXService类的构造函数,而XXXService类继承于IXXXService.Stub类(XXXNative),Stub类又继承于Binder类,因此会调用Binder类的构造函数,在这个构造函数里,又会调用init()来初始化这个Binder对象
init()只做了一件事,就是创建一个JavaBBinderHolder对象,然后把这个对象的地址保存在Binder类的mObject成员变量中
那么结果为:获得了一个新的实例XXXService(); 且Java层的Binder对象把Native层的JavaBBinderHolder(就是BBinder)保存在变量mObject中
5.4.2 ServiceManager.addService()的实现
分析完了new XXXService(),再来看下ServiceManager.addService()的实现,核心代码:
getIServiceManager()之前分析过,返回一个ServiceManagerProxy对象的IServiceManager接口,那么我们看ServiceManagerProxy.addService()的实现:
addService()最终会调用到Framework层的BinderProxy.transact();最后调用到Native层的BpBinder::transact()进入到Binder驱动,然后驱动唤醒SM响应这个ADD_SERVICE_TRANSACTION请求,把自己注册到SM中;
AMS在SM中注册服务流程图
XXXService注册服务的类图
5.5.1 Client获得XXXService的Java远程接口过程
Client是通过IServiceManager.getService()来获得XXXService的远程接口的;在client这边的onCreate()中调用IXXXService.Stub.asInterface(ServiceManager.getService(“XXX”)); 先看ServiceManager.getService(“XXX”)
ServiceManager.getService(“XXX”)。实际是调用了ServiceManagerProxy.getService(),这个函数通过mRemote.transact执行操作;和前面一样mRemote是一个BinderProxy对象。
然后调用IBinder binder = reply.readStrongBinder();作用是:调用JNI层的 android_os_Parcel_readStrongBinder(),其作用是把Java语言的Parcel对象转换成C++语言的Parcel对象parcel,并通过parcel->readStrongBinder函数来获得一个Binder引用的BpBinder对象
最后:
javaObjectForIBinder()之前介绍过,会创建一个BinderProxy对象。相当于: return javaObjectForIBinder(env, new BpBinder(handle)); 返回给上层getService()的binder对象
那么 XXXService = IXXXService.Stub.asInterface(ServiceManager.getService("XXX")); 相当于:XXXService = IXXXService.Stub.asInterface(new BinderProxy()));
5.5.2 IXXXService.Stub.asInterface()
这个函数的核心代码为:
相当于:return new android.os.IXXXService.Stub.Proxy(new BinderProxy());
这样就获得了XXXService的远程接口了,实质上是实现了IXXXService接口的IXXXService.Stub.Proxy对象
获得XXXService的类图
client使用XXXService框架图
5.6 framework层总结
Native层和Java层的关键点:
针对Java层C/S交互的5个步骤的总结:
虽然Binder机制的代码层层嵌套,逻辑复杂,但Binder机制的实质就是实现不同进程间的通信,通过SM来管理跨进程的服务;理解这一点,就可以理清Binder的核心:通信的实现最终都会由Binder的驱动实现,Native层和Java层的复杂构架,是出于2方面考虑: