Android Binder总结

摘要:
关于如何启动SystemManager并成为主管和活页夹,您可以参考以下信息:http://blog.csdn.net/luoshengyang/article/details/6621566让我们来看看MediaPlayer服务的UML,以获得全面的理解。这个客户端是MediaPlayer,它在frames/base/include/media/MediaPlayer中声明和实现。h和frames/base/media/libmedia/mediaplayer。cpp文件。BpMediaPlayerService的构造函数有一个参数impl,其类型为constsp<IBinder>&。根据上面的描述,这实际上是一个BpBinder对象。这样,要创建BpMediaPlayerService对象,首先必须有一个BpBinder对象。我们还来看看BpBinder类的构造函数,它有一个int32_ t类型的参数句柄。这个参数的含义是,请求远程接口MediaPlayerService的进程引用Binder实体MediaPlayerServices。

1. MediapplayerService 的启动,怎样在ServiceManager注冊的,不解说详细的细节

    ServiceManager 是整个系统的Service总管,其余的系统服务都是通过defaultServiceManager的远程接口来调用ServiceManager。Service获得ServiceManager的接口之后就会把自己加入到ServiceManager中,然后把自己启动起来,之后等待着Client端的请求连接。

     关于SystemManager怎样启动而且成为总管和Binder的知识能够參考:

               http://blog.csdn.net/luoshengyang/article/details/6621566


先看一下MediaPlayerService的UML,有个总体的了解。

Android Binder总结第1张


1) 首先MediaPlayerService 是从main_mediaservice.cpp main中进行实例化,所以MediaPlayerService也执行在system_service的进程中。

int main(int argc, char** argv)
{
    ProcessState> proc(ProcessState::self());
    ... ...
    MediaPlayerService::instantiate();
    ... ...
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
}

2) 在MediaPlayerService::instantiate()中主要做了两件事情,第一就是通过 ProcessState::self() 来初始化一个全局变量gProcess,在ProcessState中的mDriverFD会保存Binder设备的指针。第二个 主要工作就是调用ServiceManager把自己new一个出来然后加入到ServiceManger总管中。

sp<ProcessState> ProcessState::self()
{
    if (gProcess != NULL) return gProcess;
    
    AutoMutex _l(gProcessMutex);
    if (gProcess == NULL) gProcess = new ProcessState;
    return gProcess;
}
     addService的过程非常复杂,有兴趣的人能够拜读一下老罗的这篇文章:

          http://blog.csdn.net/luoshengyang/article/details/6629298

void MediaPlayerService::instantiate() {
    defaultServiceManager()->addService(
            String16("media.player"), new MediaPlayerService());
}


3)  在把自己增加到ServiceManager中之后,会运行下面两个函数,总要是用来通过调用talkWithDriver函数来和Binder驱动程序进行交互,实际上就是调用talkWithDriver来等待Client的请求,然后再调用executeCommand来处理请求,而在executeCommand函数中,终于会调用BBinder::transact来真正处理Client的请求

    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();


2. 怎样去调用MediaPlayerService 而且和service通信

 MediaPlayerService此时已经是一个Service了,如今就等着Client端去建立连接。这个Client就是MediaPlayer,它声明和实如今frameworks/base/include/media/mediaplayer.h和frameworks/base/media/libmedia/mediaplayer.cpp文件里。MediaPlayer继承于IMediaDeathNotifier类,这个类声明和实如今frameworks/base/include/media/IMediaDeathNotifier.h和frameworks/base/media/libmedia//IMediaDeathNotifier.cpp文件里,里面有一个静态成员函数getMeidaPlayerService,它通过IServiceManager::getService接口来获得MediaPlayerService的远程接口。

        在介绍IMediaDeathNotifier::getMeidaPlayerService函数之前,我们先了解一下这个函数的目标,实际上就是要获得一个称为BpMediaPlayerService对象的IMediaPlayerService接口。

     从之前那个类图能够看到,BpMediaPlayerService继承于BpInterface<IMediaPlayerService>类,即BpMediaPlayerService继承了IMediaPlayerService类和BpRefBase类,这两个类又分别继续了RefBase类。BpRefBase类有一个成员变量mRemote,它的类型为IBinder,实际是一个BpBinder对象。BpBinder类使用了IPCThreadState类来与Binder驱动程序进行交互,而IPCThreadState类有一个成员变量mProcess,它的类型为ProcessState,IPCThreadState类借助ProcessState类来打开Binder设备文件/dev/binder,因此,它能够和Binder驱动程序进行交互。

       BpMediaPlayerService的构造函数有一个參数impl,它的类型为const sp<IBinder>&,从上面的描写叙述中,这个实际上就是一个BpBinder对象。这样,要创建一个BpMediaPlayerService对象,首先就要有一个BpBinder对象。再来看BpBinder类的构造函数,它有一个參数handle,类型为int32_t,这个參数的意义就是请求MediaPlayerService这个远程接口的进程对MediaPlayerService这个Binder实体的引用了。因此,获取MediaPlayerService这个远程接口的本质问题就变为从Service Manager中获得MediaPlayerService的一个句柄了。

Android Binder总结第2张

我们就以create的过程作为一个样例:

