从MediaServer看Binder的使用方式(一)

语言: CN / TW / HK

theme: channing-cyan

android源码分析目录

一 概述

Binder是Android中的一种IPC机制,在Binder中,Binder是基于C/S架构的,但是除了C/S架构中的Client和Server,Android中还有一个ServiceManager,它的作用就是管理各种服务,我们在Service的启动中已经见识过它了。

接下来,在我们深入学习Binder之前,我们先通过Android系统自己对于Binder的使用,来了解Binder,在这里,我们选择的目标是MediaServer

源码目录

```

frameworks/av/media/mediaserver/main_mediaserver.cpp frameworks/native/libs/binder/ProcessState.cpp frameworks/native/libs/binder/IServiceManager.cpp frameworks/native/libs/binder/BpBinder.cpp frameworks/native/libs/binder/include/binder/IInterface.h frameworks/native/libs/binder/IServiceManager.cpp frameworks/native/libs/binder/Binder.cpp frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp frameworks/native/libs/binder/BpBinder.cpp frameworks/native/libs/binder/IPCThreadState.cpp ```

二 MediaServer的入口

MediaServer的入口函数如下,这是一个非常标准的Binder使用流程

```cpp [main_mediaserver.cpp]

int main(int argc __unused, char **argv __unused) { signal(SIGPIPE, SIG_IGN); //1 获得一个ProcessState的实例 sp proc(ProcessState::self()); //2 获得一个IServiceManager对象 sp sm(defaultServiceManager()); ALOGI("ServiceManager: %p", sm.get()); AIcu_initializeIcuOrDie(); //3 注册服务 MediaPlayerService::instantiate(); ResourceManagerService::instantiate(); //4 注册其他,默认为空 registerExtensions(); //5 ProcessState有关线程池 ProcessState::self()->startThreadPool(); //6 IPCThreadState有关线程池 IPCThreadState::self()->joinThreadPool(); } ```

在上述代码中,我们看到了大致6个步骤,接下来,我们就对这6个步骤进行一一分析

三 ProcessState

看步骤1的代码,我们也能大致猜测出来,它是一个单例,这个self方法具体如下

```cpp [ProcessState.cpp]

sp ProcessState::self() { Mutex::Autolock _l(gProcessMutex); if (gProcess != nullptr) { return gProcess; } //第一次执行一定为空,需要创建对象,所以会执行构造函数 gProcess = new ProcessState(kDefaultDriver); return gProcess; } ```

3.1 ProcessState的构造函数

```cpp [ProcessState.cpp]

ProcessState::ProcessState(const char *driver) : mDriverName(String8(driver)) //这里是关键点 , mDriverFD(open_driver(driver)) , ... { if (mDriverFD >= 0) { //调用一个mmap,拿到起始地址 mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); if (mVMStart == MAP_FAILED) { // 如果mmap映射失败,一般不会执行 ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str()); close(mDriverFD); mDriverFD = -1; mDriverName.clear(); } }

LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");

} ```

3.2 open_driver

```cpp [ProcessState.cpp]

static int open_driver(const char *driver) {
//打开binder驱动 int fd = open(driver, O_RDWR | O_CLOEXEC); if (fd >= 0) { int vers = 0; //通过ioctl的方式与binder驱动进行交互 //版本 status_t result = ioctl(fd, BINDER_VERSION, &vers); if (result == -1) { ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno)); close(fd); fd = -1; } if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) { ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)! ioctl() return value: %d", vers, BINDER_CURRENT_PROTOCOL_VERSION, result); close(fd); fd = -1; } size_t maxThreads = DEFAULT_MAX_BINDER_THREADS; //最大线程数,默认是15 result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads); if (result == -1) { ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno)); } } else { ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno)); } return fd; } ```

到这里,Process的构造函数就算是结束了,它主要的工作如下

  1. 打开binder驱动(默认是/dev/binder),获得一个fd
  2. 对于返回的fd使用mmap,这样Binder驱动就会分配一块内存来接收数据
  3. Process是单例的

