10.Binder進階:系統服務中的Binder

10.1 Binder與SystemService
    在我們編寫APP程序的時候, 經常會是用getSystemService(  String serviceName ) 這個方法,來獲取一個系統的服務對象。我們查看源碼:
    frameworks/base/core/java/android/app下ContextImpl.java ,可以看到SystemService可以通過在WallpaperManager中獲得到的,而WallpaperManager的initGlobals的構造函數中,則是用ServiceManager.getService( Context.WALLPAPAER_SERVICE) 獲取到一個binder的對象。而看其他的源碼,比如InputMethodManager他是通過單例模式獲取的,如下:
  
 registerService(INPUT_METHOD_SERVICE, new ServiceFetcher() {
                public Object createService(ContextImpl ctx) {
                    return InputMethodManager.getInstance(ctx);
                }});

    而在InputMethodManager.java的getInstance方法中,我們可以看到如下:

   
 /**
     * Internally, the input method manager can't be context-dependent, so
     * we have this here for the places that need it.
     * @hide
     */
    static public InputMethodManager getInstance(Looper mainLooper) {
        synchronized (mInstanceSync) {
            if (mInstance != null) {
                return mInstance;
            }
            IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
            IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
            mInstance = new InputMethodManager(service, mainLooper);
        }
        return mInstance;
    }

可以看到,獲取一個InputMethodManager對象,要先通過ServiceManager獲取一個InputMethod Service的Binder對象b,然後在把這個Binder對象作爲IInputManager.Stub.asInterface()的參數,返回一個InputMethodManager的統一接口,ServiceManager(android.os包下)的getService代碼如下:
  /**
     * Returns a reference to a service with the given name.
     * 
     * @param name the name of the service to get
     * @return a reference to the service, or <code>null</code> if the service doesn't exist
     */
    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return getIServiceManager().getService(name);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }


  
所以說,上面所做的就是先看我們需要的SystemService有沒有在緩存中,沒有的話,就獲取到ServiceManager再獲取。
其中getIServiceManager的代碼如下:

  
  private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }

上面的BinderInternal.getContextObject()方法,返回的是ServiceManager的全局服務代理對象,也就是一個BpBinder對象,方法是原生的方法,具體可以查看android_util_binder.cpp文件。服務會在Framework啓動的時候,創建並且添加的。這個在這邊就先不詳細介紹了。

10.2 詳述Manager
    
    Manager管理的就是服務,並且一個Manager往往管理一個服務,而且Manager更多的時候,調用服務本身的API接口,由於服務都是其他進程,因此,Manager內部使用的是Binder來實現遠程調用,Manager隱藏了服務的實現細節,所以客戶端並不直接通過調用Binder來訪問這些服務,而是調用Manager的方法,所以,我們可以說,Manager將服務的操作、實現細節都封裝了起來。這樣Manager就相當於客戶端通往SystemService的中間件,並使得我們可以靈活、可控地定製API。
   比如說AMS,我們一般不希望用戶直接訪問AMS,而是通過ActivityManager來訪問,而ActivityManager內部提供了一些更具有操作性的數據結構,比如RecentTaskInfo數據類封裝了最近訪問的Task列表,而MemoryInfo數據類封裝了和內存相關的信息。
    下面是Manager訪問遠程服務的模型圖:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章