Android ServiceManager 代理對象的獲取

OK, 上章內容學習分析了 ServiceManager 的註冊過程. 簡單來說分爲三個步驟

  • 調用函數 binder_open 打開設備文件 /dev/binder 以及將它映射到本進程的地址空間.
  • 調用函數 binder_become_context_manager 將自己註冊爲所有服務的大管家.
  • 調用函數 binder_loop 等待和處理 Client 進程的通信請求. 如果沒有進程間通信請求的話就再 binder_thread_read 函數中休眠.

本章內容主要學習分析 SM 代理對象的獲取流程.

前言

Service 組件在啓動前, 需要將自己註冊到 SM 中, 而 Client 組件在使用 Service 組件提供的服務之前, 也需要通過 SM 來獲得 Service 組件的代理對象. 由於 SM 自己本身也是一個 Service 組件, 因此, 其他 Service 組件和 Client 組件在使用它提供的服務之前, 也需要先獲得它的代理對象.

SM 代理對象的類型爲 BpServiceManager, 用來描述一個實現了 IServiceManager 接口的Client 組件.
IServiceManager 接口定義了4 個成員函數

  • getService
  • checkService
  • addService
  • listService

其中 getServicecheckService 用來獲取 Service 組件的代理對象.
addService 用來註冊 Service 組件. listService 用來獲取註冊在 SM 中的組件名稱列表.

對於一般的 Service 組件來說, Client 進程首先要通過 Binder 驅動程序來獲得它的一個句柄值, 然後纔可以根據這個句柄創建一個 Binder 代理對象. 最後將這個 Binder 代理對象封裝成一個實現了特定接口的代理對象. 由於 SM 的句柄值恆爲 0, 因此, 獲取 SM 代理對象的過程就省去與 Binder 驅動程序交互的過程.

Android 系統在應用程序框架的 Binder 庫中提供了一個函數 defaultServiceManager 來獲得一個 SM 代理對象. 下面開始進入源碼.

1. defaultServiceManager

源碼路徑: /frameworks/native/libs/binder/IServiceManager.cpp

sp<IServiceManager> defaultServiceManager()
{
01    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;    
    {
        AutoMutex _l(gDefaultServiceManagerLock);
        while (gDefaultServiceManager == NULL) {
02            gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));
              if (gDefaultServiceManager == NULL)
                sleep(1);
        }
    }
03    return gDefaultServiceManager;
}

分析之前, 先看兩個全局變量. 位於/frameworks/native/libs/binder/Static.cpp

sp<IServiceManager> gDefaultServiceManager;;
Mutex gDefaultServiceManagerLock;

全局變量 gDefaultServiceManager 是一個類型爲 IServiceManager 的強指針, 指向進程內的一個 BpServiceManager 對象, 即一個 SM 代理對象.

全局變量 gDefaultServiceManagerLock 是一個互斥鎖, 是用來保證一個進程至多隻有一個 SM 代理對象的. 結合鎖機制來保證對象在進程中的唯一性.

在 01 行處先檢查全局變量 gDefaultServiceManager 是否爲 NULL, 如果不爲 NULL, 說明 Binder 庫已經爲此進程創建過一個 SM 的代理對象了, 因此會直接將這個代理對象返回給調用者. 否則就會在第 02 行創建一個 SM 代理對象. 並且保存在全局變量 gDefaultServiceManager 中. 然後在第 03 行返回給調用者.

在 02 行代碼包含了三次函數調用, 分別是.

  • 先調用 ProcessState 類的靜態成員函數 self 獲得進程內的一個 ProcessState 對象.
  • 接着調用上面獲得 ProcessState 對象的的成員函數 getContextObject 創建一個 Binder 代理對象.
  • 最後調用模板函數 interface_cast<IServiceManager> 將上一步創建的 Binder 代理對象封裝成一個 SM 代理對象.

OK, 那麼下面分別分析這三個函數.

2. ProcessState::self()

源碼路徑: /frameworks/native/libs/binder/ProcessState.cpp

sp<ProcessState> ProcessState::self()
{
    ...
     if (gProcess != NULL) {
        return gProcess;
    }
    gProcess = new ProcessState;
    return gProcess;
}

代碼較爲簡單, 先是判斷全局變量 gProcess 是否爲 NULL, 如果是, 說明 Binder 庫已經爲其創建了一個 ProcessState 了. 直接返回給調用者. 否者就創建一個 ProcessState 對象.並且保存在全局變量 gProcessState 中. 最後返回給調用者.
因爲按之前說的, 第一次創建代理對象, 所以這裏 gProcess 是爲 NULL 的, 所以進入到 ProcessState 的構造函數, 看它的創建過程.

3. ProcessState

源碼路徑: /frameworks/native/libs/binder/ProcessState.cpp

ProcessState::ProcessState()
01  : mDriverFD(open_driver())
      , mVMStart(MAP_FAILED)  
      ...
{
    if (mDriverFD >= 0) {
        ...
02        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        ... 
    }
   ...
}