四 defaultServiceManager

defaultServiceManager是IServiceManager中的一个函数,它返回了一个IServiceManager对象,它也是一个单例

```cpp [IServiceManager.cpp ]

sp defaultServiceManager() { if (gDefaultServiceManager != nullptr) return gDefaultServiceManager;

{
    AutoMutex _l(gDefaultServiceManagerLock);
    while (gDefaultServiceManager == nullptr) {
        //创建一个gDefaultServiceManager对象
        gDefaultServiceManager = interface_cast<IServiceManager>(
            ProcessState::self()->getContextObject(nullptr));
        //如果为空,就循环等待
        if (gDefaultServiceManager == nullptr)
            sleep(1);
    }
}

return gDefaultServiceManager;

} ```

在defaultServiceManager中,首先会通过getContextObject来获取一个gDefaultServiceManager对象,如果没有获取到,那么就会循环等待,这里我们有两个问题

  1. getContextObject是如何获取的gDefaultServiceManager
  2. 什么情况下会获取不到

首先我们思考第一个问题,getContextObject做了什么

4.1 getContextObject

getContextObject是ProcessState中的函数,具体如下

```cpp [ProcessState.cpp]

sp ProcessState::getContextObject(const sp& /caller/) { return getStrongProxyForHandle(0); }

[ProcessState.cpp]

//通过一个int的handle值,来获得一个IBinder sp ProcessState::getStrongProxyForHandle(int32_t handle) { sp result;

AutoMutex _l(mLock);

//根据handle值来查找
handle_entry* e = lookupHandleLocked(handle);

if (e != nullptr) {
    //拿到查找对象中的IBinder
    IBinder* b = e->binder;
    if (b == nullptr || !e->refs->attemptIncWeak(this)) {
        //如果IBinder为空
        if (handle == 0) {
            //handle值为0
            Parcel data;
            status_t status = IPCThreadState::self()->transact(
                    0, IBinder::PING_TRANSACTION, data, nullptr, 0);
            if (status == DEAD_OBJECT)
               return nullptr;
        }
        //根据handle值创建一个BpBinder
        b = BpBinder::create(handle);
        //填充entry
        e->binder = b;
        if (b) e->refs = b->getWeakRefs();
        result = b;
    } else {
        result.force_set(b);
        e->refs->decWeak(this);
    }
}

return result;

} ```

4.2 BpBinder

在getStrongProxyForHandle函数中,我们看到了一个对象叫BpBinder,关于BpBinder,这里简单说明一下

  • 在Android中,使用BInder通信时,一般都会有两个对象BpBinder和BBinder
  • 它们都是继承自IBinder而来的,BpBinder代表客户端,BBinder代表服务端
  • 这里创建时传入的handle值0就是它们用来对应的标识

关于BpBinder的构造函数如下

```cpp [BpBinder.cpp]

BpBinder::BpBinder(int32_t handle, int32_t trackedUid) : mHandle(handle) , mAlive(1) , mObitsSent(0) , mObituaries(nullptr) , mTrackedUid(trackedUid) { ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);

extendObjectLifetime(OBJECT_LIFETIME_WEAK);
IPCThreadState::self()->incWeakHandle(handle, this);

} ```

这个构造函数很简单,接下来我们再看拿到了这个BpBInder对象之后又做了什么

4.3

经过BpBInder对象的构造,我们可以将之前代码简化

