文章目录
前言
一、注册 Binder 服务
二、service_manager.c | do_add_service
三、service_manager.c | svc_can_register
四、service_manager.c | find_svc
五、service_manager.c | svcinfo_death
前言
在上一篇博客 【Binder 机制】Native 层 Binder 机制分析 ( binder_loop | svcmgr_handler | binder.c | binder_parse ) 中 , 简单介绍了 在 service_manager.c 中的 main 函数中调用了 binder_loop 方法 , 在 binder_loop 方法中 , 传入了 svcmgr_handler 方法作为回调函数 , svcmgr_handler 中可以接收不同的消息 , 处理不同的业务 ;
一、注册 Binder 服务
参考 【Binder 机制】Native 层 Binder 机制分析 ( binder_loop | svcmgr_handler | binder.c | binder_parse ) 二、binder_loop 方法参数 svcmgr_handler 章节 ;
在 svcmgr_handler 方法中 , 添加服务 , 需要执行如下逻辑 : 接收到 SVC_MGR_ADD_SERVICE 消息 , 添加 Binder 服务 , 主要调用 do_add_service 方法 ;
i
nt svcmgr_handler(struct binder_state *bs, struct binder_transaction_data *txn, struct binder_io *msg, struct binder_io *reply) { // 链表 struct svcinfo *si; // 根据不同的 txn->code 执行不同的方法 switch(txn->code) { case SVC_MGR_ADD_SERVICE:// 收到消息 , 添加一个 Binder 服务 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)) return -1; break; } return 0; }
完整代码参考 /frameworks/native/cmds/servicemanager/service_manager.c
二、service_manager.c | do_add_service
do_add_service 中进行如下操作 :
首先 , 进行权限检测 , 检测是否有权限注册 Service , 调用 svc_can_register 方法实现 ;
然后 , 调用 find_svc 方法 , 查找 Service ;
查找到服务 , 服务不为空 , 说明之前注册过该服务 , 则先释放服务 ;
查找到服务为空 , 则为服务分配内存空间 , 创建服务 , 并挂载到 svclist 列表中 ;
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) { struct svcinfo *si; if (!handle || (len == 0) || (len > 127)) return -1; // 权限检测 : 检测是否有权限注册 Service if (!svc_can_register(s, len, spid, uid)) { ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n", str8(s, len), handle, uid); // 权限检测失败直接返回 return -1; }// 权限检测通过 // 查找 Service 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 挂载到 svclist 链表中 si->next = svclist; svclist = si; } binder_acquire(bs, handle); binder_link_to_death(bs, handle, &si->death); return 0; }
完整代码参考 /frameworks/native/cmds/servicemanager/service_manager.c
三、service_manager.c | svc_can_register
权限检测 , 是否可以注册服务 ;
static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid) { const char *perm = "add"; if (multiuser_get_app_id(uid) >= AID_APP) { return 0; /* Don't allow apps to register services */ } return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0; }
完整代码参考 /frameworks/native/cmds/servicemanager/service_manager.c
四、service_manager.c | find_svc
find_svc 查找服务方法 , 从 svclist 链表中寻找匹配 Service ; 所有的服务都存在该链表中 ;
struct svcinfo *svclist = NULL; struct svcinfo *find_svc(const uint16_t *s16, size_t len) { struct svcinfo *si; for (si = svclist; si; si = si->next) { // 先匹配长度是否一样 if ((len == si->len) && // 然后匹配名字是否一样 !memcmp(s16, si->name, len * sizeof(uint16_t))) { // 如果查找到对应服务 , 返回该服务 return si; } } // 如果没有找到服务 , 则返回空 return NULL; }
完整代码参考 /frameworks/native/cmds/servicemanager/service_manager.c
五、service_manager.c | svcinfo_death
查找服务 , 服务不为空时 , 调用 svcinfo_death 方法 , 该方法中调用 binder_release 方法释放 Binder ;
void svcinfo_death(struct binder_state *bs, void *ptr) { struct svcinfo *si = (struct svcinfo* ) ptr; ALOGI("service '%s' died\n", str8(si->name, si->len)); if (si->handle) { // 如果之前注册过 Binder , 先释放 Binder binder_release(bs, si->handle); si->handle = 0; } }
完整代码参考 /frameworks/native/cmds/servicemanager/service_manager.c