Android框架揭秘-JAVA服务框架

JAVA服务框架是一系列类的集合, 这些类用于支持开发JAVA系统服务, 这些服务运行在基于JAVA的应用程序框架中。


JAVA服务框架通过JNI与本地框架进行交互, 这样可以重用一些由C/C++编写的代码。


JAVA服务框架与本地服务框架的不同有如下两点:

<1>服务生成:

在JAVA服务框架中, 开发JAVA服务的方法有两种。

第一种是集成Binder类进行开发,这种方式常常用于开发可以实现精确控制的服务中,开发JAVA系统服务时常用这种方式。

Android提供了AIDL语言及编译器,使得编写JAVA系统服务比编写本地系统服务要容易得多。

第二种是继承Service类进行开发, 常常用来开发一些周期执行某些任务的后台服务。

<2>Binder IPC处理:

为了支持Binder IPC, JAVA服务框架将通过JNI使用本地服务框架中的相应组成部分。


JAVA服务管理

<1>与本地系统服务一样, JAVA系统服务注册到Context Manager中, 而后通过Service Manager使用服务。

<2>JAVA应用程序服务由Activity Manager Service而非Context Manager进行管理。


1. JAVA服务框架的层次结构

JAVA服务框架由服务层, RPC层, IPC层三个层构成。

图 JAVA服务框架构成

<1>服务层

与本地服务不同, 需要自己实现FooManager类, 因为SDK包中并不包含ServiceManager类, 应用程序服务使用ServiceManager类来注册或检索服务。

为了让应用程序开发者能够使用系统服务,服务开发者必须将包装类包含到SDK中。

例如, 为了让应用程序开发者能够使用FooService, 系统服务开发者就要编写FooManager包装类, 添加使用ServiceManager获取FooService的功能。

并将其编入SDK中。然后应用程序开发者就可以通过包含在SDK中的FooManager类来使用FooService系统服务了。


图  FooManager包装类的作用


<2>RPC层

JAVA服务框架使用Android平台中的AIDL语言与编译器自动生成服务代理和服务Stub。

首先编写IFooService.aidl文件, 在其中定义服务接口。

然后编译器会自动生成IFooService.Stub与IFooService.Stub.Proxy两个类。


<3>IPC层

使用JAVA服务框架开发的服务与服务代理通过Binder IPC进行交互

为了支持Binder IPC, 本地服务框架提供了BpBinder和BBinder两个类, JAVA服务框架则提供了BinderProxy与Binder两个类。

JAVA服务框架也可以通过JNI使用本地服务框架的Binder IPC,即BidnerProxy与Binder通过JNI使用本地服务框架的BpBinder与BBinder类的功能。


图 BinderProxy与Binder的Binder IPC


2. JAVA服务框架中各个类间的相互作用

首先先看一下客户端

服务客户端与本地服务框架相比, JAVA服务框架在服务客户端中多了两个调用过程

分别是服务用户调用FooManager的foo方法  与BinderProxy的transact方法通过JNI本地函数android_os_BinderProxy_transact调用BpBinder的transact函数的过程。

当BpBinder的transact函数调用执行后, 接下来的过程就与在本地服务框架中的内容一样了。


图客户端内部相互作用


接着再看一下Java系统服务所在的Service Server

在Java服务框架中多了BBinder的transact函数使用JavaBBinder本地服务Stub调用Binder的exacTransact方法的过程。


图Service Server内部相互作用


下面分析一下FooService服务注册到系统以及使用的过程。


图使用FooService时各个部分间的相互作用


<1> 请求服务注册:在向系统注册服务时, 本地服务框架将通过本地服务管理器BpServiceManager来处理服务注册,

而Java服务框架则使用JAVA服务管理器ServiceManager来处理服务注册。

FooService服务在向系统注册时将调用ServiceManager的addService方法, 在ServiceManager内部存在BinderProxy对象,

它通过JIN与持有ContextManager指针的BpBinder连接在一起。


<2>注册服务:ServiceManagerProxy服务代理将调用addService方法的信息转换为RPC数据。

Binder RPC数据被存储在Parcel(Java)类中传递给BinderProxy,而后通过JNI传递给BpBinder,最后通过Binder IPC传递给Context Manager,

如此, FooService服务即被注册到系统之中。


<3>请求服务检索:在使用FooService服务时, 本地服务用户将通过BpServiceManager来检索服务,

而JAVA服务则会调用SDK中的getSystemService方法来检索服务。


<4>服务检索:调用getSystemService方法将引起ServiceManager的getService方法的调用, 在系统中检索FooService服务。

若检索到FooService, 则会向服务用户返回FooManager对象, 该对象可以引用IFooService.Stub.Proxy服务代理。


<5>调用foo服务代理方法:服务用户调用FooManager的foo方法,而后IFooService.Stub.Proxy将foo方法的调用信息转换为RPC数据,

通过BinderProxy传递给BpBinder。


<6>执行foo服务Stub方法:BBinder从Binder Driver接收Binder RPC数据后, 通过JavaBBinder调用Binder的execTransact方法,

