1. MediapplayerService 的启动,如何在ServiceManager注册的,不讲解具体的细节
ServiceManager 是整个系统的Service总管,其余的系统服务都是通过defaultServiceManager的远程接口来调用ServiceManager。Service获得ServiceManager的接口之后就会把自己添加到ServiceManager中,然后把自己启动起来,之后等待着Client端的请求连接。
关于SystemManager如何启动并且成为总管和Binder的知识可以参考:
http://blog.csdn.net/luoshengyang/article/details/6621566
先看一下MediaPlayerService的UML,有个整体的了解。
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::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
BpMediaPlayerService的构造函数有一个参数impl,它的类型为const sp
我们就以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通信
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