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

781 阅读8分钟

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使用流程

[main_mediaserver.cpp]

int main(int argc __unused, char **argv __unused)
{
    signal(SIGPIPE, SIG_IGN);
	//1 获得一个ProcessState的实例
    sp<ProcessState> proc(ProcessState::self());
    //2 获得一个IServiceManager对象
    sp<IServiceManager> 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方法具体如下

[ProcessState.cpp]

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

3.1 ProcessState的构造函数

[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

[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对象,它也是一个单例

[IServiceManager.cpp ]

sp<IServiceManager> 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中的函数,具体如下

[ProcessState.cpp]

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

[ProcessState.cpp]

//通过一个int的handle值,来获得一个IBinder
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> 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的构造函数如下

[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对象的构造,我们可以将之前代码简化

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

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

[IInterface.h]

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

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

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

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

[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的一个内部类

[IServiceManager.cpp]

class BpServiceManager : public BpInterface<IServiceManager>
{
public:
    explicit BpServiceManager(const sp<IBinder>& impl)
        : BpInterface<IServiceManager>(impl)
...

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

[IInterface.h]

template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
    : BpRefBase(remote)
...

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

[Binder.cpp]

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

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

五 IPCThreadState

5.1 服务的注册

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

[MediaPlayerService.cpp]

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

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

[IServiceManager::BpServiceManager]

virtual status_t addService(const String16& name, const sp<IBinder>& 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方法

[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;
}

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

[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

[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

[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

[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的细节,本篇还没完全说明白,关于后续的部分在下一篇说明