1) MediaPlayer.getMediaPlayerService()

     MediaPlayer继承IMediaDeathNotifier,所以就是调用IMediaDeathNotifier.getMediaPlayerService(),这个函数的主要作用就是从SystemManager中获取"media.player" Service的IBinder,也就是获取一个BpMediaPlayerService,通过这个IBinder与服务端通信。


2) service->create(getpid(), this, mAudioSessionId)

    这个service实际上就是BpMediaPlayerService,所以就是调用BpMediaPlayerService的create,在这个函数中回去调用remote()->transact。

3) remote()->transact(CREATE, data, &reply)

     这个remote()返回的是一个BpBinder, 实际上就是BpBinder.transact,这个transact自己是不做什么事情的,主要是通过调用IPCThreadState->transact去完毕数据请求工作。

4) IPCThreadState::self()->transact

    在这个transact中主要通过waitForResponse和talkWithDriver去完毕与Binder设备的ioctl操作。当调用talkWithDriver之后,MediaPlayerService中的IPCThreadState就用监听到请求而且调用自己的executeCommand。

5) BnMediaPlayerService.onTransact()

    在executeCommand会依据command的类型去调用回调函数,这里就是调用BBinder.transact, 而BBinder.transact终于会调用BnMediaPlayer.onTransact去做详细的处理,调用create然后返回一个Mediaplayer的一个Ibinder的client。 


3.  以AMS为样例,看一下Java层的Service Binder是假设去使用。AMS怎样去拿到Client,Client怎样和Service通信

Android Binder总结第3张


Android Binder总结第4张

1) Instrumentation.execStartActivity()

    Activity里面有一个StartActivity函数回去调用Instrumentation.execStartActivity(), 而在execStartActivity()又会通过ActivityManagerNative.getDefault()去掉用startActivity


2) ActivityManagerProxy.transact()

   在ActivityManagerNative.getDefault()事实上返回的就是ActivityManagerProxy。在ActivityManagerProxy的startActivity会调用mRemote.transact,而mRemote事实上BinderProxy对象,所以等于直接调用BinderProxy的trasact函数。


3)Binder.exectransact()

    BinderProxy的trasact会去通过JNI的来完毕Binder的请求,最后由服务端的Binder的execTranaction去做函数响应。


4) ActivityManagerService.onTransact

   Biner.execTranaction使用ActivityManagerService.onTransact最为回调函数去运行,并将结果放在reply中。


UML图:

http://sdrv.ms/Q79iGk


免责声明:文章转载自《Android Binder总结》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇C# 标签打印示例 1(stm32f103学习总结)—ADC模数转换实验下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

smali 语言语法

Androidkiller 可以反编译Android的apk,生成一种.smali代码。(这理解好像不对) 网上找了一篇smali的语法手册,可以方便查找,文章名《Smali文件语法参考》 手册地址:http://blog.csdn.net/litton_van/article/details/7843490 网上有一篇smali的语法讲解(java与sm...

Golang源码探索(二) 协程的实现原理(转)

Golang最大的特色可以说是协程(goroutine)了, 协程让本来很复杂的异步编程变得简单, 让程序员不再需要面对回调地狱,虽然现在引入了协程的语言越来越多, 但go中的协程仍然是实现的是最彻底的.这篇文章将通过分析golang的源代码来讲解协程的实现原理. 这个系列分析的golang源代码是Google官方的实现的1.9.2版本, 不适用于其他版...

RPC(Remote Procedure Calls)远程过程调用

很长时间以来都没有怎么好好搞清楚RPC(即Remote Procedure Call,远程过程调用)和HTTP调用的区别,不都是写一个服务然后在客户端调用么?这里请允许我迷之一笑~Naive!本文简单地介绍一下两种形式的C/S架构,先说一下他们最本质的区别,就是RPC主要是基于TCP/IP协议的,而HTTP服务主要是基于HTTP协议的,我们都知道HTTP协...

Python面向对象之反射

一、补充 @classmethod 整个方法中没有用到对象命名空间中的名字,且用到了类的命名空间中的名字(普通方法和属性property除外) 类方法的默认参数:cls 调用这个发方法的类 类方法的调用方式:通过类名调用 通过类名调用的本质是方法 @statimethod 将一个普通函数放到类中来就给这个函数加一个@staticmethod装饰器 这个函...

VC++ 6.0中实现三叉切分窗口与多视图 [转]

一、引用   当用户需要同时对文当的不同部分进行编辑时,常常会用到切分窗口;这些窗口可以都是相同的视,或者一个窗口为列表视,而另一个为树型视图。应用程序框架有多种方式来表示多视图,切分窗口是其中的方式之一。   切分窗口分为动态切分窗口和静态切分窗口,它们都是由CsplitterWnd类(MFC类库)来实现的,在这两种表示方式中,创建同一视图类的对象是比较...

Boost库学习(3) 内存管理

preface: 1、传统C++内存管理中可能出现的问题:内存泄露、野指针、访问越界;相关解决方案:智能指针 std::auto_ptr,不能完全解决内存管理中出现的问题; 2、关于smart_ptr库的概述: 2.1、C++程序员通常采用RAII(资源获取即初始化)机制管理内存资源,在使用资源的类的构造函数中申请资源,最后在析构函数中释放资源;如果对象的...