ServiceManager 分为三部分:framework 中的 java 层和 c++层和系统服务 c 层。我们可以认为这是 service manager 的服务端和客户端。这个设计也是一个典型的 binder C/S 结构。
Java(framework)层
这张类图,我们从左往右看。
ServiceManager.java是 framework 可以直接拿到的对象,目前对于 app 层是不能拿到的(但也是使用到了的,例如:Context.getSystemService(),是通过 ContextImpl -> SystemServiceRegistry -> 在注册方法中 new 出各种 Service 的 Java 端对象,或者说引用。然后在使用这个些对象中的方法时,就会调用到 ServiceManager)。
ServiceManager.java 的主要职责是:提供获取服务、检查服务、发布服务等方法(不包含具体的获取等 action 的实现,但保存了一份副本 sCache,缓存常用的服务。)给 framework 使用。
IServiceManager.java是 ServiceManager.java 持有的引用。它提供了 ServiceManager.java 所需要的功能的具体实现的抽象。
ServiceManagerNative.java继承于 Binder.java,同时实现了 IServiceManager。源码中,它与 aidl 生成的类非常相似。所以它的职责是服务端的代理。这个类中的
mRemote对象就是ServiceManager.java#getIServiceManager()中的 BinderInternal#getContextObject()对象。可以认为,ServiceManagerNative.java 就是为了和系统的 service manager 进程通信而构建的代理。
Native - C++层
源码路径:frameworks/native/libs/binder/
主要包含:IServiceManager.h、IServiceManager.cpp、ProcessState.cpp
IServiceManager.h 继承与 IInterface.h,因此具有 asInterface 和 onAsBinder 等方法,另外还有一些模板类,例如:
template<typename INTERFACE> inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj) { return INTERFACE::asInterface(obj); }
IServiceManager.h 还定义了**defaultServiceManager()**和 getService 等方法。
IServiceManager.cpp 实现了 defaultServiceManager(),并从 ProcessState 中获取到 gDefaultServiceManager 的引用,是一个 BpBinder 对象,然后通过
interface_cast转换为 IServiceManager.cpp 中定义的 BpServiceManager 对象。而 BpServiceManager 是继承 BpInterface,其中包含了一个 remote 对象(目前可以理解为 c 层的 service_manager),因而 BpServiceManager 具有了远程通信的能力。进而去调用 getService 等方法。ProcessState.cpp 是 Binder C++层重要的内容,对于 Service Manager 而言,它是注册 C++ 层 context object 的入口和实现的位置。它还是 IPCThreadState 的持有者,负责开启线程池等操作。由于这里主要是 Service Manager 的内容,就不对 Binder 实现进行展开。
Native - C 层
service manager 系统服务更简单了。关键类只有两个:service_manager.c 和 binder.c。它们的源码路径为:frameworks/native/cmds/servicemanager/
service_manager.c 在系统启动时由 rc 脚本拉起。进而在 c 文件的main()方法中(通过 ioctl 下沉到内核空间)注册自己为 context object 到 binder 驱动中。同时 service_manager.c 中维护了一个 svc_list 的链表,用于保存 service 的信息。
我话讲完。
等等,上面只讲了 service manager 的结构,并没有讲它是怎么工作的呀!
好的,我们来视察一下 service manager 的工作内容吧。
Service Manager 的工作过程
故事不长,请听我慢慢道来。
说在高三《四》班,数学老师叫小元,刚开学的时候他想选一个课代表。于是小俊同学就举手了,说我想做这个课代表。然后数学老师就问了,你为什么想做课代表啊?你能做些什么事呢?小俊说,我可以帮老师检查作业呀。我有一个专门的小本本(svclist)可以记住每个同学的名字(svcinfo),另外,我有个小弟(Java 层 sm)每天和同学们混在一起,可以很方便的收集同学们的意见(cmd),然后他会把意见(通过 binder 机制)放到我座位上[这个过程后续在 binder 驱动中详细分析],然后我可以一直(binder_loop)帮老师分类处理这些内容(svcmgr_handler)。
闲话少说,RTFSC!
我们从系统服务 service_manager.c 开始,看看这个狗腿子背着我们都干了些啥。
- 主函数
int main(int argc, char** argv)
{
struct binder_state *bs;
union selinux_callback cb; // 暂时不明觉厉
char *driver;
if (argc > 1) {
driver = argv[1];
} else {
driver = "/dev/binder";
}
bs = binder_open(driver, 128*1024); // 1. 打开驱动设备
if (!bs) {
//...
if (binder_become_context_manager(bs)) { // 2. 将自己注册成 context manager object(就是课代表)
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
//...
binder_loop(bs, svcmgr_handler); // 只要干不死,就往死里干。注意:第二个参数svcmgr_handler传递的是一个函数。
return 0;
}
service_manager 在启动后就开启了无限循环,读取消息。这一步有点类似于 ActivityThread 在启动后就开启了 Looper.loop()。
- svcmgr_handler
int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data_secctx *txn_secctx,
struct binder_io *msg,
struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
size_t len;
uint32_t handle;
uint32_t strict_policy;
int allow_isolated;
uint32_t dumpsys_priority;
struct binder_transaction_data *txn = &txn_secctx->transaction_data;
//ALOGI("target=%p code=%d pid=%d uid=%d\n",
// (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
if (txn->target.ptr != BINDER_SERVICE_MANAGER)
return -1;
if (txn->code == PING_TRANSACTION)
return 0;
//...
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE: // 获取服务的引用
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid,
(const char*) txn_secctx->secctx);
if (!handle)
break;
bio_put_ref(reply, handle);
return 0;
case SVC_MGR_ADD_SERVICE: // 添加服务
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
handle = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
dumpsys_priority = bio_get_uint32(msg);
if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,
txn->sender_pid, (const char*) txn_secctx->secctx))
return -1;
break;
case SVC_MGR_LIST_SERVICES: {
uint32_t n = bio_get_uint32(msg);
uint32_t req_dumpsys_priority = bio_get_uint32(msg);
if (!svc_can_list(txn->sender_pid, (const char*) txn_secctx->secctx, txn->sender_euid)) {
ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
txn->sender_euid);
return -1;
}
si = svclist;
// walk through the list of services n times skipping services that
// do not support the requested priority
while (si) {
if (si->dumpsys_priority & req_dumpsys_priority) {
if (n == 0) break;
n--;
}
si = si->next;
}
if (si) {
bio_put_string16(reply, si->name);
return 0;
}
return -1;
}
default:
ALOGE("unknown code %d\n", txn->code);
return -1;
}
bio_put_uint32(reply, 0);
return 0;
}
主要是 case 分发,我们看一个具体的 case:SVC_MGR_ADD_SERVICE添加服务。
int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle,
uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid, const char* sid) {
struct svcinfo *si;
//ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
// allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
if (!handle || (len == 0) || (len > 127))
return -1;
if (!svc_can_register(s, len, spid, sid, uid)) {
ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
str8(s, len), handle, uid);
return -1;
}
si = find_svc(s, len);
if (si) {
if (si->handle) {
ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
str8(s, len), handle, uid);
svcinfo_death(bs, si);
}
si->handle = handle;
} else {
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
if (!si) {
ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
str8(s, len), handle, uid);
return -1;
}
si->handle = handle;
si->len = len;
memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
si->name[len] = '\0';
si->death.func = (void*) svcinfo_death;
si->death.ptr = si;
si->allow_isolated = allow_isolated;
si->dumpsys_priority = dumpsys_priority;
si->next = svclist;
svclist = si;
}
binder_acquire(bs, handle);
binder_link_to_death(bs, handle, &si->death);
return 0;
}
看吧,没什么难的。主要就是先查找一次,是不是已经添加过了。然后没有添加过把服务信息登记到小本本(svclist)上。
总结
本次的 service manager 主要是做一个整体性的理解。有很多细节可以展开讨论的。如 Java 层的 service manager 是怎么与 native 建立关系的(其实很明显是通过 Binder 机制)。从 c++层利用 context object 进行关联,传递到 c 层。