我们已经知道android的系统服务分为本地系统服务和java系统服务,android framework层即包含了本地系统服务和java系统服务,而本地系统服务是c++编写的服务,java系统服务是一些平台服务和硬件服务并采用java语言编写。本篇文章侧重点在分析android本地系统服务的运行机制及简单举例。

一、本地系统服务定义 

android本地系统服务详解_第1张图片

android中的本地系统服务采用c++编写,并且运行在libraries层,以android4.4版本的代码为例,本地系统服务主要有AudioFlinger,MediaPlayerService,CameraService,AudioPolicyService,这四个服务是运行在mediaserver守护进程中,在  mediaserver进程的main函数中,初始化这些服务的实例,代码如下:

int main(){        ...        sp proc(ProcessState::self());        sp sm = defaultServiceManager();        ALOGI("ServiceManager: %p", sm.get());        AudioFlinger::instantiate();        MediaPlayerService::instantiate();        CameraService::instantiate();        AudioPolicyService::instantiate();        registerExtensions();        ProcessState::self()->startThreadPool();        IPCThreadState::self()->joinThreadPool();        ...}

上面代码在初始化服务过程中,先创建本地系统服务,然后通过IBinder机制将服务注册到servicemanager进程中,这样其他的进程就可以通过IBinder方式与本地系统服务建立联系了。

但是这里我会想到一个问题,google为什么要设计这么一层本地系统服务框架呢,因为我们知道java层系统服务框架完全可以实现 本地系统服务框架对应的功能,java层服务只需要通过jni方式调用具体底层驱动代码,原因很可能是解决效率问题,像audio,camera,mediaplayer这些硬件具有的很多功能,这些功能的业务逻辑放到c++层效率高于放到java层。

二、本地系统服务运行机制 

  • 类的结构

要想了解本地系统服务的整个运行原理,首先得要知道框架的结构,具体点就是各个接口类以及各自的继承关系,下图就是本地系统服务框架的类或接口的继承关系:

android本地系统服务详解_第2张图片

 IBinder是android Binder的抽象,它提供两个子类BBinder和BpBinder;BBinder类负责接收RPC代码与数据,并在Binder Driver内部生成Binder节点。BpBinder类保存着目标服务的Handle信息,用于Binder Driver查找服务管理进程的Binder节点。

IInterface类提供类型变换功能,将服务或服务代理类转换为IBinder类型,实际的类型转换是由BnInterface、BpInterface两个类完成,BnInterface将服务类转换成IBinder类型,而BpInterface则将服务代理类转换成IBinder类型。在通过Binder Driver传递Binder对象时,必须进行类型转换,比如在向系统注册服务时,需要先将服务类型转换成IBinder,再将其传递给ServiceManager。

ProcessState类用来管理Binder Driver,IPCThreadState类用来支持服务客户端,Service Server与Binder Driver间的Binder IPC通信

Parcel在服务于服务代理间进行Binder IPC时,Parcel类负责保存IPC数据。Parcel 类可以处理的数据有C语言的基本数据结构、基本数据结构数组、Binder对象、文件描述符等。

  • AudioFlinger服务的类图

android本地系统服务详解_第3张图片

 AudioFlinger服务由IAudioFlinger服务接口、BnAudioFlinger服务Stub、AudioFlinger服务、BpAudioFlinger服务代理构成,上图左边是构成服务的各个类,右边是构成服务代理的各个类.

IInterface.h -->IInterface,BpInterface,BnInterface

IBinder.h-->IBinder

Binder.h-->BBinder,BpRefBase,

BpBinder.h-->BpBinder

IAudioFlinger.h-->IAudioFlinger,BnAudioFlinger

IAudioFlinger.cpp-->BpAudioFlinger

AudioFlinger.h-->AudioFlinger,

  • 服务接口

服务函数在服务接口中声明,并分别在服务和服务代理中实现,例如在IAudioFlinger服务接口中有一个setMasterVolume()服务函数的声明,该服务函数分别在AudioFlinger服务和BpAudioFlinger服务代理中实现。在服务接口中还存在一些函数,这些函数能够把服务接口转换成IBinder类型,或者把IBinder类型转换成服务接口。IAudioFligner接口如下所示:

class IAudioFlinger : public IInterface{public:    DECLARE_META_INTERFACE(AudioFlinger);    // or-able bits shared by createTrack and openRecord, but not all combinations make sense    enum {        TRACK_DEFAULT = 0,  // client requests a default AudioTrack        TRACK_TIMED   = 1,  // client requests a TimedAudioTrack        TRACK_FAST    = 2,  // client requests a fast AudioTrack or AudioRecord        TRACK_OFFLOAD = 4,  // client requests offload to hw codec    };    typedef uint32_t track_flags_t;    virtual     status_t    setMasterVolume(float value) = 0;    ...}

上面的宏DECLARE_META_INTERFACE(AudioFlinger)定义是在IInterface.h头文件中,如下图所示,也就是声明了descriptor,转换成IInterface接口函数asInterface,以及getInterfaceDescriptor()。

#define DECLARE_META_INTERFACE(INTERFACE)                               \    static const android::String16 descriptor;                          \    static android::sp asInterface(                       \            const android::sp& obj);                  \    virtual const android::String16& getInterfaceDescriptor() const;    \    I##INTERFACE();                                                     \    virtual ~I##INTERFACE();  

其他IInterface.h,BnInterface.h,BpInterface.h这几个头文件的声明,大家可以自己去研究一下 

