【Android基础回顾】四:ServiceManager
Android 中的 ServerManager 是 Android 框架中一个用于管理系统服务的核心机制。它是 Binder IPC 的一部分,用于在客户端和服务端之间建立联系,广泛应用于系统服务(如 ActivityManager、WindowManager 等)的注册与获取。
1 ServiceManager职责是什么?有什么用?
ServiceManager 是 Android 系统中一个特殊的 Binder 服务,其职责主要是:
服务注册(addService)
服务查找(getService、checkService)
服务列举(listServices)
它是所有系统服务的“目录服务”,作用类似一个全局的“服务注册表”。
2 ServiceManager的关键模块有哪些?
2.1 ServiceManager 本身(Native C++)
位于 frameworks/native/cmds/servicemanager/,其本质是一个 Binder 服务,负责接收请求(添加、查找服务)并处理。
int main() {sp<ServiceManager> sm = new ServiceManager(); // 实例化sm->addService(...); // 注册服务...IPCThreadState::self()->joinThreadPool(); // 进入 Binder 循环
}
2.2 IServiceManager 接口
是客户端与服务端交互的 Binder 接口定义,定义了如下方法:
addService(name, service)
getService(name)
checkService(name)
listServices()
2.3 defaultServiceManager()(C++)
客户端通过该方法获取 ServiceManager 的代理对象。
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("activity"));
2.4 Java 层封装
Java 层通过 android.os.ServiceManager 访问 native 的 ServiceManager:
IBinder binder = ServiceManager.getService("activity");
内部通过 JNI 调用 native 层 BinderInternal.getContextObject() 获得 binder 代理。
3 注册与获取服务流程
3.1 注册服务(addService)
系统服务启动时调用 ServiceManager.addService(name, binder)
binder 驱动将请求转发给 native 的 ServiceManager
ServiceManager 保存服务到本地表中(map)
3.2 获取服务(getService)
客户端调用 ServiceManager.getService(name)
binder 驱动将请求传给 native ServiceManager
查找到对应 binder 实例返回。
Q&A
怎么理解“ServiceManager 是 Android 系统中一个特殊的 Binder 服务”?
这里面有两个关键词。
一是binder服务,Binder 是 Android 的核心 IPC(进程间通信)机制。在 Binder 架构中,“服务” 是一个实现了 Binder 接口的对象(IBinder),可以被其他进程远程调用。每个服务都通过 Binder 驱动注册到内核,并能被其他进程通过 Binder 通信访问。
二是“特殊”,特殊性在哪?ServiceManager 就是一个这样的 Binder 服务对象,但它比一般服务更特殊。原因如下:
- 它是 Binder 世界的“入口”
所有系统服务(如 ActivityManager、WindowManager 等)在启动后都先注册到 ServiceManager 中。
客户端想用这些服务时,必须通过 ServiceManager 查询到对应的 Binder 接口。👉 它充当了一个“Binder 服务注册与发现中心”(相当于服务注册表)。 - 由系统早期启动并驻留内存。它在 init 进程阶段由 native 层以独立可执行程序的形式(servicemanager)启动。启动时会进入一个 Binder 循环线程池,不断处理其他进程通过 Binder 发来的服务注册/查询请求。
- 权限控制 & 本地注册表,仅系统进程才能注册服务,防止恶意进程篡改系统服务。ServiceManager 会维护一个本地服务表(map),键是服务名,值是对应的 IBinder 实现。
普通的client进程和service进程想要通过AIDL通讯,需要注册到ServiceManager吗?
这里有两种场景,先说第一种,系统服务场景(系统进程 + 普通 app)。
比如我们想通过 AIDL 访问 ActivityManager、WindowManager,这些系统服务会在系统启动时通过 ServiceManager.addService() 注册自己。
普通 App 调用 ServiceManager.getService(“activity”),获得其 Binder 接口。
系统服务在系统启动的时候会注册到 ServiceManager,这是它们能被系统和 app 找到的前提。
第二种场景,自定义服务场景(普通 App 进程 + 普通 App 进程)。
我们自己写一个 AIDL 服务并运行在一个 Service 中,想让其他 App 调用它:这种情况不需要也无法使用ServiceManager注册我们自己的服务,因为ServiceManager 是系统服务,不对第三方应用开放 addService() 权限。通常用 绑定服务(bindService) 的方式建立连接。
流程是这样的,服务端在 AndroidManifest.xml 中声明一个 Service,并实现 AIDL 接口。
客户端通过 Intent(带包名和 Service 类名)调用 bindService()。系统通过 AMS(ActivityManagerService)管理服务绑定,并将 Binder 对象通过回调传给客户端(onServiceConnected())。
所以这种场景下,不是通过 ServiceManager 查找,而是通过 AMS 的服务绑定机制传递 Binder 对象。
持续更新。。。