Android框架揭秘-Android Service Framework

Android Service Framework是一系列类的集合,使用它可以快速开发出可靠优良的Android平台上的各种服务。


使用Service Framework开发时, 把主要精力集中在核心功能上即可, 服务注册,服务Binder IPC等功能都由系统提供。


Service Framework分为C++语言编写的本地服务框架及JAVA编写的JAVA服务框架。

图, 服务框架


应用程序框架中的Activity Manager等Java系统服务都是使用Java服务框架实现的, Surface Flinger等本地系统服务都是使用本地服务框架实现的。


Android Service Framework提供的四种主要功能

服务接口,  服务生成, Binder IPC处理, 服务管理


1. 服务框架的构成

1.1 各层构成元素的配置



1.2各层构成元素间的相互作用

<1>位于服务层中的服务接口使服务使用者与服务使用同一的接口进行相互作用。

<2>处于RPC层的服务代理与服务Stub支持Binder RPC操作。

      服务代理将函数调用信息转化为RPC代码与数据, 服务Stub分析服务代理发送过来的RPC代码与数据, 而后调用服务Stub函数。

<3>位于IPC层的BpBinder类与BBinder支持Binder IPC操作。

      当调用BpBinder的tansact函数时, BBinder的tansact函数即被调用, 同时传递RPC代码与数据。

      IPC层还提供了IPCThreadState类,IPCThreadState使用Binder协议命令与Binder Driver通信。


2. 运行机制


Audio Flinger类图



2.1 服务接口

服务函数中服务接口中声明, 并分别在服务于服务代理中实现。

例如Audio Flinger的 服务接口IAudioFlinger, 主要特征如下:

<1>IAudioFlinger类继承自IInterface类

<2>类的内部使用DECLARE_META_INTERFACE宏

<3>声明IAudioFlinger的setMasterVolume成员函数

IAudioFlinger服务接口继承自IInterface类

IAudioFlinger服务接口中有一个setMasterVolume服务函数的声明, 分别在AudioFlinger和BpAudioFlinger服务代理中实现。

IInterface类中, asBinder函数用来将服务接口类型转换为IBinder类型, asInterface函数则用来将IBinder类型转换为服务接口类型。


在向Context Manager注册服务时,AudioFlinger通过IInterface类的asBinder先把服务转换成IBinder类型, 再传递给Binder Driver。


BnInterface与BpInterface两个类中的onAsBinder成员函数代码不同。

BnInterface继承了BBinder类, BBinder类又继承了IBinder类,所以BnInterface是IBinder的子类。

BnInterface类的onAsBinder函数的返回值为IBinder类型, 即返回类自身的地址。


BpInterface类的onAsBinder函数将调用remote函数, 调用remote函数又会引起BpRefBase类的remote函数调用, 返回mRemote变量。

mRemote变量是IBinder类型的。


DECLARE_META_INTERFACE宏的作用

宏预处理, 在代码中有descriptor数据成员, asInterface, getInterfaceDescriptor成员函数的声明。

其中asInterface是类型变换函数, 它接收一个IBinder类型的参数, 将其转换成IAudioFlinger类型, 功能与IInterface的asBinder函数正好相反。

若传递过来的参数类型是BpBinder, 则IBinder的queryLocallInterface函数将被调用,将创建BpAudioFlinger实例。

若参数是BBinder类型, 则BnInterface的queryLocallInterface函数被调用,若参数值为IAudioFlinger接口的名称(android.media.IAudioFlinger),

则返回AudioFlinger服务的实例。

总之, asInterface函数由DECLARE_META_INTERFACE与IMPLEMENT_META_INTERFACE宏生成,该函数接受IBinder类型的参数,

通过判断参数的具体类型(BBinder或者BpBinder),调用相应函数,返回IAudioFlinger类型的具体服务或者服务代理。即将IBinder类型转换为具体的

IAudioFlinger类型返回。


图   IAudioFlinger与IBinder类间进行类型转换的过程。


2.2 服务

服务函数中服务类中被实现,如setMasterVolume函数, 在AudioFlinger类中被具体实现。

AudioFlinger继承BnAudioFlinger, BnAudioFlinger负责分析Audio Flinger服务中的RPC代码, 并调用AudioFlinger类的相应服务的stub函数。

BnAudioFlinger类中仅声明了一个onTransact函数, 该函数的第一个参数接收RPC代码, 第二个参数接收RPC数据。


图, BnAudioFlinger的onTransact函数处理RPC代码

注册Audio Flinger服务

