算是对阅读这篇文章的一个记录。
Framework层Binder的位置:
#ls frameworks/native/libs/binder/
Android.mk IInterface.cpp IPermissionController.cpp MemoryDealer.cpp PermissionCache.cpp
Binder.cpp IMemory.cpp IServiceManager.cpp MemoryHeapBase.cpp ProcessState.cpp
BpBinder.cpp IPCThreadState.cpp MemoryBase.cpp Parcel.cpp Static.cpp
大部分服务与binder交互都会有这么个流程:
int main(int argc, char** argv)
{
sp proc(ProcessState::self());
sp sm = defaultServiceManager();
MediaPlayerService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
代码片段截自frameworks/av/media/mediaserver/main_mediaserver.cpp
下面说下主要的函数:
1. ProcessState
它的构造函数做的工作:
打开/dev/binder设备
映射fd到内存
2. defaultServiceManager
sp defaultServiceManager()
{
...
gDefaultServiceManager = interface_cast(
ProcessState::self()->getContextObject(NULL));
...
}
ProcessState::self()->getContextObject(NULL) ---> getStrongProxyForHandle(0) ---> new BpBinder(handle)
最终会转化为:
gDefaultServiceManager = interface_cast(new BpBinder(0));
new BpBinder(0) ---> IPCThreadState::self()->incWeakHandle(handle) ---> 主要是得到一个IPCThreadState实例,incWeakHandle不用管它
再来看看interface_cast(new BpBinder(0))是怎么把BpBinder实例转换为IServiceManager的。
要从interface_cast模板开始分析,这个模板类里有个叫asInterface的函数,也就是调用到了IServiceManager::asInterface,在IServiceManager类定义时有一句:
DECLARE_META_INTERFACE(ServiceManager),在IServiceManager.cpp文件里有一句
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager"),跟到IMPLEMENT_META_INTERFACE这个宏里,最终会有个asInterface函数,在
asInterface这个函数里有句new BpServiceManager(obj)。
所以
gDefaultServiceManager = interface_cast(new BpBinder(0));
相当于
gDefaultServiceManager = new BpServiceManager(new BpBinder(0));
看看BpServiceManager类的声明:
class BpServiceManager : public BpInterface
也就是说BpServiceManager类同时继承BpInterface和IServiceManager。
*一般binder都会有个BnServiceManager,BpServiceManager,就是Binder Native, Binder Proxy的缩写。这两个BnServiceManager,BpServiceManager的实现都在
IServiceManager.cpp文件里。Bp即是ServiceManager的代理,Bn就是和这个代理打交道的。
*用binder时一般都会通过BpServiceManager,调用BpServiceManager的addService告诉ServiceManager来管理我们的Service。
new BpServiceManager
--->
BpServiceManager(const sp& impl)
: BpInterface(impl)
{
}
--->
inline BpInterface::BpInterface(const sp& remote)
: BpRefBase(remote)
{
}
--->
BpRefBase::BpRefBase(const sp& o)
: mRemote(o.get()), mRefs(NULL), mState(0)
{
...
}
这里的mRemote指向了BpBinder(0)
目前我们可以知道:
sp sm = defaultServiceManager(); 返回的实际是BpServiceManager,它的remote对象是BpBinder,传入的那个handle参数是0
之后会得到一个MediaPlayerService实例,通过BpServiceManager调用addService告诉ServiceManager有服务加入。
BnServiceManager一般有一个binder_looper函数,专门等着从binder中接收请求,即等着addService的请求。目前BnServiceManager不存在,不过有个service_manager,
service_manager做了上边描述的事情。代码在frameworks/base/cmds/servicemanager/service_manager.c
照这样看,BpServiceManager可以理解为ServiceManager的一个引用,用来和ServiceManager交互,而BnServiceManager是处理请求的。
*注意每个Service都有对应的binder设备fd,通过这个fd与binder驱动交互
接下来我们看看以下两句都做了什么:
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
void ProcessState::spawnPooledThread(bool isMain)
{
sp t = new PoolThread(isMain);
t->run(buf);
}
startThreadPool ---> spawnPooledThread
---> new PoolThread(isMain) ---> PoolThread和Thread的构造函数
---> t->run ---> 此时还未创建线程,所以调用的是基类的run,即Thread的run
Thread::run ---> createThreadEtc(_threadLoop, ...) ---> self->threadLoop() ---> PoolThread::threadLoop
---> IPCThreadState::self()->joinThreadPool(mIsMain) 注意这是开启的新线程,所以会再初始化一个IPCThreadState实例,与main函数里用到的不是同一个实例
Thread类在:
frameworks/native/libs/utils/Threads.cpp
只列joinThreadPool的主体:
do {
result = talkWithDriver();
result = executeCommand(cmd);
} while (result != -ECONNREFUSED && result != -EBADF);
executeCommand() {
case BR_TRANSACTION:
sp b((BBinder*)tr.cookie);
b->transact(tr.code, buffer, &reply, tr.flags);
}
class BnMediaPlayerService: public BnInterface
template
class BnInterface : public INTERFACE, public BBinder
也就是说BnMediaPlayerService从BBinder继承,所以b->transact ---> BnMediaPlayerService::onTransact
frameworks/av/media/libmedia/IMediaPlayerService.cpp
onTransact代码不列,自行查看。内容主要是switch/case,通过case来区分IMediaPlayerService提供的函数。
*也就是说,BnXXX的onTransact函数收取命令,然后派发到派生类的函数,由他们完成实际的工作
上面有两个地方调用了joinThreadPool,一个是最上边列的main函数,一个是在PoolThread::threadLoop函数里,注意这是两个不同的线程,实例是不一样的。不用追究为什么这
么做,可能是效率的原因,注掉main函数里的那个也能工作,有人试过。
那MediaPlayerClient怎么和MediaPlayerService交互呢?
当然是创建个BpMediaPlayerService,然后和BnMediaPlayerService交互了。