在第01 行代碼中先調用了函數 open_driver() 打開設備文件 /dev/binder, 並將得到的文件描述符保存在成員變量 mDriverFD 中. 然後在第 02 行代碼調用函數 mmap 將設備文件映射到進程的地址空間. 大小爲 BINDER_VM_SIZE, 也就是 1M - 8K.
OK. 現在繼續看 open_driver 函數

4. open_driver

源碼路徑: /frameworks/native/libs/binder/ProcessState.cpp

static int open_driver()
{
01    int fd = open("/dev/binder", O_RDWR);
      if (fd >= 0) {
         ...
02       size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
03       result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
         ...
      }else {
         ...
      }
      return fd;
}

在 01 行代碼處調用函數 open 打開設備文件 /dev/binder.
在 02 行代碼 DEFAULT_MAX_BINDER_THREADS 值爲 15.
在 03 行代碼處通過 ioct 控制命令 BINDER_SET_MAX_THREADS 來通知 Binder 驅動程序它最多可以請求創建 15 個Binder 線程來處理進程間通信.

創建了 ProcessState 對象後, 返回到第 1 步 defaultServiceManager 函數中. 調用它的成員函數 getContextObject. 來創建一個 Binder 代理對象.

5. getContextObject 創建 SM 的 Binder 代理對象

源碼路徑: /frameworks/native/libs/binder/ProcessState.cpp

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    return getStrongProxyForHandle(0);
}

內部又調用了成員函數 getStrongProxyForHandle, 傳入的句柄爲 0.

6. getStrongProxyForHandle 真正的創建 SM 的 Binder 代理對象

源碼路徑: /frameworks/native/libs/binder/ProcessState.cpp

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    ...
01    handle_entry* e = lookupHandleLocked(handle);

    if (e != NULL) {
        IBinder* b = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            if (handle == 0) {
                Parcel data;
                status_t status = IPCThreadState::self()->transact(
                        0, IBinder::PING_TRANSACTION, data, NULL, 0);
                if (status == DEAD_OBJECT)
                   return NULL;
            }

            b = new BpBinder(handle); 
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    return result;
}

通過上一步調用可知參數 handle 的值爲 0. 這裏先說一下 01 行代碼處的 handle_entry.

Binder 庫爲每一個進程維護了一個 handle_entry 類型的 Binder 代理對象列表, 它以句柄作爲關鍵字來維護進程內部所有的 Binder 代理對象. 這個 Binder 代理對象列表保存在 ProcessState 類的成員變量 mHandleToObject 中. 定義如下
源碼路徑: /frameworks/native/include/binder/ProcessState.h

struct handle_entry {
   IBinder* binder;
   RefBase::weakref_type* refs;
};
...
Vector<handle_entry>mHandleToObject;

每一個 Binder 代理對象都使用一個 handle_entry 的結構體來描述. handle_entry 的兩個成員變量 binderrefs 分別指向一個 Binder 代理對象以及它內部的一個弱引用計數對象.

一個 Binder 代理對象的句柄值同時也是它在列表 mHandleToObject 中的索引值.

OK, 接着回到 getStrongProxyForHandle 函數.
在第 01 行代碼處 調用 lookupHandleLocked 函數.來檢查成員變量 mHandleToObject 中是否已經存在一個與句柄值 handle 對應的 handle_entry 結構體. 現在進入到這個函數內.

6.1 lookupHandleLocked 檢查是否已經存在與句柄值對應的 handle_entry 結構體

源碼路徑: /frameworks/native/include/binder/ProcessState.h

ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
{
    const size_t N=mHandleToObject.size();
    if (N <= (size_t)handle) {
        handle_entry e;
        e.binder = NULL;
        e.refs = NULL;
        status_t err = mHandleToObject.insertAt(e, N, handle+1-N);
        if (err < NO_ERROR) return NULL;
    }
    return &mHandleToObject.editItemAt(handle);
}

在函數中先來檢查句柄值 handle 的值是否大於或者等於列表 mHandleToObject 的大小. 如果是, 則命中 if. 說明 mHandleToObject 列表裏不存在一個與句柄值 handle 相對應的 handle_entry 結構體. 那麼 if 內的幾行代碼就會在列表 mHandleToObject 中插入一個 handle_entry 結構體. 在最後就可以將與句柄值 handle 對應的 handle_entry 結構體返回給調用者.

注: 這些插入的 handle_entry 結構體還未與 Binder 代理對象關聯起來. 因此它們的成員變量 binderrefs 都還是 NULL.

接着回到第 6 步. 爲了方便代碼直接貼到這裏

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    ...
01    handle_entry* e = lookupHandleLocked(handle);

    if (e != NULL) {
        IBinder* b = e->binder;
02        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            if (handle == 0) {
                Parcel data;
03              status_t status = IPCThreadState::self()->transact(0, IBinder::PING_TRANSACTION, data, NULL, 0);
                if (status == DEAD_OBJECT)
                   return NULL;
            }

04          b = new BpBinder(handle); 
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
05            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    return result;
}

