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代理对象