接著上篇binder簡要介紹(見 http://www.linuxidc.com/Linux/2012-07/66195.htm ),我們來分析binder機制的設計。binder主要框架分為三個部分:服務端,binder驅動,客戶端。
binder在Android最常見的使用場景就是一個程序的activity與系統service進行交互。比如我通過wifi的service來獲取wifi控制代理對象,來對wifi進行相關的操作。注意:這裡的系統service是指System server,而不是sdk 中的Service類。
從Linux空間上來看,Activity,系統service它們都分屬不同的進程,不同進程之間的數據交換就是涉及到了IPC通信。而如果我們從開發者調用角度來看,我們看不到進程的概念。從公共對象請求代理的高度來看Binder,我們會驚異於這種設計思路。Binder相對於Activtiy,service來說是一個很低層的概念。當設計android程序涉及到IPC,我們無需考慮底層的實現細節,而去只關心怎麼去獲取相關服務並通信,這也使我們更專注於軟件的開發,而非傳統基於C/S架構去思考它們之間的數據是如何去實現交換的。
在用戶空間,我們需要做的就是去請求相關有能力的服務對象,不必去了解這個通訊是如何完成。這種設計架構給不僅解決了通訊,引入了一種新的設計理念,也與java面向對象的開發思想契合在一起。這裡,我們看不到binder,我們感覺就像是客戶端直接身服務端請求,然後通過服務端的一個代理對象處理相關工作。Activity與service之間仿佛是一種很直接的,自然的通信。
對於android外部性空間來說,我們不知道服務對象在哪裡,我們只需通過公共代理對象去請求服務。Android系統中,系統級的service都是由serviceManager來管理。借著serviceManger就可以獲取service的對象引用。
先了解下serviceManger,它本身也是一個service,但它管理著系統其它的service。Framework提供了一個系統函數BinderInternal.getContextObject(),可以獲取該Service對應的Binder引用。通過這個靜態函數返回的ServiceManager提供的方法又可以獲取其它系統Service的Binder引用。所以serviceManager是整個系統service的總管,也是系統的一個核心對象,它是開機就自啟動的。其它的service都要向它進行注冊並保管引用,這樣保證所有的服務都可以通過servericeManger獲取到引用。這種設計模式的一個好處就是僅暴露一個Binder引用,而其它的系統服務可以隱藏起來,從而有助於系統服務的擴展,以及調用系統服務的安全檢查 。現在我們來看下serviceManger是怎樣處理service的注冊和查詢的。我先看下serviceManger源碼:
在源碼裡有一個HashMap,HashMap裡保存著系統service的名字,和引用。
private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();
繼續看源碼了解客戶端向服務的請求是怎樣完成的:在客戶端通過ServiceManager類getService(String name)方法傳遞一個需要的服務,然後ServcieManager在sCache的HashMap中去查詢與name對應的service,然後再將這個service的IBinder引用返回給客戶端。