一个服务必须先将自身注册到Android系统中才能给用户提供服务。一般地,服务注册将在服务生成的同时进行,

调用AudioFlinger类的instantiate函数将会生成AudioFlinger实例,并通过Service Manager将其注册到系统中。


图,AudioFlinger注册代码。


2.3服务代理

服务代理函数用来传递Binder RPC所需要的RPC代码与数据, 这些函数具体在服务代理类中实现。

比如BpAudioFlinger服务代理的setMasterVolume函数会将SET_MASTER_VOLUME(RPC代码), 与音量值(RPC数据)发送到BpBinder中。

BpAudioFlinger服务代理类继承了IAudioFlinger类, 服务用户通过它来使用AudioFlinger服务。

BpAudioFlinger类重新定义了setMasterVolume函数, 并提供了将调用setMasterVolume函数相关的信息转换为RPC代码与数据的功能。

图, BpAudioFlinger类的继承关系图


如图所示, remote但是在RefBpBase类中被声明, 它返回IBinder类型的对象, 在服务代理端是BpBinder, 它将RPC代码, RPC数据,

以及服务Handle信息一并传递给IPCThreadState的transact函数。


图,服务代理中调用setMasterVolume函数的过程。


获取BpBinder对象的过程

BpBinder对象是以BpAudioFlinger构造函数的参数形式获取的。

首先AudioSystem通过ServiceManager的getService获取BpBinder对象,然后以参数的形式将BpBinder对象传递给BpAudioFlinger的构造函数。

依次调用父类BpInterface, RefBpBase的构造函数, 最后BpBinder对象被保存到RefBpBase的mRemote变量中。

图, 生成BpAudioFlinger类的过程


2.4 Binder IPC处理

 

ProcessState类 主要功能

<1>打开Binder Driver

<2>创建BpBinder类的实例

IPCThreadState类主要功能是负责传递Binder IPC数据。


3 本地服务管理

3.1 Service Manager概要

服务被注册到Context Manager的过程中, Binder Driver将生成Binder 节点, 该节点中包含服务连接信息。

并且Service Framework会议服务Handle值的形式引用Binder 节点。


服务用户若想访问服务, 必须首先从Context Manager中获取服务的Handle值, 以便连接到要使用的服务上。


Service Framework提供了用于处理Bindr RPC的服务代理,这些服务代理帮助服务用户使用Audio Flinger, Surface Flinger等各种服务提供的功能。

服务代理与服务间复杂的Binder RPC由底层的Service Framework完成, 在上层服务用户看来, 服务代理与服务就像同一进程, 如同在同一进程中使用服务一样。


Service Manager是Context Manager的服务代理。


3.2 Service Manager类

在Android启动过程中,System Server初始化并启动多种服务, 这些服务通过Service Manager与Context Manager进行Binder IPC调用,完成服务的注册。

JAVA系统服务通过JAVA层的Service Manager注册服务,  本地系统服务通过C/C++层的Service Manager注册服务。

JAVA层的Service Manager通过JNI 与 C/C++层的Service Manager连接在一起 ,  C/C++层的Service Manager通过Binder Driver与Context Manager进行Binder RPC。


 C/C++层的Service Manager

图, Service Manager的类层次结构以及Binder IPC过程。


图, Android基本的Binder RPC与Service Manager的Binder RPC。


3.3 Service Manager的运行

3.3.1 Service Manager初始化

服务或服务用户在使用Service Manager注册或者检索服务之前, 需要先创建ProcessState实例,

该实例生成的同时, Binder Driver即被打开,并且相关信息被保存在ProcessState中。


图, 初始化生成ProcessState及BpBinder实例。


创建的BpBinder对象拥有Context Manager的服务Handle值。由于Context Manager的服务Handle值为0, 所以直接生成BpBinder。

对于其他服务, 由于不知道这些服务的Handle值, 需要先从Context Manager获取服务信息后, 再生成BpBinder。


在通过Handle向特定服务发送Binder IPC数据时, 将会用到BpBinder, 并且通过ProcessState可以防止在同一进程里重复生成BpBinder对象。

因此当应用程序访问某个使用中的服务时, 不必创建新的BpBinder对象, 直接使用已有的BpBinder对象即可。


接下来生成BpServiceManager, 拥有指向BpBinder的指针, 而BpBinder则拥有Context Manager的服务Handle。


图,生成BpServiceManager实例对象


至此, BpServiceManager与ContextManager之间就可以进行Binder RPC操作了。


服务Handle与BpBinder以及BpServiceManager的连接就像插积木一样, 在连接其他服务与服务代理时也采用了这样的结构形式。


