Android笔记 - Binder之servicemanager代理对象

Posted demonyan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android笔记 - Binder之servicemanager代理对象相关的知识,希望对你有一定的参考价值。

1. 前言

上一篇文章解答了关于 servicemanager 的三个问题,其中讲到 servicemanager 作为一个特殊的 Service 组件,既负责为系统中其他的 Service 组件提供注册服务,同时又负责为 Client 组件提供获取 Service 组件代理对象的服务。那么 Service 组件和 Client 组件如何才能使用到 servicemanager 提供的服务呢?当然是通过 servicemanager 的代理对象,本文主要分析 defaultServiceManager 函数获取 servicemanager 代理对象的过程。 defaultServiceManager 函数定义如下:

代码路径:frameworks/native/libs/binder/IServiceManager.cpp

sp<IServiceManager> defaultServiceManager()

    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;

    
        AutoMutex _l(gDefaultServiceManagerLock);
        while (gDefaultServiceManager == NULL) 
            gDefaultServiceManager = interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(NULL));
            if (gDefaultServiceManager == NULL)
                sleep(1);
        
    

    return gDefaultServiceManager;

defaultServiceManager 函数中使用单例模式来获取 servicemanager 的代理对象,也就是说每个 Client 进程中只会存在一个 servicemanager 的代理对象。

由于全局变量 gDefaultServiceManager 用于保存 servicemanager 的代理对象,所以先判断 gDefaultServiceManager 是否为空,如果不为空则直接返回该变量,否则需要进行以下两个步骤:
1. 调用 ProcessState 的 getContextObject 函数获得一个代理对象 BpBinder,该代理对象即为 servicemanager 对应的代理对象 。
2. 调用模板函数 interface_cast 将获得的 BpBinder 进一步封装成 Client 进程易于使用的 BpServiceManager 对象。

接下来对这两个步骤的实现过程进行详细说明。

2. 获得 servicemanager 对应的代理对象 BpBinder

首先通过 ProcessState::self() 获得一个全局唯一的 ProcessState 实例,self 函数定义如下:

代码路径:frameworks/native/libs/binder/ProcessState.cpp

sp<ProcessState> ProcessState::self()

    Mutex::Autolock _l(gProcessMutex);
    if (gProcess != NULL) 
        return gProcess;
    
    gProcess = new ProcessState;
    return gProcess;

self 函数也使用单例模式来创建一个 ProcessState 实例,并赋值给全局变量 gProcess 。接下来看看 ProcessState 的构造函数,如下所示:

代码路径:frameworks/native/libs/binder/ProcessState.cpp

ProcessState::ProcessState()
    : mDriverFD(open_driver())
    , mVMStart(MAP_FAILED)                                                                         [1]           
    ......

    if (mDriverFD >= 0) 
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);  [2]
        if (mVMStart == MAP_FAILED) 
            close(mDriverFD);
            mDriverFD = -1;
        
    

使用 C++ 类构造函数的初始化列表显式的初始化类的成员。

[1] 调用函数 open_driver 打开 Binder 驱动设备文件 /dev/binder,并将设备文件描述符保存在成员变量 mDriverFD 中。
[2] 使用系统调用 mmap 将 Binder 设备文件映射到进程的用户地址空间,映射的地址空间大小为 BINDER_VM_SIZE,此过程在 Binder之守护进程servicemanager 中有说明。BINDER_VM_SIZE 大小定义如下:

#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))

接下来看 open_driver 函数的具体实现,函数定义如下所示:

代码路径:frameworks/native/libs/binder/ProcessState.cpp

static int open_driver()

    int fd = open("/dev/binder", O_RDWR);                                                          [1]
    if (fd >= 0) 
        fcntl(fd, F_SETFD, FD_CLOEXEC);
        int vers;
        status_t result = ioctl(fd, BINDER_VERSION, &vers);                                        [2]
        ......
        size_t maxThreads = 15;
        result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);                                   [3]
        if (result == -1) 
            ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
        
     else 
        ALOGW("Opening '/dev/binder' failed: %s\\n", strerror(errno));
    
    return fd;

[1] 调用系统调用 open 以读写模式打开 Binder 驱动设备文件 /dev/binder。
[2] 调用系统调用 ioctl 读取 Binder 驱动程序的版本系统,使用的命令是 BINDER_VERSION。
[3] 调用系统调用 ioctl 设置 Binder 驱动程序可以请求进程创建的最大线程数,使用的命令是 BINDER_SET_MAX_THREADS。

通过 ProcessState::self() 得到 ProcessState 实例后,接着调用成员函数 getContextObject 来为 servicemanager 创建一个代理对象。如下所示:

代码路径:frameworks/native/libs/binder/ProcessState.cpp

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)

    return getStrongProxyForHandle(0);

getStrongProxyForHandle 函数定义如下:

