Binder机制分析(2)——从MediaService中看Binder的实现和使用(2)

来源:互联网 发布:Vb大漠插件注册 编辑:程序博客网 时间:2024/04/25 12:52

本文是对《Android技术内幕-系统卷》第三章的摘抄和整理。


1. 如果我们要使用MediaPlayerService服务,那么MediaPlayerService客户端就需要与MediaPlayerService(即BnMediaPlayerService)交互。交互的过程需要建立一个循环,然后读写Binder设备。注意,在BnMediaPlayerService中并没有打开Binder设备和建立一个循环监听,这里实际上是借用ProcessState来完成了MediaPlayerService的一些功能,下面我们继续分析。


    前面说过,ProcessState会维护一个进程中的所有服务(Server)代理,每个进程中只能有一个;当然,也包括需要维护这里的MediaPlayerService服务的代理。因此,在main_mediaserver.cpp的main函数中,紧接着由“ProcessState::self()->startThreadPool();”来创建一个线程池并启动,而线程池PoolThread又继承自线程Thread。因此,当PoolThread在执行run函数启动时,会执行Thread的run函数(位于“framework\base\libs\utils\thread.cpp中”),如代码所示。

    Thread::run的实现
    status_t Thread::run(const char  
    name, int32_t priority, size_t stack)  
    {  
        //省略部分代码  
        if (mCanCallJava) {  
            res = createThreadEtc(_threadLoop,  
                    this, name, priority, stack, &mThread);  
        } else {  
            res = AndroidCreateRawThreadEtc(_threadLoop,  
                    this, name, priority, stack, &mThread);  
        }  
        //省略部分代码  
        return NO_ERROR;  
    }

2. 这里通过createThreadEtc创建了一个线程,线程函数为_threadLoop,因此,在_threadLoop函数中又调用了IPCThreadState::self()->joinThreadPool。注意,在main_mediaserver.cpp的main函数中也会调用IPCThreadState::self()->joinThreadPool,也就是说,主线程和工作线程都会执行joinThreadPool;在该函数中通过talkWithDriver函数操作Binder驱动程序,executeCommand函数来执行命令。查看executeCommand的代码可以得知,实际上会根据不同的命令进行不同的解析,但是最终的解析还是调用BBinder::transact函数,而transact又调用了自己的BBinder::onTransact函数。这里的BnMediaPlayerService继承自BBinder,所以会调用到它自己的BnMediaPlayerService::onTransact函数。

3. 最后,如果我们需要使用MediaPlayerService,那么首先就需要创建一个BpMediaPlayer Service,创建过程大致如代码清单3-62所示。
    创建BpMediaPlayerService的过程
    sp<IServiceManager> sm = defaultServiceManager();  
    sp<IBinder> binder;  
    do {  
        //查询MediaPlayerService,返回Binder  
        binder = sm->getService(String16("media.player"));  
        if (binder != 0) {  
                    break;  
        }  
        usleep(500000); // 0.5 s  
     } while(true);  
    sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
    其过程为:首先通过defaultServiceManager函数获得ServiceManager对象,然后调用Service Manager::getService查询指定名称(media.player)的MediaPlayerService服务,再通过interface_cast将查询得到的Binder转化成BpMediaPlayerService对象。这样,BpMediaPlayerService就可以与BnMediaPlayerService进行通信了。
原创粉丝点击