Chinaunix首页 | 论坛 | 博客
  • 博客访问: 412716
  • 博文数量: 60
  • 博客积分: 442
  • 博客等级: 下士
  • 技术积分: 910
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-27 14:53
文章分类

全部博文(60)

文章存档

2021年(1)

2018年(1)

2017年(14)

2016年(31)

2015年(1)

2013年(3)

2012年(9)

我的朋友

分类: Android平台

2016-04-16 20:49:52

算是对阅读这篇文章的一个记录。

 
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交互了。
阅读(1753) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~