一、概述
Binder 是Android 系统提供的一种基于C/S架构体系的IPC机制。安卓系统通过ServiceManager管理系统服务器。服务提供者通可以通过Binder通信向ServiceManager注册服务器,而Client可以向ServiceManager查询服务,并且获取自己需要的服务器的handle,然后通过Binder调用自己需要服务器。架构如下:
二、Server如何通过Binder与ServiceManager通信
我们以MediaServer为例,去看Server怎么与ServiceManager通信。MediaServer进程中驻留的服务有:MediaPlayService、CameraService、AudioPolicyService等服务器,可以在安卓系统代码中搜索到MediaServer的代码:Main_MediaServer.cpp如下:
1、获取ProcessState实例
代码通过ProcessState::self()获取一个ProcessState实例,函数的重要调用流如下,可以根据调用流自己跟一下代码:
调用流程(一层缩进一次函数调用,同一层缩进在同一个函数中):
ProcessState::self()
==> ProcessState::ProcessState()
==> open_driver()
==>int fd = open("/dev/binder", O_RDWR | O_CLOEXEC);//打开binder设备驱动
==> mmap(0, mMmapSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0)//通过mmap,驱动会分配一个内存,映射到用户空间
可以看出,ProcesstState:self打开了Binder驱动文件:"/dev/binder",并且通过mmap映射一段内存到用户空间。
2、获取ISericeManager与ServiceManager通信
通过defaultServiceManager(),获取ISericeManager对象,以便与ServiceManager通信。
调用流程:
defaultServiceManager()
==> ProcessState::self()->getContextObject()
==> getStrongProxyForHandle(0) //参数handle为0,0是ServiceManager的handle
==> BpHwBinder(handle) //创建一个BpBinder
==> interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));
==> asInterface(obj);//生成一个IServiceManager,转入上面生成的BpBinder
==> new BpServiceManager(obj)//通过宏:IMPLEMENT_META_INTERFACE ,obj为上面生成的BpBinder,最终存于BpServiceManager的变量mRemote
==> new BpInterface(obj)
==> new BpRefBase(obj):mRemote(o.get()), mRefs(NULL), mState(0)
通过调用,创建了一个BpBinder,并且用这个BpBinder生成了一个BpServiceManager,BpServiceManager有一个mRemote变量存放上面生成的BpBinder。BpServiceManager实现了ISericeManager接口。
他们的族谱如下图:
所以,通过defaultServiceManager(),可以得到以下两个对象:
- 有一个BpBinder对象,它的Hanlel值为0,指向ServiceManager
- 有一个BpServiceManager对包,它有一个mRemote值,是上面的BpBinder.
为什么要有上面两上对象呢?这两个对象又有何作用?
- BpServiceManager对象主要实现与ServiceManager通信的业务逻辑,函数包括:getService()、addService()、checkService()、listServices()
- BpBinder对象主要实现通信逻辑,函数包括:transact()
3、注册MediaPlayerService
上面函数重要调用流程如下:
defaultServiceManager()//为单例设计模式,直接返回上面的生成的BpServiceManager。
==> BpServiceManager::addService()
==> remode() // 返回mRemote,即使BpBinder
==>BpHwBinder::transact()
==>IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
(1)defaultServiceManager
defaultServiceManager()为单例设计模式,直接返回上面的生成的BpServiceManager。
(2) BpServiceManager::addService()
业务层逻辑,添加服务到SerivceManager,打包数据并调用BpHwBinder::transact()
(3)BpHwBinder::transact()
通信层逻辑,实现IPC通信,实际调用IPCThreadState::self() -> transact()
(4)IPCThreadState::self() -> transact()
IPCThreadState真实通信业务的承担者
IPCThreadState::self()作用:创建一个线程,并且创建一个IPCThreadState对象,作为线程的TLS:Thread Local Storage(线程本地空间,线程之间互相不共享,通过pthread_setspecific(gTLS, this)和pthread_getspecific(k)来获取和设置)。
每个线程都有一个IPCThreadState,每一个IPCThreadState都有一个mIn和mOunt,mIn用于接收自来Binder设备的数据,mOunt用于存储发往Binder设备的数据
调用流程:
IPCThreadState::self() -> transact()
==>IPCThreadState::self()
==>pthread_key_create(&gTLS, threadDestructor)//创建线程TLS空间
==>new IPCThreadState()//创建IPCThreadState对象
==> pthread_setspecific(gTLS, this);
==>mIn.setDataCapacity(256);
==> mOut.setDataCapacity(256);
==>IPCThreadState -> transact()
==>writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
==>mOut.writeInt32(cmd);
==>mOut.write(&tr, sizeof(tr));
==> waitForResponse(reply);
==>talkWithDriver();//与驱备沟通,实现读写和作用
==>ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) //通守ioctl对"/dev/binder"操作,实现binder读写通信
4、创建一个子线程与Binder通信
main_mediaserver.cpp中main函数调用:ProcessState::self()->startThreadPool();来创建一个子线程与Binder通信。
调用流程:
ProcessState::self()->startThreadPool();
==> spawnPooledThread()
==>sp<Thread> t = new PoolThread(isMain);
==>t->run(name.string());
==>PoolThread::threadLoop()
==>IPCThreadState::self()->joinThreadPool(mIsMain);
==>getAndExecuteCommand()//在while循环中被调用
==>talkWithDriver()
5、主线程自己通Binder通信
main_mediaserver.cpp中main函数调用:IPCThreadState::self()->joinThreadPool(mIsMain);
三、Server小结:
- MediaServer有四个服务:AudioFlinger、MediaPlayerService、CameraService和AudioPolicyService。
- 通过调用PorcessState::self()打开binder设备驱动/dev/binder并通过通过mmap,驱动会分配一个内存,映射到用户空间。
- 通过defaulteServiceManager(),创建一个BpBinder用于处理通信逻辑,生成一个BpServiceManager,用于处理业务逻辑。
- 在各个Service的instantiate()函数中,创建服务并调用BpServiceManager的addService函数,与ServiceManager通信,注册服务
- 创建一个子线程,在子线程和主线程中,轮询Binder设备通信
四、ServiceManager
(1)binder_open:打印驱动设备(“/dev/binder”)
调用流程:
binder_open()
==> open(driver, O_RDWR | O_CLOEXEC)
==> ioctl(bs->fd, BINDER_VERSION, &vers)
==>mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
(2) binder_become_context_manager()设置handle为0
==> ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
(3) binder_loop(bs, svcmgr_handler):处理binder设备业务
binder_loop()
==> binder_parse()//通信逻辑
==>svcmgr_handler()//SerivceManager的业务逻辑:添加get\check\add\list service
==>binder_send_reply()
(4)关于注册服务调用流程:
do_add_service()
==> svc_can_register() // 判断是否有权限注册
==>find_svc () //查找是否已经存在服务
==> si->next = svclist; svclist =si; //添加到链表
==> binder_link_to_death //服务退出处理
ServiceManager存在意义:
- 集中管理系统内的所有服务,权限管控
- 通过名字查找服务,类似DNS
- 使client更容易获取服务器的状态:生老病死
五、MediaPlayerService
1、MediaPlayerService的类继承家谱图
BnInterface继承了业务逻辑类(IMediaPlayerService)和通信逻辑类(BBinder)
类定义时,业务逻辑部分使用模板类,作用时方便切换不同业务逻辑。
2、MediaPlayerService如何提供服务
(1)client通过ServiceManger获取MediaPlayerService
IMediaDeathNotifier::getMediaPlayerService()
{
ALOGV("getMediaPlayerService");
Mutex::Autolock _l(sServiceLock);
if (sMediaPlayerService == 0) {
//获取ServiceManger的BpBinder
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
//通过ServiceManger获取MediaPlayerService的BpBinder
binder = sm->getService(String16("media.player"));
if (binder != 0) {
break;
}
ALOGW("Media player service not published, waiting...");
usleep(500000); // 0.5 s
} while (true);
if (sDeathNotifier == NULL) {
sDeathNotifier = new DeathNotifier();
}
binder->linkToDeath(sDeathNotifier);
//interface_cast把binder转换为BpMediaPlayerService
sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
}
ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
return sMediaPlayerService;
}
(2)MediaPlayerService如何提供服务
MediaPlayerService给Client提供服务的具体逻辑如下:
MediaPlayerService服务驻留在MediaServer进程中,上面已经介绍了,MediaServer进程通过两个线程,调用IPCThreadState::self()->joinThreadPool(mIsMain)接收Binder信息。
MediaPlayerService服务如何给client提供服务呢?
调用流:
==>IPCThreadState::self()->joinThreadPool(mIsMain);
==>IPCThreadState::getAndExecuteCommand
==>talkWithDriver();//通过Binder驱动获取
==>executeCommand() //运行服务指令,假设此如为BR_TRANSACTION
==>BnMediaPlayerService::onTransact()//如BnMediaPlayerService通过继承了