```cpp gDefaultServiceManager = interface_cast( ProcessState::self()->getContextObject(nullptr)); //因为ProcessState::self()->getContextObject(nullptr)获得的是一个BpBInder //所以如上代码如下 gDefaultServiceManager = interface_cast(new BpBInder(0));

然后通过interface_cast将这个对象转化成IServiceManager,关于interface_cast,它是模板函数

[IInterface.h]

//模板函数 template inline sp interface_cast(const sp& obj) { return INTERFACE::asInterface(obj); }

//宏定义如下 #define DECLARE_META_INTERFACE(INTERFACE) \ public: \ static const ::android::String16 descriptor; \ static ::android::sp asInterface( \ const ::android::sp<::android::IBinder>& obj); \ ...

#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \ ...
::android::sp I##INTERFACE::asInterface( \ const ::android::sp<::android::IBinder>& obj) \ { \ ::android::sp intr; \ if (obj != nullptr) { \ intr = static_cast( \ obj->queryLocalInterface( \ I##INTERFACE::descriptor).get()); \ if (intr == nullptr) { \ intr = new Bp##INTERFACE(obj); \ } \ } \ return intr; \ }
```

然后通过两个宏定义DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE,就将它们关联起来了

```cpp [IServiceManager.h]

class IServiceManager : public IInterface { public: DECLARE_META_INTERFACE(ServiceManager) ... } ```

并且在IServiceManager.cpp中,有一行IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager")

所以上述的interface_cast(new BpBInder(0));最后其实是创建了一个BpServiceManager

4.3 BpServiceManager

接下来,我们看看这个创建过程发生了哪些事情,首先我们先看BpServiceManager的继承关系

ServiceManager继承关系.png 首先是BpServiceManager的构造函数,它是IServiceManager.cpp的一个内部类

```cpp [IServiceManager.cpp]

class BpServiceManager : public BpInterface { public: explicit BpServiceManager(const sp& impl) : BpInterface(impl) ... ```

然后是BpInterface,它是IInterface.h的一个内部类

```cpp [IInterface.h]

template inline BpInterface::BpInterface(const sp& remote) : BpRefBase(remote) ... ```

接下来是BpRefBase,它是Binder.cpp的一个内部类

```cpp [Binder.cpp]

BpRefBase::BpRefBase(const sp& o) : mRemote(o.get()), mRefs(nullptr), mState(0) ... ```

通过 BpServiceManager -> BpInterface -> BpRefBase,最后将我们传入的一个BpBinder和一个mRemote关联了起来,到这里,我们的准备工作就算是完成了

五 IPCThreadState

5.1 服务的注册

在main_mediaserver.cpp的第三步MediaPlayerService::instantiate();,就是服务的注册

```cpp [MediaPlayerService.cpp]

void MediaPlayerService::instantiate() { defaultServiceManager()->addService( String16("media.player"), new MediaPlayerService()); } ```

如果看过SystemServer的源码,就会发现里面有很多这样addService注册服务的逻辑,这里的defaultServiceManager在前面我们已经说了,它是一个BpServiceManager对象,它继承自IServiceManager,它的addService方法如下

```cpp [IServiceManager::BpServiceManager]

virtual status_t addService(const String16& name, const sp& service, bool allowIsolated, int dumpsysPriority) { //这里有一个Parcel,这个对象是Android中跨进程通信的重要对象,数据就保存在这里面 Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); data.writeString16(name); data.writeStrongBinder(service); data.writeInt32(allowIsolated ? 1 : 0); data.writeInt32(dumpsysPriority); //这个remote()就是我们创建时候传入的BpBinder status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); return err == NO_ERROR ? reply.readExceptionCode() : err; } ```

这里我们看到了一个transact,这个方法我们以后会经常看见,它就是和Binder交互的重要函数

5.2 IPCThreadState的创建

刚才我们说到了Binder的具体交互函数transact,它是定义在BpBinder中的,接下来我们就看看BpBinder中的具体逻辑

``` [BpBinder.cpp]

status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { // Once a binder has died, it will never come back to life. if (mAlive) { //关键点,IPCThreadState status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags); if (status == DEAD_OBJECT) mAlive = 0; return status; }

return DEAD_OBJECT;

} ```

这里我们看到了一个IPCThreadState,这个类也是Binder通信中非常重要的类,我们先看它的self方法

