Android ServiceManager 代理对象的获取

OK, 上章内容学习分析了 ServiceManager 的注册过程. 简单来说分为三个步骤

  • 调用函数 binder_open 打开设备文件 /dev/binder 以及将它映射到本进程的地址空间.
  • 调用函数 binder_become_context_manager 将自己注册为所有服务的大管家.
  • 调用函数 binder_loop 等待和处理 Client 进程的通信请求. 如果没有进程间通信请求的话就再 binder_thread_read 函数中休眠.

本章内容主要学习分析 SM 代理对象的获取流程.

前言

Service 组件在启动前, 需要将自己注册到 SM 中, 而 Client 组件在使用 Service 组件提供的服务之前, 也需要通过 SM 来获得 Service 组件的代理对象. 由于 SM 自己本身也是一个 Service 组件, 因此, 其他 Service 组件和 Client 组件在使用它提供的服务之前, 也需要先获得它的代理对象.

SM 代理对象的类型为 BpServiceManager, 用来描述一个实现了 IServiceManager 接口的Client 组件.
IServiceManager 接口定义了4 个成员函数

  • getService
  • checkService
  • addService
  • listService

其中 getServicecheckService 用来获取 Service 组件的代理对象.
addService 用来注册 Service 组件. listService 用来获取注册在 SM 中的组件名称列表.

对于一般的 Service 组件来说, Client 进程首先要通过 Binder 驱动程序来获得它的一个句柄值, 然后才可以根据这个句柄创建一个 Binder 代理对象. 最后将这个 Binder 代理对象封装成一个实现了特定接口的代理对象. 由于 SM 的句柄值恒为 0, 因此, 获取 SM 代理对象的过程就省去与 Binder 驱动程序交互的过程.

Android 系统在应用程序框架的 Binder 库中提供了一个函数 defaultServiceManager 来获得一个 SM 代理对象. 下面开始进入源码.

1. defaultServiceManager

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

sp<IServiceManager> defaultServiceManager()
{
01    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;    
    {
        AutoMutex _l(gDefaultServiceManagerLock);
        while (gDefaultServiceManager == NULL) {
02            gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));
              if (gDefaultServiceManager == NULL)
                sleep(1);
        }
    }
03    return gDefaultServiceManager;
}

分析之前, 先看两个全局变量. 位于/frameworks/native/libs/binder/Static.cpp

sp<IServiceManager> gDefaultServiceManager;;
Mutex gDefaultServiceManagerLock;

全局变量 gDefaultServiceManager 是一个类型为 IServiceManager 的强指针, 指向进程内的一个 BpServiceManager 对象, 即一个 SM 代理对象.

全局变量 gDefaultServiceManagerLock 是一个互斥锁, 是用来保证一个进程至多只有一个 SM 代理对象的. 结合锁机制来保证对象在进程中的唯一性.

在 01 行处先检查全局变量 gDefaultServiceManager 是否为 NULL, 如果不为 NULL, 说明 Binder 库已经为此进程创建过一个 SM 的代理对象了, 因此会直接将这个代理对象返回给调用者. 否则就会在第 02 行创建一个 SM 代理对象. 并且保存在全局变量 gDefaultServiceManager 中. 然后在第 03 行返回给调用者.

在 02 行代码包含了三次函数调用, 分别是.

  • 先调用 ProcessState 类的静态成员函数 self 获得进程内的一个 ProcessState 对象.
  • 接着调用上面获得 ProcessState 对象的的成员函数 getContextObject 创建一个 Binder 代理对象.
  • 最后调用模板函数 interface_cast<IServiceManager> 将上一步创建的 Binder 代理对象封装成一个 SM 代理对象.

OK, 那么下面分别分析这三个函数.

2. ProcessState::self()

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

sp<ProcessState> ProcessState::self()
{
    ...
     if (gProcess != NULL) {
        return gProcess;
    }
    gProcess = new ProcessState;
    return gProcess;
}

代码较为简单, 先是判断全局变量 gProcess 是否为 NULL, 如果是, 说明 Binder 库已经为其创建了一个 ProcessState 了. 直接返回给调用者. 否者就创建一个 ProcessState 对象.并且保存在全局变量 gProcessState 中. 最后返回给调用者.
因为按之前说的, 第一次创建代理对象, 所以这里 gProcess 是为 NULL 的, 所以进入到 ProcessState 的构造函数, 看它的创建过程.

3. ProcessState

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