而后RPC数据传递给IFooService.Stub服务Stub的onTransact方法, 经过分析后, 调用FooService的foo服务Stub方法。


Java服务框架最重要的特征就是通过JNI复用本地服务框架提供的功能。

使用Java服务框架实现的系统服务被包含在应用程序中, 其中一部分可以使用在SDK中, 在开发应用程序时,

应当额外提供服务管理器(Service Manager)的包装类, 以便使用系统服务。

Android系统也提供了一种接口描述语言AIDL用来自通为服务接口生成服务Stub与代理。


3. 运行机制

下面通过源码分析Java服务框架使用本地服务框架的运作机制。

<1>Java服务框架初始化

在app_process进程启动时, AndroidRuntime类就会调用startReg函数, 将JNI函数加载到Dalvik虚拟机中。

使用register_android_os_Binder函数注册的JNI本地函数就是与JAVA服务框架有关联的本地函数。


图register_android_os_Binder函数

<2>Binder类

注册完JNI函数后, Binder类的本地方法将被映射到JNI本地函数中。

图Binder类的本地方法与JNI本地函数的映射关系。


<3>生成Binder对象

为了进行Binder IPC, 使用BBinder提供的功能, Binder类中生成Binder对象的同时将生成BBinder对象。

Binder类中构造方法中调用init本地方法, init本地方法与JNI的android_os_Binder_init函数映射在一起。

android_os_Binder_init函数首先生成JavaBBinderHolder类的对象, 而后调用名称为SetIntField的JNI函数,

将刚创建的JavaBBinderHolder对象的地址保存到Binder的mObject变量中。


图 android_os_Binder_init函数


<4>生成JavaBBinder对象

在创建Binder对象的同时会生成BBinder对象,JavaBBinder是对象是在JavaBBinderHolder的get函数中创建的,

在get函数中直接调用JavaBBinder类的构造函数, 生成了JavaBBinder对象。

JavaBBinder类继承并实现了父类BBinder, 创建JavaBBinder对象时也会生成BBinder对象。


图  JavaBBinderHolder的get函数


下面简单描述了生成BBinder对象的过程


图 生成BBinder对象


<5>Binder类与JavaBBinder服务Stub的相互作用

BBinder的transact函数将引起对JavaBBinder的onTransact函数的调用。除了基本的Binder RPC函数外, 若想扩展BBinder的功能,

需要在继承BBinder的服务Stub类中重新定义onTransact方法。

JavaBBinder服务Stub类继承了BBinder类, 重定义了onTransact方法,在其中调用了Binder的execTransact方法。


4. BinderProxy

<1>BinderProxy类的JNI设定

如同Binder类, 使用BinderProxy类之前, 也需要先将BinderProxy类本地方法对应的JNI本地函数注册到虚拟机中。

调用int_register_android_os_BinderProxy函数时, BinderProxy类的本地方法与JNI本地函数映射在一起。


<2>生成BinderProxy对象

BinderProxy类中执行Binder IPC时需要使用本地服务框架的BpBinder功能, 因此在创建BinderProxy对象时将同时生成BpBinder对象。

前面讲过BpBinder对象是由Parcel(c++) 的readStrongBinder函数创建的。


因此, BinderProxy对象是在调用Parcel(java)的readStrongBinder方法时生成的。当调用Parcel(java)的readStrongBinder方法时,

Parcel(c++)的readStrongBinder函数以及javaObjectForBinder函数将一次被调用, 从而生成BpBinder与BinderProxy对象。

如下图


图 生成BinderProxy对象-调用Parcel(java)的readStrongBinder方法


<3>BinderProxy类与 BpBinder类的相互作用

由于BinderProxy的transact本地方法与JNI本地函数android_os_BinderProxy_transact映射在一起

所以,当调用BinderProxy的transact本地方法时, android_os_BinderProxy_transact函数即会被调用。

在android_os_BinderProxy_transact函数中,获取到mObejct变量中的BpBinder对象地址, 而后调用transact函数。


5. Parcel

在BinderIPC期间, Parcel(java)类用来保存由发送端向接收端发送的数据。

特别地, Parcel(java)内部缓冲区中持有IBinder对象的引用, 并且在进程间移动时需要维持这个引用。

<1>Parcel(java)类的JNI设定

Parcel(java)类的本地方法通过JNI与Parcel(c++)类中的同名的本地成员函数映射在一起,

调用int_register_android_os_BinderProxy函数时, Parcel(java)类的部分信息就被保存到gParcelOffsets全局变量中,

并且将Parcel(java)类的本地方法与JNI本地函数映射在一起。


<2>生成Parcel(java)对象

生成Parcel(java)对象的过程与Binder和BinderProxy略有不同,

首先看Parcel(java)的构造方法, 它有一个私有方法, 外部代码不能使用new Parcel语句创建Parcel(java)的实例对象。


但是Parcel(java)类提供了一个名称为obtain方法, 使用该方法即可创建Parcel(java)类的实例对象。

obtain方法调用Parcel(java)的私有构造方法, 构造方法将调用init本地方法, 从而引起对本地函数