代码路径:frameworks/native/libs/binder/ProcessState.cpp

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)

    sp<IBinder> result;

    AutoMutex _l(mLock);

    handle_entry* e = lookupHandleLocked(handle);                                                  [1]

    if (e != NULL) 
        // We need to create a new BpBinder if there isn't currently one, OR we
        // are unable to acquire a weak reference on this current one.  See comment
        // in getWeakProxyForHandle() for more info about this.
        IBinder* b = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) 
            ......

            b = new BpBinder(handle);                                                              [2]
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
         
        ......
    

    return result;

[1] 首先通过 lookupHandleLocked 函数在 ProcessState 类的成员变量 mHandleToObject 中查询是否有参数 handle 对应的代理对象。mHandleToObject 是一个 handle_entry 类型的容器,用于保存进程中所有的 Binder 代理对象,它的定义如下所示:

代码路径:frameworks/native/include/binder/ProcessState.h

class ProcessState : public virtual RefBase

            ......
private:
            struct handle_entry 
                IBinder* binder;
                RefBase::weakref_type* refs;
            ;

            handle_entry*       lookupHandleLocked(int32_t handle);

            Vector<handle_entry>mHandleToObject;
            ......

结构体 handle_entry 有两个成员变量,binder 用于指向 Binder 代理对象,refs 用于指向代理对象内部的一个弱引用计数。mHandleToObject 是一个 handle_entry 类型的 vector 容器,使用句柄值 handle 作为索引值。
[2] 如果不能在 mHandleToObject 中找到句柄值 handle 对应的 Binder 代理对象,那么需要根据句柄值 handle 创建一个新的 Binder 代理对象,并将其保存到 mHandleToObject 容器中。

获得句柄值 0 对应的代理对象 BpBinder 后,回到 defaultServiceManager 函数中,继续下面的封装过程。

3. 将 BpBinder 封装成 BpServiceManager 对象

函数模板 interface_cast<IServiceManager> 将返回的代理对象 BpBinder 封装成 servicemanager 的代理对象 BpServiceManager。实现如下所示:

代码路径:frameworks/native/include/binder/IInterface.h

template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)

    return INTERFACE::asInterface(obj);

IServiceManager 接口的成员函数 asInterface 是通过宏 IMPLEMENT_META_INTERFACE 来定义的,如下所示:

IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");

宏在预编译时会被展开,展开后 asInterface 函数的定义如下所示:

代码路径:frameworks/native/libs/binder/IServiceManager.cpp

android::sp<IServiceManager> IServiceManager::asInterface(
            const android::sp<android::IBinder>& obj)

    android::sp<IServiceManager> intr;
    if (obj != NULL) 
        intr = static_cast<IServiceManager*>(
            obj->queryLocalInterface(IServiceManager::descriptor).get());                          [1]
        if (intr == NULL) 
            intr = new BpServiceManager(obj);                                                      [2]
        
    
    return intr;
  

[1] 参数 obj 为代理对象 BpBinder,调用它的成员函数 queryLocalInterface 返回 NULL。
[2] 为 servicemanager 创建一个代理对象 BpServiceManager,参数为代理对象 BpBinder。BpServiceManager 的构造函数定义如下:

代码路径:frameworks/native/libs/binder/IServiceManager.cpp

BpServiceManager(const sp<IBinder>& impl)
        : BpInterface<IServiceManager>(impl)

BpServiceManager 继承于 BpInterface<IServiceManager> ,这里调用了父类 BpInterface 的构造函数,并将 BpBinder 传入其构造函数。如下所示:

代码路径:frameworks/native/include/binder/IInterface.h

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

在 BpInterface 的构造函数中,再次以传入的代理对象 BpBinder 为参数,调用其父类 BpRefBase 的构造函数。BpRefBase 类的定义如下:

class BpRefBase : public virtual RefBase

protected:
    ......

    inline  IBinder*        remote()                 return mRemote; 
    inline  IBinder*        remote() const           return mRemote; 

private:
                            BpRefBase(const BpRefBase& o);
    BpRefBase&              operator=(const BpRefBase& o);

    IBinder* const          mRemote;
    RefBase::weakref_type*  mRefs;
    volatile int32_t        mState;
;

BpRefBase 类的构造函数定义如下所示:

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

    ......

在构造函数中,最终将代理对象 BpBinder 保存在 BpRefBase 类的私有成员变量 mRemote 中,子类 BpServiceManager 可以通过 remote 函数获得代理对象 BpBinder,然后请求 servicemanager 提供的服务。

至此,defaultServiceManager 函数获取 servicemanager 代理对象的过程分析完成,这个过程涉及到很多 Binder 通信相关的类,以下是类关系图:

参考资料:
1. Android 系统源代码情景分析的第5章 - Binder 进程间通信系统
2. Android 的设计与实现:卷 I 的第5章 - Binder 在 Native 框架层的实现

以上是关于Android笔记 - Binder之servicemanager代理对象的主要内容,如果未能解决你的问题,请参考以下文章

Android笔记 - Binder之请求注册Service组件

Android笔记 - Binder之Client请求Service代理对象

Android笔记 - Binder之Client请求Service代理对象

Android笔记 - Binder之servicemanager代理对象

Android笔记 - Binder之servicemanager代理对象

Android笔记 - Binder之守护进程servicemanager