You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

71 lines
3.1 KiB

---
Service 代理对象的获取过程
---
Service 组件将自己注册到 ServiceManager 中之后,它就在 Service 进程中等待 Client 进程将进程间通信请求发送过来。Client 进程为了和运行中 Service 进程中的 Service 组件通信,首先要获得它的一个代理对象,这是通过 ServiceManager 提供的 Service 组件查询服务来实现的。
ServiceManager 代理对象的成员函数 getService 提供了获取一个 Service 组件的代理对象的功能,而 ServiceManager 代理对象可以通过 Binder 库提供的函数 defaultServiceManager 来获得。在调用 ServiceManager 代理对象的成员函数 getService 来获得一个 Service 组件的代理对象时,需要指定这个 Service 组件注册到 ServiceManager 中的名称。
ServiceManager 代理对象的成员函数 getService 的实现如下所示:
```c++
class BpServiceManager : public BpInterface<IServiceManager>
{
virtual sp<IBinder> getService(const String16& name) const
{
unsigned n;
for (n = 0; n < 5; n++) {
sp<IBinder> svc = checkService(name);
if (svc != NULL) return svc;
sleep(1);
}
return NULL;
}
}
```
这个函数最多会尝试五次来获得一个名称为 name 的 Service 组件的代理对象。如果上一次获取失败,就会 sleep 1 秒后重新获取。
ServiceManager 代理对象的成员函数 checkService 的实现如下所示:
```c++
class BpServiceManager : public BpInterface<IServiceManager>
{
virtual sp<IBinder> checkService(const String16& name) const
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
return reply.readStrongBinder();
}
}
```
ServiceManager 是统一在函数 svcmgr_handler 中处理来自 Client 进程的进程间通信请求的,它处理操作代码为 CHECK_SERVICE_TRANSACTION 的进程间通信请求的过程如下所示:
```c++
int svcmgr_handler(struct binder_state *bs, ...) {
struct svcinfo *si;
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
ptr = do_find_service(bs, ...);
}
}
void *do_find_service(struct binder_state *bs, ...)
{
struct svcinfo *si;
si = find_svc(s, len);
if (si && si->ptr) {
return si->ptr;
} else {
return 0;
}
}
```
调用函数 find_svc 来查找与字符串 s 对应的一个 svcinfo 结构体 si,它通过遍历已注册 Service 组件列表 svclist 来查找与字符串 s 对应的一个 svcinfo 结构体,然后返回它的成员变量 ptr。
结构体 svcinfo 的成员变量 ptr 保存的是一个引用了注册到 ServiceManager 中的 Service 组件的 Binder 引用对象的句柄值。当 ServiceManager 将这个句柄值返回给 Binder 驱动程序时,Binder 驱动程序就可以根据它找到相应的 Binder 引用对象,接着找到该 Binder 引用对象所引用的 Binder 实体对象,最后 Binder 驱动程序就可以在请求获取该 Service 组件的代理对象的 Client 进程中创建另一个 Binder 引用对象了。