binder java层_Binder机制4---Framework层

5. Binder机制的Java接口

通常,应用程序框架中基

于Java语言的Binder接口是通过JNI来调用基于C/C++语言的Binder运行库来为Java应用程序提供进程间通信服务的。在应用程序

中,Server被实现为Service的形式,并通过IServiceManager.addService接口来把这个Service添加到

Service

Manager中;Client也是通过IServiceManager.getService接口来获得Service接口,这样就可以使用这个

Service提供的功能了。

这里,我们以XXXService代表XXX的Service服务为例,把整个交互的过程分为如下几个部分来分析:初始化Framework层Binder框架

C/S获得ServiceManager的Java远程接口过程

XXXService的接口定义和启动过程,添加自己到SM中

Client获得XXXService的Java远程接口过程

Client通过Java远端接口使用XXXService提供的服务

2fe724042e2210e9e4f8dffc42993cbb.png

5.1 Binder framework层的初始化

在java层工作前,需建立与Native层的关系,建立这个关系的函数是 android_util_Binder.cpp::register_android_os_Binder(),流程如下:初始化Java Binder类和Native层的关系:调用 int_register_android_os_Binder(env)找到Java层的Binder

通过gBinderOffsets对象保存和Binder类相关的某些在JNI层中使用的信息

注册Binder类中native函数的实现

初始化Java BinderInternal类和Native层的关系:调用 int_register_android_os_BinderInternal(env)根据BinderInternal的全路径(com/android/internal/os/BinderInternal)找到代表该类的jclass对象

通过gBinderInternal静态对象,保存BinderInternal类的一些信息:如methodID和filedID

注册BinderInternal类中native函数的实现

初始化 Java BinderProxy类和Native层的关系:调用 int_register_android_os_BinderProxy(env)通过gWeakReferenceOffsets来和WeakReference类交互,包括:获取WeakReference类get函数的methodID

通过gErrorOffsets来和Error类交互

通过gBinderProxyOffsets来和BinderProxy类交互,包括:获取BinderProxy的一些信息

通过gClassOffsets来和Class类交互

注册BinderProxy native函数的实现

初始化Java Parcel类和Native层的关系:调用 int_register_android_os_Parcel(env)

3d0a80de7d5e213601e53819e0e2cb14.png

作用:初始化其实就是提前获取一些JNI层的使用信息,这样可以节省每次使用时获取这些信息的时间

5.2 Binder framework层构架总览

37a7a1330381213204b3432ae3c00328.png

这里解释一下Java Binder, Java Internal, Java Proxy,以及IBinder的关系:系统定义了一个IBinder接口类以及DeathRecipient接口。IBinder接口类中定义了FLAG_ONEWAY标志,作用是实现非阻塞,只把请求发送到Binder驱动即可返回,不用等待服务端的结果。

Binder类和BinderProxy类分别实现了IBinder接口。Binder类作为服务端Bn的代表;BinderProxy类作为客户端Bp的代表

BinderInternal类仅供Binder架构使用,其内部有一个GcWatcher类,专门用于处理和Binder架构相关的垃圾回收

Java层同样提供一个用于承载通信数据的Parcel类

5.3 C/S获得ServiceManager的Java远程接口过程

a0de387b1de8b72c0118eed7df280894.png

我们要获取的ServiceManager的Java远程接口是一个ServiceManagerProxy对象的IServiceManager

接口,如上图。IServiceManager接口提供了getService()和addService()两个函数来管理Service。从

serviceManagerProxy的构造函数中发现,它需要一个BinderProxy对象的IBinder接口作为参数;所以得先获得

BinderProxy对象。

99a452e1c9641d290de330cb6b6bb3c3.png

上图中,我们可以看到获取SM的Java远程接口ServiceManagerProxy的路径,是通过ServiceManager.getIServiceManager()来获取,而该函数又是通过ServiceManagerNative来获取。

我们先来分析getIServiceManager()

5.3.1 ServiceManager.getIServiceManager()

这个函数定义在frameworks/base/core/java/android/os/ServiceManager.java文件中,里面的核心代码:sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());

return sServiceManager;

如果其静态成员变量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文件中,核心代码为:sp b = ProcessState::self()->getContextObject(NULL);ProcessState::self()->getContextObject(NULL)返回一个BpBinder对象,handle值为0,代码即可以写成:

sp b = new BpBinder(0);

return javaObjectForIBinder(env, b);   把这个BpBinder对象转换成一个BinderProxy对象object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);  创建了一个BinderProxy对象

env->SetIntField(object, gBinderProxyOffsets.mObject,

(int)val.get());

把BpBinder对象和BinderProxy对象关联起来;BinderProxy.mObject成员记录了这个BpBinder对象的地址

