您的位置:首页 > 移动开发 > Android开发

Android笔记 - Binder之servicemanager代理对象

2016-01-30 09:18 721 查看

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 框架层的实现
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息