ProcessState::ProcessState()
01  : mDriverFD(open_driver())
      , mVMStart(MAP_FAILED)  
      ...
{
    if (mDriverFD >= 0) {
        ...
02        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        ... 
    }
   ...
}

在第01 行代码中先调用了函数 open_driver() 打开设备文件 /dev/binder, 并将得到的文件描述符保存在成员变量 mDriverFD 中. 然后在第 02 行代码调用函数 mmap 将设备文件映射到进程的地址空间. 大小为 BINDER_VM_SIZE, 也就是 1M - 8K.
OK. 现在继续看 open_driver 函数

4. open_driver

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

static int open_driver()
{
01    int fd = open("/dev/binder", O_RDWR);
      if (fd >= 0) {
         ...
02       size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
03       result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
         ...
      }else {
         ...
      }
      return fd;
}

在 01 行代码处调用函数 open 打开设备文件 /dev/binder.
在 02 行代码 DEFAULT_MAX_BINDER_THREADS 值为 15.
在 03 行代码处通过 ioct 控制命令 BINDER_SET_MAX_THREADS 来通知 Binder 驱动程序它最多可以请求创建 15 个Binder 线程来处理进程间通信.

创建了 ProcessState 对象后, 返回到第 1 步 defaultServiceManager 函数中. 调用它的成员函数 getContextObject. 来创建一个 Binder 代理对象.

5. getContextObject 创建 SM 的 Binder 代理对象

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

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

内部又调用了成员函数 getStrongProxyForHandle, 传入的句柄为 0.

6. getStrongProxyForHandle 真正的创建 SM 的 Binder 代理对象

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

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    ...
01    handle_entry* e = lookupHandleLocked(handle);

    if (e != NULL) {
        IBinder* b = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            if (handle == 0) {
                Parcel data;
                status_t status = IPCThreadState::self()->transact(
                        0, IBinder::PING_TRANSACTION, data, NULL, 0);
                if (status == DEAD_OBJECT)
                   return NULL;
            }

            b = new BpBinder(handle); 
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    return result;
}

通过上一步调用可知参数 handle 的值为 0. 这里先说一下 01 行代码处的 handle_entry.

Binder 库为每一个进程维护了一个 handle_entry 类型的 Binder 代理对象列表, 它以句柄作为关键字来维护进程内部所有的 Binder 代理对象. 这个 Binder 代理对象列表保存在 ProcessState 类的成员变量 mHandleToObject 中. 定义如下
源码路径: /frameworks/native/include/binder/ProcessState.h

struct handle_entry {
   IBinder* binder;
   RefBase::weakref_type* refs;
};
...
Vector<handle_entry>mHandleToObject;

每一个 Binder 代理对象都使用一个 handle_entry 的结构体来描述. handle_entry 的两个成员变量 binderrefs 分别指向一个 Binder 代理对象以及它内部的一个弱引用计数对象.

一个 Binder 代理对象的句柄值同时也是它在列表 mHandleToObject 中的索引值.

OK, 接着回到 getStrongProxyForHandle 函数.
在第 01 行代码处 调用 lookupHandleLocked 函数.来检查成员变量 mHandleToObject 中是否已经存在一个与句柄值 handle 对应的 handle_entry 结构体. 现在进入到这个函数内.

6.1 lookupHandleLocked 检查是否已经存在与句柄值对应的 handle_entry 结构体

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

ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
{
    const size_t N=mHandleToObject.size();
    if (N <= (size_t)handle) {
        handle_entry e;
        e.binder = NULL;
        e.refs = NULL;
        status_t err = mHandleToObject.insertAt(e, N, handle+1-N);
        if (err < NO_ERROR) return NULL;
    }
    return &mHandleToObject.editItemAt(handle);
}

在函数中先来检查句柄值 handle 的值是否大于或者等于列表 mHandleToObject 的大小. 如果是, 则命中 if. 说明 mHandleToObject 列表里不存在一个与句柄值 handle 相对应的 handle_entry 结构体. 那么 if 内的几行代码就会在列表 mHandleToObject 中插入一个 handle_entry 结构体. 在最后就可以将与句柄值 handle 对应的 handle_entry 结构体返回给调用者.

注: 这些插入的 handle_entry 结构体还未与 Binder 代理对象关联起来. 因此它们的成员变量 binderrefs 都还是 NULL.