最后,把BinderProxy返回到android_os_BinderInternal_getContextObject函数,再返回到ServiceManager.getIServiceManager()中,我们就获得一个BinderProxy对象了

在该函数中,有两个变量gBinderOffsets和gBinderProxyOffsets:

gBinderOffsets变量是用来记录”ppt 2.”左下角第二个类图中的Binder类的相关信息的,它是在注册Binder类的JNI方法的int_register_android_os_Binder函数初始化的

gBinderProxyOffsets是用来变量是用来记录”ppt

2.”右上角第一个图中的BinderProxy类的相关信息的,它是在注册BinderProxy类的JNI方法的

int_register_android_os_BinderProxy函数初始化的

核心代码:

在getIServiceManager()中的:sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());

相当于:sServiceManager = ServiceManagerNative.asInterface(new BinderProxy());

5.3.1.2 ServiceManagerNative.java::asInterface()

接下来调用asInterface(),定义在frameworks/base/core/java/android/os/ServiceManagerNative.java 文件中:asInterface(IBinder

obj):obj是一个BpProxy对象或者BinderProxy对象(取决于这个申请SM的Java层远程接口的对象是Client还是

Server),构造一个和业务相关的Proxy对象。这里我们假设申请者是client,构造了ServiceManagerProxy对象

这样,在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关联起来,整体流程如下:

bcf0e881d4be7559fe42ef637602fe17.png

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()

9730584d7d5e37f5cd9ae670305d3378.png

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().addService(name, service);

getIServiceManager()之前分析过,返回一个ServiceManagerProxy对象的IServiceManager接口,那么我们看ServiceManagerProxy.addService()的实现:获得Parcel类型的data和reply

data.writeStrongBinder(service)

调用mRemote.transact(ADD_SERVICE_TRANSACTION,data,reply,0);这里的mRemote就是BinderProxy对象,调用transact把封装好的请求数据发送出去

addService()最终会调用到Framework层的BinderProxy.transact();最后调用到Native层的

BpBinder::transact()进入到Binder驱动,然后驱动唤醒SM响应这个ADD_SERVICE_TRANSACTION请求,把自

己注册到SM中;

AMS在SM中注册服务流程图

673039216b8a0c0d77335b326d89dd03.png

XXXService注册服务的类图

b18ec6bb5d4f0e370043f91a503a2cf1.png

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对象

最后:return javaObjectForIBinder(env, parcel->readStrongBinder());

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()

这个函数的核心代码为:android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);

if (((iin!=null)&&(iin instanceof android.os.IXXXService))) {

return ((android.os.IXXXService)iin);

}

return new android.os.IXXXService.Stub.Proxy(obj);

}

这里的obj是一个BinderProxy对象,它的queryLocalInterface返回null,于是调用下面语句获得XXXService的

远程接口:    return new android.os.IXXXService.Stub.Proxy(obj);

相当于:return new android.os.IXXXService.Stub.Proxy(new BinderProxy());

这样就获得了XXXService的远程接口了,实质上是实现了IXXXService接口的IXXXService.Stub.Proxy对象

获得XXXService的类图

feada1d450c392a97b94f1dd9d3747c1.png

client使用XXXService框架图

04b8569f584d7a23f43886b024c46d09.png

5.6 framework层总结

Native层和Java层的关键点:native层中,client会有一个BpBinder引用,Server会有一个BBinder引用来实现通信;

Java层中,client会有一个BinderProxy对象,server会有一个JavaBBinder对象来负责通信,但实质的通信实现是基于native层,Native层又基于Binder驱动的

针对Java层C/S交互的5个步骤的总结:初始化Java层Binder框架,是为了减少在以后通信过程中初始化的时间

C/S获得ServiceManager的Java远程接口过程,实际上就是获得ServiceManagerProxy,为Java层提供C/S与SM通信的对象

XXXService的接口定义和启动过程,添加自己到SM中,实际上是为XXXService对象创建与SM通信的BinderProxy对象(就是步骤2),和创建为与client通信的JavaBBinder对象

Client获得XXXService的Java远程接口过程,实际上是为client创建与SM通信的BinderProxy对象(就是步骤2),和创建与XXXService通信的BinderPorxy对象

Client通过Java远端接口使用XXXService提供的服务,实际上是利用client的BinderProxy对象与XXXService的JavaBBinder对象通信,达到client使用服务的目的

虽然Binder机制的

代码层层嵌套,逻辑复杂,但Binder机制的实质就是实现不同进程间的通信,通过SM来管理跨进程的服务;理解这一点,就可以理清Binder的核心:

通信的实现最终都会由Binder的驱动实现,Native层和Java层的复杂构架,是出于2方面考虑:Native层的构架是为了提供统一的接口,并把业务层和逻辑层分开

Java层的构架是为应用层提供统一的接口,把内部实现封装起来,隔开了底层实现和上层应用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值