01 行代碼已經分析完了, 將從 Binder 代理對象列表中獲得的 handle_entry 結構體保存在變量 e 中.

02 代碼處判斷 handlle_entry 結構體的成員變量 binder 值是否爲 NULL, 如果爲 NULL, 說明尚未爲句柄值 handle 創建過 Binder 代理對象. 那麼久會在 03 代碼處創建 Binder 代理對象. 如果不爲 NULL, 既它已經指向了一個 Binder 代理對象, 則需要調用 attemptIncWeak 函數檢查這個代理對象是否還存活着.

03 代碼處通過 PING_TRANSACTION 命令測試 Binder 是否準備就緒.

04 行代碼處就開始根據句柄值 handle 創建 Binder 代理對象, 並將其保存在 handle_entry 結構體 e 的成員變量 binder 中.

05 行代碼說明進程中已經有一個 Binder 代理對象與句柄值 handle 相對應, 並且這個 Binder 代理對象是有效的. 直接返回給調用者.

最終返回了 Binder 的代理對象.

自此在第 1 步 defaultServiceManager 函數內 ProcessState::self()->getContextObject(NULL) 分析完了, 成功返回了 Binder 代理對象. 那繼續回到 defaultServiceManager 向下執行在 02行調用模板函數 interface_cast<IServiceManager> 將這個Binder 代理對象封裝稱爲一個 ServiceManager 代理對象. 這裏也直接貼出第 1 步代碼

sp<IServiceManager> defaultServiceManager()
{
01    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;    
    {
        AutoMutex _l(gDefaultServiceManagerLock);
        while (gDefaultServiceManager == NULL) {
02            gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));
              if (gDefaultServiceManager == NULL)
                sleep(1);
        }
    }
03    return gDefaultServiceManager;
}

7. interface_cast<IServiceManager> 將 Binder 代理對象封裝爲 SM 代理對象

源碼路徑: /frameworks/native/include/binder/IInterface.h

template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

這裏的 INTERFACE 可以簡單的理解爲泛型, 上面傳入的是 IServiceManager, 因此它實際上調用的是 IServiceManager 接口的成員函數 asInterface, 將一個句柄值爲 0 的 Binder 代理對象封裝爲一個 SM 對象.

對於 asInterface 函數, 通過在 IServiceManager 搜索代碼, 發現根本找不到這個函數在哪裏定義的, 其實這個函數是通過宏來定義的.
源碼路徑: /frameworks/native/libs/binder/IServiceManager.cpp

IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");

展開前定義如下
源碼路徑:/frameworks/native/include/binder/IInterface.h

#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
    ...                                                          \
    android::sp<I##INTERFACE> I##INTERFACE::asInterface(                \
            const android::sp<android::IBinder>& obj)                   \
    {                                                                   \
        android::sp<I##INTERFACE> intr;                                 \
        if (obj != NULL) {                                              \
            intr = static_cast<I##INTERFACE*>(                          \
                obj->queryLocalInterface(                               \
                        I##INTERFACE::descriptor).get());               \
            if (intr == NULL) {                                         \
                intr = new Bp##INTERFACE(obj);                          \
            }                                                           \
        }                                                               \
        return intr;                                                    \
    }
    I##INTERFACE::I##INTERFACE() { }                                    \
    I##INTERFACE::~I##INTERFACE() { }                                         

展開可以理解爲 將##INTERFACEname. 替換爲傳入的參數. 展開後如下

android::sp<IServiceManager> IServiceManager::asInterface( const android::sp<android::IBinder>& obj)                   
    {                                                                   
        android::sp<IServiceManager > intr;                                 
        if (obj != NULL) {                                              
            intr = static_cast<IServiceManager>(obj->queryLocalInterface( IServiceManager::descriptor).get());               
            if (intr == NULL) {                                         
                intr = new BpServiceManager(obj);                          
            }                                                           
        }                                                               
        return intr;                                                    
    }
    IServiceManager::IServiceManager() { }                                    
    IServiceManager::~IServiceManager() { }       

前面可知參數 obj 指向一個 Binder 代理對象, 既一個 BpBinder 對象. 它的成員函數 queryLocalInterface 返回爲 NULL,. 因此會執行 intr = new BpServiceManager(obj); 也就是創建一個 SM 的代理對象. 其實也就是 BpServiceManager 對象. 返回給調用者.

到這裏, SM 代理對象的獲取流程就分析學習完了.
有了這個 SM 代理對象之後, Service 組件就可以在啓動的過程中使用它的成員函數 addService 將自己註冊到 SM 中.
而 Client 組件就可以使用它的成員函數 getService 來獲得一個指定名稱的 Service 組件的代理對象了.

下一章將繼續學習分析 Service 組件是如何將自己註冊到 SM 中的.

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