```cpp [IPCThreadState.cpp]

IPCThreadState IPCThreadState::self() { //第一次是false if (gHaveTLS) { restart: //在restart中创建IPCThreadState对象 const pthread_key_t k = gTLS; IPCThreadState st = (IPCThreadState*)pthread_getspecific(k); if (st) return st; return new IPCThreadState; }

//第一次是false
if (gShutdown) {
    ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
    return nullptr;
}

//线程锁
pthread_mutex_lock(&gTLSMutex);
if (!gHaveTLS) {
    int key_create_value = pthread_key_create(&gTLS, threadDestructor);
    if (key_create_value != 0) {
        pthread_mutex_unlock(&gTLSMutex);
        ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
                strerror(key_create_value));
        return nullptr;
    }
    gHaveTLS = true;
}
pthread_mutex_unlock(&gTLSMutex);
//跳转到restart
goto restart;

} ```

可以看出这个是一个和线程相关的单例,在同一个线程下它只有一个对象,接下来我们再看它的构造函数

```cpp [IPCThreadState.cpp]

IPCThreadState::IPCThreadState() : mProcess(ProcessState::self()), mWorkSource(kUnsetWorkSource), mPropagateWorkSource(false), mStrictModePolicy(0), mLastTransactionBinderFlags(0), mCallRestriction(mProcess->mCallRestriction) { //和线程相关联 pthread_setspecific(gTLS, this); clearCaller(); //和Binder驱动交互的两个缓冲区 mIn.setDataCapacity(256); mOut.setDataCapacity(256); mIPCThreadStateBase = IPCThreadStateBase::self(); } ```

然后在构造函数中,初始化了两个缓冲区mIn和mOut,这个mIn是从Binder设备读数据的,而mOut则是向Binder设备写数据的

5.3 transact

接下来我们就要看最关键的transact

```cpp [IPCThreadState.cpp]

status_t IPCThreadState::transact(int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { ... err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr); ... if ((flags & TF_ONE_WAY) == 0) {
... if (reply) { err = waitForResponse(reply); } else { Parcel fakeReply; err = waitForResponse(&fakeReply); } ... } else { err = waitForResponse(nullptr, nullptr); } return err; } ```

transact中的逻辑非常长,并且里面还有很多判断,不过这里不论是哪个分支,都会调用到两个方法,分别是writeTransactionData和waitForResponse,接下来我们就看看这个waitForResponse里面具体做了什么事

5.4 writeTransactionData

```cpp [IPCThreadState.cpp]

status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer) { binder_transaction_data tr;

tr.target.ptr = 0;
tr.target.handle = handle;
tr.code = code;
tr.flags = binderFlags;
tr.cookie = 0;
tr.sender_pid = 0;
tr.sender_euid = 0;

//将数据用tr进行封装
...

//将数据写到mOut
mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr));

return NO_ERROR;

} ```

显然,writeTransactionData主要的作用就是将要传递的参数写到mOut中去

5.5 waitForResponse

```cpp [IPCThreadState.cpp]

status_t IPCThreadState::waitForResponse(Parcel reply, status_t acquireResult) { uint32_t cmd; int32_t err;

while (1) {
    if ((err=talkWithDriver()) < NO_ERROR) break;
    ...
    //从Binder中读出数据
    cmd = (uint32_t)mIn.readInt32();

    //死循环加上switch,说明一次Binder交互会读出多次数据
    switch (cmd) {
    ...


    default:
        //执行拿到的cmd
        err = executeCommand(cmd);
        if (err != NO_ERROR) goto finish;
        break;
    }
}

finish: if (err != NO_ERROR) { if (acquireResult) *acquireResult = err; if (reply) reply->setError(err); mLastError = err; }

return err;

} ```

在waitForResponse中,会不断的从mIn中读出数据,然后根据这个读出的数据,执行不同的逻辑

六 总结

到此,我们基本知道了,MediaServer在使用Binder时,是如何注册的,不过对于IPCThreadState的细节,本篇还没完全说明白,关于后续的部分在下一篇说明