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 對象。
持續更新。。。