图, 生成BpServiceManager的实例


3.3.2 服务注册

为了让其他进程使用服务自身提供的功能, 服务必须先注册到Context Manager中。

下面分析Audio Flinger的instantiate函数来学习服务注册过程。

<1>调用defaultServiceManager函数, 获取BpServiceManager的实例指针, 而后调用BpServiceManager的addService函数,

      调用addService函数时, 首先生成Binder RPC数据, Binder RPC数据用于发送到Context Manager以注册Audio Flinger服务,

      而后引用BpBinder(该对象持有Context Manager的服务Handle), 通过Binder Driver传递给Context Manager。    

<2>下面分析BpServiceManager的addService函数。

图, addService函数

addService函数按照(a)(b)(c)顺序保存并生成要发送的RPC数据, 然后调用remote函数, 返回持有Context Manager的BpBinder对象。

再通过BpBinder的tansact函数, 传递生成的Binder RPC代码(ADD_SERVICE_TRANSACTION)与 数据

(a)调用IServiceManager的getInterfaceDescriptor函数,返回Service Manager的名称(android.os.IServiceManager),

(b)调用Parcel的writeString16函数, 将AudioFlinger的服务名称(media.audio_flinger)保存到data中。

(c)调用Parcel的writeStrongBinder函数, 向data中保存表示Audio Flinger对象的flat_binder_object数据结构。

图,writeStrongBinder函数

flatten_binder函数带有三个参数, 分别是ProcessState对象, AudioFlinger对象(BBinder), 以及保存Binder RPC数据的data对象(parcel)


准备好数据之后, 继续执行addService函数, 调用mRemote.transact函数, 实际调用BpBinder的transact函数,同时把上面生成的

Binder RPC代码与BinderRPC数据作为参数传入函数中, 以供生成Binder IPC数据。


<3>BpBinder的transact函数将调用IPCThreadState的tansact函数, 并将上面生成的RPC数据原封不动的传递给IPCThreadState的transact函数。

除此之外, BpBinder的transact函数还传递给IPCThreadState的transact函数一个自身保存的Handle值。

在IPCThreadState的transact函数中调用writeTransactionData创建binder_transaction_data数据结构,该数据结构与Binder协议一起构成了Binder IPC数据。

之后调用waitForResponse函数, 将Binder IPC数据传递给Binder Driver。


<4>waitForResponse函数执行与Binder Driver间的Binder IPC数据的收发操作。

在waitForResponse函数中调用talkWithDriver, 将IPC数据传递给Binder Driver, 并保存来自Binder Driver的Binder IPC应答数据。


Context Manager执行注册后, 生成应答数据, 即addService的函数的返回值, 当服务注册完成后, Binder Driver将为Audio Flinger生成新的Binder 节点。

而后Context Manager将Audio Flinger添加到自身的服务目录中。


小结

在Service Framework中, 传递给Binder Driver的Binder IPC数据包含Binder 协议与binder_transaction_data两部分。

要传递给Context Manager的Binder RPC数据保存在位于发送端进程用户内存的data(parcel)中, Binder Driver将其拷贝到接收端进程的Binder mmap区域中。

并且在Service Framework中, 从Binder Driver接收到的Binder IPC数据也由Binder协议与binder_transaction_data两部分构成,

Context Manager的Binder RPC数据被保存到接收端进程的Binder mmap区域中, reply(回复数据 parcel)将引用它。


图,完成服务注册及Binder RPC, IPC数据的处理过程。



3.3.3 获取服务信息

服务用户若想访问某个服务, 必须先从Context Manager获取指定服务的信息。

图AudioSystem的get_audio_flinger函数


<1>调用defaultServiceManager函数, 获取BpServiceManager实例对象的指针。

<2>调用Service Manager的getService函数, 获取持有Audio Flinger服务Handle的BpBinder对象。

      getService函数的参数是Audio Flinger服务的名称,

      getService函数根据传递进来的参数, 生成要传递给Context Manager的Binder RPC数据,用于获取Audio Flinger的服务信息。

      并引用持有Context Manager服务Handle的BpBinder对象, 通过Binder Driver将Binder RPC数据传送至Context Manager中。

