本文是对《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进行通信了。