一句话总结 :
ServiceManager 就像学校的"教务处",所有老师(系统服务)在这里登记,学生(应用)找老师时先去教务处查教室号(Binder 引用),然后直接去教室找人!
一、ServiceManager 的核心角色
- 服务注册中心 :所有系统服务(如
ActivityManager
、WindowManager
)启动时在此登记。 - 服务黄页:提供按名称查询服务的功能,返回服务的联系方式(Binder 引用)。
二、查找服务的流程(以学生找老师为例)
1. 教务处登记老师信息(服务注册)
-
系统服务启动时 :如
ActivityManagerService
(AMS)启动后,向 ServiceManager 注册:arduinoServiceManager.addService("activity", amsBinder);
-
ServiceManager 维护的映射表:
服务名 Binder 引用 activity
amsBinder window
wmsBinder power
powerBinder
2. 学生查教务处(应用查询服务)
-
应用调用
getSystemService()
:scss// 示例:获取 ActivityManager ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
-
底层流程:
- 联系 ServiceManager :通过固定 Binder 句柄(如
0
)访问 ServiceManager。 - 按名称查询 :调用
ServiceManager.getService("activity")
。 - 返回 Binder 引用 :拿到
amsBinder
,通过它调用 AMS 的方法(如启动 Activity)。
- 联系 ServiceManager :通过固定 Binder 句柄(如
三、关键细节
1. ServiceManager 的 Binder 句柄
- 固定句柄
0
:所有进程都知道 ServiceManager 的 Binder 句柄是0
,无需动态查找。 - 直接访问 :通过
BinderInternal.getContextObject()
获取 ServiceManager 的 Binder 代理。
2. 权限校验
- 敏感服务限制 :如
location
(定位服务),普通应用无权限时返回null
。 - 系统级校验 :ServiceManager 会检查调用进程的权限(如
Manifest.permission.ACCESS_FINE_LOCATION
)。
3. 缓存优化
- 客户端缓存 :应用首次获取服务后,可能缓存 Binder 引用(如
ActivityManager
单例),避免重复查询。 - 服务端缓存:ServiceManager 内部使用高效数据结构(如哈希表)快速查询。
四、查找流程示意图
scss
应用 → getSystemService("activity")
↓
Binder 调用 ServiceManager(句柄0)
↓
ServiceManager 查表 → 返回 amsBinder
↓
应用通过 amsBinder 调用 AMS 的方法
五、为什么需要 ServiceManager?
- 统一入口:避免每个服务单独管理通信渠道。
- 权限管控:集中校验服务访问权限。
- 跨进程协调:解决服务依赖的"鸡生蛋"问题(如 AMS 启动时需要其他服务)。
六、实际场景:启动 Activity
scss
// 应用代码
startActivity(new Intent(this, MainActivity.class));
// 底层调用链
1. ContextImpl.getSystemService("activity") → 向 ServiceManager 查 AMS
2. 拿到 amsBinder → 调用 AMS 的 startActivity()
3. AMS 处理逻辑 → 通知 ActivityThread 创建新 Activity
七、总结口诀
- 服务启动先登记,ServiceManager 管全局
- 应用查服务按名字,Binder 引用直接取
- 权限不够不给找,缓存优化效率高
- 跨进程通信全靠它,安卓流畅不卡壳!