接着回到第 6 步. 为了方便代码直接贴到这里

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    ...
01    handle_entry* e = lookupHandleLocked(handle);

    if (e != NULL) {
        IBinder* b = e->binder;
02        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            if (handle == 0) {
                Parcel data;
03              status_t status = IPCThreadState::self()->transact(0, IBinder::PING_TRANSACTION, data, NULL, 0);
                if (status == DEAD_OBJECT)
                   return NULL;
            }

04          b = new BpBinder(handle); 
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
05            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    return result;
}

01 行代码已经分析完了, 将从 Binder 代理对象列表中获得的 handle_entry 结构体保存在变量 e 中.

02 代码处判断 handlle_entry 结构体的成员变量 binder 值是否为 NULL, 如果为 NULL, 说明尚未为句柄值 handle 创建过 Binder 代理对象. 那么久会在 03 代码处创建 Binder 代理对象. 如果不为 NULL, 既它已经指向了一个 Binder 代理对象, 则需要调用 attemptIncWeak 函数检查这个代理对象是否还存活着.

03 代码处通过 PING_TRANSACTION 命令测试 Binder 是否准备就绪.

04 行代码处就开始根据句柄值 handle 创建 Binder 代理对象, 并将其保存在 handle_entry 结构体 e 的成员变量 binder 中.

05 行代码说明进程中已经有一个 Binder 代理对象与句柄值 handle 相对应, 并且这个 Binder 代理对象是有效的. 直接返回给调用者.

最终返回了 Binder 的代理对象.

自此在第 1 步 defaultServiceManager 函数内 ProcessState::self()->getContextObject(NULL) 分析完了, 成功返回了 Binder 代理对象. 那继续回到 defaultServiceManager 向下执行在 02行调用模板函数 interface_cast<IServiceManager> 将这个Binder 代理对象封装称为一个 ServiceManager 代理对象. 这里也直接贴出第 1 步代码

sp<IServiceManager> defaultServiceManager()
{
01    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;    
    {
        AutoMutex _l(gDefaultServiceManagerLock);
        while (gDefaultServiceManager == NULL) {
02            gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));
              if (gDefaultServiceManager == NULL)
                sleep(1);
        }
    }
03    return gDefaultServiceManager;
}

7. interface_cast<IServiceManager> 将 Binder 代理对象封装为 SM 代理对象

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

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

这里的 INTERFACE 可以简单的理解为泛型, 上面传入的是 IServiceManager, 因此它实际上调用的是 IServiceManager 接口的成员函数 asInterface, 将一个句柄值为 0 的 Binder 代理对象封装为一个 SM 对象.

对于 asInterface 函数, 通过在 IServiceManager 搜索代码, 发现根本找不到这个函数在哪里定义的, 其实这个函数是通过宏来定义的.
源码路径: /frameworks/native/libs/binder/IServiceManager.cpp

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

展开前定义如下
源码路径:/frameworks/native/include/binder/IInterface.h

#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 != NULL) {                                              \
            intr = static_cast<I##INTERFACE*>(                          \
                obj->queryLocalInterface(                               \
                        I##INTERFACE::descriptor).get());               \
            if (intr == NULL) {                                         \
                intr = new Bp##INTERFACE(obj);                          \
            }                                                           \
        }                                                               \
        return intr;                                                    \
    }
    I##INTERFACE::I##INTERFACE() { }                                    \
    I##INTERFACE::~I##INTERFACE() { }                                         

展开可以理解为 将##INTERFACEname. 替换为传入的参数. 展开后如下

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());               
            if (intr == NULL) {                                         
                intr = new BpServiceManager(obj);                          
            }                                                           
        }                                                               
        return intr;                                                    
    }
    IServiceManager::IServiceManager() { }                                    
    IServiceManager::~IServiceManager() { }       

前面可知参数 obj 指向一个 Binder 代理对象, 既一个 BpBinder 对象. 它的成员函数 queryLocalInterface 返回为 NULL,. 因此会执行 intr = new BpServiceManager(obj); 也就是创建一个 SM 的代理对象. 其实也就是 BpServiceManager 对象. 返回给调用者.

到这里, SM 代理对象的获取流程就分析学习完了.
有了这个 SM 代理对象之后, Service 组件就可以在启动的过程中使用它的成员函数 addService 将自己注册到 SM 中.
而 Client 组件就可以使用它的成员函数 getService 来获得一个指定名称的 Service 组件的代理对象了.

下一章将继续学习分析 Service 组件是如何将自己注册到 SM 中的.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章