一句话总结 :
ServiceManager 注册服务就像"公司前台登记部门信息",新部门(系统服务)开张后必须到前台登记名字和工位号(Binder 引用),其他人要找部门办事时直接问前台查位置!
一、服务注册的流程拆解
1. 系统服务启动(新部门成立)
-
例子 :
ActivityManagerService(人事部)启动时,需要告诉全公司(系统)自己的存在。 -
关键代码:
ini// SystemServer 中启动 AMS 并注册 ActivityManagerService ams = new ActivityManagerService(); ServiceManager.addService("activity", ams);
2. 联系 ServiceManager(到前台登记)
- Binder 通信 :通过 Android 的
Binder机制,向 ServiceManager 发送注册请求。 - 固定句柄
0:ServiceManager 的 Binder 句柄固定为0,所有服务都知道这个"前台电话"。
3. 登记服务信息(填写登记表)
- 服务名 :唯一标识符(如
activity、window),相当于部门名称。 - Binder 引用:服务的联系方式,相当于工位号或分机号。
- 权限校验:ServiceManager 会检查调用者是否有权限注册(防止恶意服务冒充)。
二、ServiceManager 如何处理注册请求?
1. 接收请求(前台接电话)
- 监听 Binder 请求:ServiceManager 启动后进入循环,等待其他服务的注册或查询请求。
- 解析请求类型 :区分是注册服务(
addService)还是查询服务(getService)。
2. 存储服务信息(更新通讯录)
-
内部存储结构 :使用哈希表(
Map<String, IBinder>)保存服务名和 Binder 引用。arduino// ServiceManager 的注册逻辑(C 层简化版) void do_add_service(struct binder_state *bs, const char *name, IBinder *binder) { // 1. 检查权限 if (!check_permission()) return; // 2. 插入哈希表 hashmap_put(service_map, name, binder); }
3. 权限控制(防冒名顶替)
- 系统级服务 :只有
SystemServer、Zygote等高权限进程可以注册核心服务(如activity、power)。 - 普通应用:无法注册系统服务,防止恶意应用注入假服务。
三、为什么必须注册到 ServiceManager?
- 统一管理:所有服务集中登记,避免散落各处难以协调。
- 跨进程通信:其他组件(App 或其他服务)需要通过 ServiceManager 查找服务地址(Binder 引用)。
- 权限隔离 :防止未授权的服务干扰系统运行(如恶意应用注册假
power服务控制电量)。
四、实际场景:ActivityManagerService 的注册
1. 启动阶段
-
SystemServer 启动时创建
ActivityManagerService实例。 -
调用注册方法:
ini// SystemServer.java ActivityManagerService ams = new ActivityManagerService(); ServiceManager.addService(Context.ACTIVITY_SERVICE, ams);
2. ServiceManager 的响应
- 检查权限 :确认调用者
SystemServer有权限注册activity服务。 - 存储到哈希表 :记录
"activity" → amsBinder。
3. 应用查询服务
-
当 App 调用
getSystemService(Context.ACTIVITY_SERVICE)时:- 向 ServiceManager 查询
"activity"。 - 拿到
amsBinder,通过 Binder 调用 AMS 的方法(如启动 Activity)。
- 向 ServiceManager 查询
五、总结:注册服务的意义
- 核心服务的"身份证" :没有登记的服务,其他组件无法找到和调用。
- 系统安全的基石:权限控制防止恶意服务破坏系统。
- 跨进程协作的桥梁:Binder 通信依赖 ServiceManager 维护的全局服务表。
口诀:
- 服务启动先报到,ServiceManager 来登记
- 名字 Binder 不能少,权限检查防冒充
- 查服务像查黄页,安卓稳定靠协作!