android_os_Parcel_init的调用,本地函数创建了Parcel(c++)类的实例对象。


<3>Parcel(java)类与Parcel(c++)类间的相互作用

一般地, Parcel(java)类用来在服务代理中保存Binder RPC数据,

例如,FooService服务用户在调用IFooService.Stub.Proxy服务代理的foo代理方法时, 就会调用Parcel(java)类的

obtain函数创建出Parcel(java)对象, 并将其传入到transact方法中。


图 Parcel(java)类与Parcel(c++)类的相互作用


6 JAVA系统服务的实现

下面以闹钟服务为基础, 分析系统服务的结构

<1>闹钟服务分析

下图显示了实现闹钟服务的类图结构。


图 实现闹钟服务的类图


<1.1>闹钟服务的实现方式

在编写本地系统服务时, 开发者必须亲自实现服务接口, 服务代理, 服务Stub, 服务。

而在编写Java系统服务时,开发者可以使用AIDL语言自动生成他们。

首先编写AIDL接口文件, IAlarmManager.aidl,系统会自动编译生成IAlarmManager.Stub类。

应该编写服务类继承Stub类,重新定义IAlarmManager.Stub类Binder类的onTransact方法, 并添加系统Binder RPC功能。

AlarmManagerService的服务Stub类重定义了onTransact方法, 并且实现了与IAlarmManager接口中5个方法相关的代码。


<1.2>使用闹钟服务(AlarmManagerService)

应用程序开发者若要使用系统服务, 需要调用SDK中的getSystemService方法。

首先调用ServiceManager的getService方法, 请求AlarmManagerService服务,返回一个指向AlarmManagerService服务的BinderProxy对象。

调用IAlarmManager.Stub服务Stub的asInterface方法,获取IAlarmManager.Stub.Proxy服务代理类的对象。

创建并返回AlarmManager对象。


调用getSystemService方法获取AlarmManager对象, 以Context的ALARM_SERVICE变量为参数, 通过强制类型转换, 获得AlarmManager对象。


注意: ServiceManager 在android.os包中, ServiceManager类被标记成@hide 

在SDK中没有对外开放,Context在android.app包中, 对外开放,

所以不能APP开发者不能使用ServiceManager获取系统服务。需要写AlarmManager包装类, 使APP开发者能够通过Context获取AlarmManager,

从而使用服务。


7. 编写HelloWorldService系统服务


图 HelloWorldService系统服务类图


首先编写HelloWorldService服务接口aidl文件,

然后系统自动生成HelloWorldService服务接口, 服务代理, 服务Stub

之后再实现HelloWorldService与HelloWorldManager类。


实现HelloWorldService服务

HelloWorldService服务实现类   HelloWorldService.java在com.android.app包中。

HelloWorldService要继承并实现服务IHelloWorld.Stub类(由编译器根据aidl文件自动生成)。


注册HelloWorldService服务

在SystemServer.java的ServerThread的run方法中注册HelloWorldService服务。

helloWorldService = new HelloWorldService(context);

ServiceManager.addService(Context.HELLO_SERVICE, helloWorldService);



使用HelloWorldService系统服务

编写HelloWorldManager包装类, 构造方法接收IHelloWorld.Stub.Proxy类的实例对象,

HelloWorldManager类的构造方法访问权限为default, 只有同一个包(android.app)中的类才能调用它。


获取HelloWorldManager

应用程序开发者可以通过ContextImpl的getSystemService方法来使用系统服务。

调用getSystemService方法接收一个字符串参数, 若字符串与HELLO_SERVICE变量中的字符串相同, 则调用getHelloWorldManager方法。

getHelloWorldManager方法向ServiceManager请求检索HelloWorldService服务, 若ServiceManager检索到HelloWorldService服务,

则返回一个指向它的BinderProxy对象。getHelloWorldManager方法将接收到的BinderProxy对象传递给HelloWorld.Stub服务Stub的asInterface方法。

生成IHelloWorld.Stub.Proxy服务代理对象。并将这个服务代理对象传递给HelloWorldManager构造方法, 生成HelloWorldManager对象,

并且其mService变量中保存着IHelloWorld.Stub.Proxy服务代理对象的引用。

最后返回HelloWorldManager对象。


为了使用HelloWorldService服务, 应用程序将调用ContextImpl的getSystemService方法, 把Context.HELLO_SERVICE传入方法中,

然后将返回值转换成HelloWorldService类型, 这样就可以使用HelloWorldService服务了。


8 Java Service Manager

Java系统服务于本地服务一样都是由Context Manager进行管理的, 通常使用Java服务框架编写的系统服务都是通过Java Service Manager注册到系统中的。

<1>Java Service Manager简介

Java Service Manager由服务层,RPC层, IPC层组成, IServiceManager服务接口与ServiceManager包装类位于服务层中,

它们由Service Manager用户使用。 ServiceManagerProxy服务代理位于RPC层, 它将方法的调用信息转换为Binder RPC数据。

Binder Proxy位于IPC层, 它通过JNI 与BpBinder类连接在一起。


















































































































你可能感兴趣的:(Android框架揭秘-JAVA服务框架)