  • 服务

setMasterVolume函数具体实现实在AudioFlinger类中,AudioFlinger类就是所有服务函数的实现类,继承自IAudioFlinger

class AudioFlinger :    public BinderService,    public BnAudioFlinger{    friend class BinderService;   // for AudioFlinger()public:    static const char* getServiceName() ANDROID_API { return "media.audio_flinger"; }    virtual     status_t    dump(int fd, const Vector& args);    virtual     status_t    setMasterVolume(float value);    ...}

BnAudioFlinger这个类我们叫做服务stub类,负责onTransact具体内容,android源码中,BnAudioFlinger类被定义在IAudioFlinger.h头文件中,而BnInterface类被定义在IInterface.h头文件中,

class BnAudioFlinger : public BnInterface{public:    virtual status_t    onTransact( uint32_t code,                                    const Parcel& data,                                    Parcel* reply,                                    uint32_t flags = 0);};

 AudioFlinger服务类图如下:

android本地系统服务详解_第4张图片

  •  服务代理

Audio系统中的服务代理类是BpAudioFlinger,服务客户端通过BpAudioFlinger来使用具体服务,具体的setMasterMute函数如下:

virtual status_t setMasterVolume(float value)    {        Parcel data, reply;        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());        data.writeFloat(value);        remote()->transact(SET_MASTER_VOLUME, data, &reply);        return reply.readInt32();    }

服务代理BpAudioFlinger在初始化构造函数时,将BpBinder作为参数传入,而这个BpBinder如何获取后面再讲,当调用setMasterVolume函数时,首先会去调用remote()->transact方法,而remote方法返回的是IBinder对象,这里就是代理BpBinder,这样就会进入到BpBinder类中的transact方法,之后调用IPCThreadState的transact方法与Binder Driver去交互

  • Binder IPC处理

android本地系统服务详解_第5张图片

1、调用BpAudioFlinger的setMasterVolume函数,将SET_MASTER_VOLUME作为第一个参数传入BpBinder的transact函数中,而后将android.media.IAudioFlinger字符串和音量值保存到Parcel实例data中,再讲器作为第二个参数传入函数中

2、在BpAudioFlinger的setMasterVolume函数中调用BpBinder的transact函数时,目的地信息将被作为首个参数传入IPCThreadState的transact函数中,并且Parcel实例将作为第二个参数传入函数中

3、在BpBinder的transact函数中,调用IPCThreadstate的transact函数时将Binder协议与之前传递过来的数据作为参数传入writeTransactionData函数中,该函数将创建binder_transaction_data结构体,以供Binder Driver使用,并且将接收到的RPC代码,RPC数据以及目的地信息保存到结构体中。

总的流程为:

客户端调用BpAudioFlinger transact(),此方法中调用remote()-->transact,remote()其实返回的就是BpBinder,这里就是调用了BpBinder中的transact,之后此方法中会调用IPCThreadState中的transact将数据封装好之后调用writeTransactionData和waitForResponse,然后再调用talkwithdriver函数与Linux中的Binder设备通信,接着IPCThreadState在waitForResponse函数中接收到宏为BR_TRANSACTION(BC_TRANSACTION为向Binder发送的消息码)的回复消息,之后调用BBinder的transact函数,transact函数会默认调用onTransact函数,由于BnAudioFlinger实现了onTransact,因此BnAudioFlinger会被执行onTransact,最后会调用具体AudioFinger里面的服务函数。

ps:

1、BpBinder通过参数handle来向指定的服务发消息,这个handle就是服务注册在Binder中的标识号,Binder通过这个handle找到对应的服务

2、mediaserver进程在初始化时候就会去默认开启线程startThreadPool()和joinThreadPool,目的就是为了监听Binder设备返回的消息

三、编写本地系统服务

以打印helloworld为例

主要需要编写的源码如下:

1、服务接口IHelloWorld.cpp IHelloWorld.h

2、服务类HelloWorldService.cpp  HelloWorldService.h

3、服务Stub类BnHelloWorldService.cpp BnHelloWorldService.h

4、服务代理类BpHelloWorldService.cpp BpHelloWorldService.h

5、编写运行服务的服务守护进程main_helloworldservice.cpp

6、编写用于编译HelloWorld服务的Android.mk

7、编写用于编译运行服务进程及客户端的Android.mk

具体代码将在下一篇文章展示,

总结,本文主要讲解了本地系统服务的框架的结构以及从代理端开始到服务端接受的整个流程,下一篇文章将着重讲解Service Manager管理服务的机制

更多相关文章

  1. C语言函数以及函数的使用
  2. 让Android 变身回一台真正的Linux系统吧!!!
  3. Android 电池管理系统
  4. 最封闭的开源系统:话说 Android 的八宗罪
  5. Android系统信息和安全机制

随机推荐

  1. Android(安卓)文件的上传
  2. Android(安卓)- 4种基本布局
  3. 我的android 第7天 - 控件美化 和 编码性
  4. Android动画之RotateAnimation使用
  5. ERROR: Unknown command 'crunch'
  6. android反编译工具(ApkDec-Release-0.1)-正
  7. Android详细教程 - 基础篇完成了
  8. android Shape使用
  9. android webkit学习笔记1---url的load过
  10. android软键盘弹出,会把原来的界面挤上去