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
其中 getService
与 checkService
用来获取 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 defaultServiceManager()
{
01 if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
02 gDefaultServiceManager = interface_cast(ProcessState::self()->getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep(1);
}
}
03 return gDefaultServiceManager;
}
分析之前, 先看两个全局变量. 位于/frameworks/native/libs/binder/Static.cpp
sp 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
将上一步创建的 Binder 代理对象封装成一个 SM 代理对象.
OK, 那么下面分别分析这三个函数.
2. ProcessState::self()
源码路径: /frameworks/native/libs/binder/ProcessState.cpp
sp 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 ProcessState::getContextObject(const sp& /*caller*/)
{
return getStrongProxyForHandle(0);
}
内部又调用了成员函数 getStrongProxyForHandle
, 传入的句柄为 0.
6. getStrongProxyForHandle 真正的创建 SM 的 Binder 代理对象
源码路径: /frameworks/native/libs/binder/ProcessState.cpp
sp 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
mHandleToObject; 每一个 Binder 代理对象都使用一个
handle_entry
的结构体来描述.handle_entry
的两个成员变量binder
与refs
分别指向一个 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 代理对象关联起来. 因此它们的成员变量binder
与refs
都还是 NULL.
接着回到第 6 步. 为了方便代码直接贴到这里
sp 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
将这个Binder 代理对象封装称为一个 ServiceManager 代理对象. 这里也直接贴出第 1 步代码
sp defaultServiceManager()
{
01 if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
02 gDefaultServiceManager = interface_cast(ProcessState::self()->getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep(1);
}
}
03 return gDefaultServiceManager;
}
7. interface_cast 将 Binder 代理对象封装为 SM 代理对象
源码路径: /frameworks/native/include/binder/IInterface.h
template
inline sp interface_cast(const sp& 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::asInterface( \
const android::sp& obj) \
{ \
android::sp intr; \
if (obj != NULL) { \
intr = static_cast( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == NULL) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
}
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { }
展开可以理解为 将##INTERFACE
与 name
. 替换为传入的参数. 展开后如下
android::sp IServiceManager::asInterface( const android::sp& obj)
{
android::sp intr;
if (obj != NULL) {
intr = static_cast(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 中的.