现在的位置: 首页 > 综合 > 正文

android下Binder机制

2013年08月18日 ⁄ 综合 ⁄ 共 3673字 ⁄ 字号 评论关闭
以MediaService为例,这个是个后台服务,用来播放多媒体的。

int main(int argc, char** argv)

{

//FT,就这么简单??

//获得一个ProcessState实例

sp<ProcessState> proc(ProcessState::self());

//得到一个ServiceManager对象

    sp<IServiceManager> sm = defaultServiceManager();

    MediaPlayerService::instantiate();//初始化MediaPlayerService服务

    ProcessState::self()->startThreadPool();//看名字,启动Process的线程池?

    IPCThreadState::self()->joinThreadPool();//将自己加入到刚才的线程池?

}

首先明确几个关键问题:
1.android的一个程序(比如activity)的运行机制是这样的:
图形界面的client端,发送请求给服务对应的代理,代理再通过binder(一个驱动),和server端的service通信,service来执行动作。
2.每个service分两个面,service的bnXXX,代理端的bpXXX,bp和bn通过binder通信,bp一般都是把bpbinder对象当做参数传给bpXXX的类,通过bpbinder的transact函数来发送和接受请求(调用talkWithDriver与binder设备交互)。而bn端一般是自己打开binder设备,调用drivertalk函数来发送和接受请求。
3.所有的service都由servicemanager管理,这个servicemanager的名字叫"service”(囧)。它维护着一个链表,里面放了所有的service,用名字(字符串)和对应的对象关联起来。比如代理端要调用mediaservice服务,那就去servicemanager里通过"mediaservice"找这个服务,如果有,就返回一个bpbinder的实例,通过它和service端对话。让service端执行发过去的命令。
上面就是这个service的入口。
第一步的sp<ProcessState> proc(ProcessState::self());就是打开binder
具体做法是:
     1.打开dev/binder设备(android自己创建的虚拟设备,相当于一个文件),得到fd
     2.用mmap把fd映射到内存,映射后的指针保存在ProcessStat的实例中。
第二步:创建一个servicemanager对象。经过几层代码,实际调用的是:interface_cast<IServiceManager>(new BpBinder(0));
bpbinder作为参数传入,作用就是读写binder设备。
关键是另两个:interface_cast函数,和IServiceManager。
interface_cast的作用是以IServiceManager为接口,生成对应的对象,比如这里就是生成bpServiceManager对象。
interface_cast<IServiceManager>(new BpBinder(0));等价于IServiceManager::asInterface(new BpBinder(0));所以interface_cast不过是调用IServiceManager的asInterface函数,前提是IServiceManager必须有实现这个函数。
DECLARE_META_INTERFACE(ServiceManager);

IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");



IServiceManager类里面通过这两个宏实现了asInterface函数,这种方法借鉴了MFC。
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager")宏实现的asInterface函数主要做了下面的事:

new BpServiceManager(obj);

回到前面,interface_cast<IXXX>(new BpBinder(0));的作用就是生成一个bpXXX对象。
BpServiceManager要实现一个函数addservice,这个就是bpServiceManager对象要做的是,添加service,这个函数是在IServiceManager类里声明的,BpServiceManager通过class
BpServiceManager : public BpInterface<IServiceManager>继承过来。


第三步:MediaPlayerService::instantiate();
new了一个BnMediaPlayerService,并调用上面的bpServiceManager对象的addservice函数,把这个service添加到服务端bnServiceManager管理的list里。
addservice把BnMediaPlayerService的服务打包成data,再调用bpbinder的transact函数,通过binder设备,把这个包发到服务端的bnServiceManager。


第四步:

 ProcessState::self()->startThreadPool();//看名字,启动Process的线程池?

    IPCThreadState::self()->joinThreadPool();//将自己加入到刚才的线程池?

startThreadPool函数创建子线程:_threadLoop,然后调用joinThreadPool,主线程和子线程都调用了joinThreadPool。
joinThreadPool函数调用talkWithDriver和binder设备交互,executeCommand执行binder中解析出的命令。它是通过BBinder类(MediaPlayerService的父类),来调用MediaPlayerService实现的onTransact函数,
onTransact会根据不同的指令,执行不同的操作。

下面讲下,MediaPlayerService是怎么实现的

class MediaPlayerService : public BnMediaPlayerService


class BnMediaPlayerService: public BnInterface<IMediaPlayerService>

template<typename INTERFACE>

class BnInterface : public INTERFACE, public BBinder 这里通过模板把要继承的接口IMediaPlayerService,通过多重继承,继承过来


兑现后变成

class BnInterface : public IMediaPlayerService, public BBinder     :这里同时继承了BBinder,后面就可以通过BBinder类,来调用MediaPlayerService实现的函数了




如何自己实现service:

int main()

{

  sp<ProcessState> proc(ProcessState::self());

sp<IServiceManager> sm = defaultServiceManager();

sm->addService(“service.name”,new XXXService());

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

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

}


要实现XXXService,XXXService包括bp和bn两个部分,
要实现bp就要用class BpXXX: public BpInterface<IXXX>,获取这对象用inteface_cast<IXXXService>(bpbinder());
要实现bn就要用class bnXXX:public BnInterface<IXXXService>

IXXXService用到下面两个宏:
DECLARE_META_INTERFACE(XXXService);
IMPLEMENT_META_INTERFACE(XXXService,
"android.os.I
XXXService");
来实现asInterface,这个用来得到bp对象



同时要定义bp用到函数的虚接口。

bnXXXService继承IXXXService后要定义的接口是onTransact,这个是bn用来处理bp发过来的指令的。

抱歉!评论已关闭.