<3>BpServiceManager的getService函数将循环调用checkService函数查询Service,防止一次查询失败,

      checkService中会生成RPC数据, 之后调用remote->transact函数,即BpBinder的transact函数,传递生成的Binder RPC数据。

      BpBinder的transact函数继续调用IPCThreadState的transact函数, 并且IPCThreadState的transact函数的第一个参数是BpBinder传入的

      其自身保存的ContextManager的Handler值, 然后调用IPCThreadState的waitForResponse函数, 将生成的IPC数据, 传递给Binder Driver。

      当获取服务信息后, 将从Binder Driver收到Binder IPC数据(IPCThreadState的mIn(收信parcel)),

      其中收到的IPC数据中的binder_transaction_data数据结构中的buffer与offsets分别指向接收的Binder RPC数据中Binder mmap区域中的位置。

      data_size表示buffer的有效数据大小, offsets_size表示flat_binder_object数据结构的大小, 该数据结构保存在offsets所指的位置上。

      与注册服务时不同, offset_size为4, 表示仅有一个flat_binder_object数据结构。该数据结构中包含着指定服务的Handle。

     

<4>接下来以从Binder Driver接收到的Context Manager的Binder RPC数据为基础, 调用Parcel的readStrongBinder函数, 创建BpBinder对象,

      该对象持有Audio Flinger的服务Handle。readStrongBinder函数又调用了unflatten_binder函数, 在这个函数中, flat->type值为BINDER_TYPE_HANDLE时,

      继续调用ProcessState的getStrongProxyForHandle函数。并将相关服务的Handle作为参数传入函数中, 创建出BpBinder对象。

      并且ProcessState保证不会在同一进程中生成多个重复的BpBinder对象。接下来生成BpAudioFlinger实例对象,该对象能够引用BpBinder实例的指针,

      并且BpBinder实例持有AudioFlinger的服务Handle。


<3>调用interface_cast,将上面获取的BpBinder对象, 转换成用作Audio Flinger服务代理的BpAudioFlinger对象。

      interface_cast模板中的INTERFACE会被IAudioFlinger替换, 所以最终调用的是IAudioFlinger的asInterFace函数。

      所以最终调用的是IAudioFlinger的asInterface函数。调用BpAudioFlinger构造函数, 创建了BpAudioFlinger对象,

      该构造函数的参数是前面创建的BpBinder实例对象的指针。

      这样AudioFlinger的服务代理BpAudioFlinger对象就创建好了。


4. 编写本地服务

<1>编写HelloWorld服务接口, IHelloWorldService类继承IInterface类

定义DECLARE_META_INTERFACE宏

定义helloWorld服务函数


<2>编写HelloWorld服务

BnHelloWorldService服务Stub

BnHelloWorldService服务Stub类用来处理从服务用户接收到的RPC代码, 它继承了BnInterface类,

并模板继承了IHelloWorldService类, 并且重新定义了BBinder类的onTransact方法。

当传入onTransact方法的RPC代码为HW_HELLOWORLD时, 调用helloWorld方法。


编写HelloWorldService服务类, 继承BnHelloWorldService类。

在HelloWorldService类中首先声明了instantiate函数, 该函数用来生成HelloWorld服务。

在instantiate函数内部, 调用ServiceManager的addService方法, 中生成HelloWorld服务的同时将其注册到系统中。

然后编写helloWorld方法, 使用printf函数将接收到的字符输出到标准设备中。


<3>编写HelloWorld服务代理

在使用HelloWorld服务的过程中, 需要使用BpHelloWorldService服务代理。

BpHelloWorldService继承自BpInterface, 并模板继承了IHelloWorldService

在BpHelloWorldService中, 重写helloWorld方法。

首先将服务接口名称保存到发送数据中,

然后将要调用服务函数的参数保存到发送数据中,

再调用BpBinder类的transact方法, 传入将要调用的函数的RPC代码及数据。

最后等待调用结果。完成服务代理的编写。


<4>运行HelloWorldService服务

服务运行在Service Server进程, 首先生成Service Server进程, 运行HelloWordService服务。

在main_helloworldservice.cpp 的main函数中,

首先调用HelloWorldService的instantiate函数, 创建HelloWorldService的实例对象, 并将HelloWorld服务注册到系统中。

而后调用ProcessState的startThreadPool方法创建线程池, 再调用IPCThreadState的joinThreadPool方法, 中线程池中等待接收服务用户请求。


<5>使用HelloWorldService服务

首先调用defaultServiceManager函数, 获取Service Manager后, 再调用Service Manager的getService函数, 获取指向HelloWorld服务的BpBinder对象。

在获取BpBinder对象后, 使用interface_cast宏, 将其转换成BpHelloWorldService服务代理。

最后调用服务代理的helloWorld函数。



































































































































































你可能感兴趣的:(Android框架揭秘-Android Service Framework)