binder機制學習

Android系統的Binder機制之一——ServiceManager

Android雖然構建在Linux上面,但是在IPC(進程間)機制方面,沒有利用Linux提供IPC機制,而是自己實現了一套輕量級的IPC機制 ——binder機制。並且Android Binder機制之上,Android框架提供了一套封裝,可以實現對象代理(在本地進程中代理遠程進程的對象)。本文簡單分析一下Android Binder機制。

Binder情景分析

    一個IPC通訊我們可以理解成客戶端-服務器模式,因此我們先在這裏分析一下典型的Binder應用模式:

1、客戶端通過某種方式(後文會詳細介紹)得到服務器端的代理對象。從客戶端角度看來代理對象和他的本地對象沒有什麼差別。它可以像其他本地對象一樣調用其方法,訪問其變量。
2、客戶端通過調用服務器代理對象的方法向服務器端發送請求。
3、代理對象把用戶請求通過Android內核(Linux內核)的Binder驅動發送到服務器進程。
4、服務器進程處理用戶請求,並通過Android內核(Linux內核)的Binder驅動返回處理結果給客戶端的服務器代理對象。
5、客戶端收到服務器端的返回結果。

    如果你對COM或者Corba熟悉的話,以上的情景是否會讓你聯想到什麼呢?沒錯!都是對象代理。以上的情景,在Android中經常會被用到。如果你還沒有注意到這點兒,那麼本文非常適合你。

Binder機制的組成

1、Binder驅動

    binder是內核中的一個字符驅動設備位於:/dev/binder。這個設備是Android系統IPC的核心部分,客戶端的服務代理用來通過它向服 務器(server)發送請求,服務器也是通過它把處理結果返回給客戶端的服務代理對象。我們只需要知道它的功能就可以了,本文我們的重點不在這裏,所以後面不會專門介紹這部分,因爲很少會有人會顯示打開這個設備去開發Android程序。如果想深入瞭解的話,請研究內核源碼中的binder.c。

2、Service Manager

    負責管理服務。對應於第一步中,客戶端需要向Service Manager來查詢和獲得所需要服務。服務器也需要向ServiceManager註冊自己提供的服務。可以看出Service Manager是服務的大管家。

3、服務(Server)

    需要強調的是這裏服務是指的是System Server,而不是SDK server,請參考《(轉)高煥堂——Android框架底層結構知多少?》關於兩種Server的介紹(其實應該是三種,丟掉了init調用的server,在init.rc中配置)。

4、客戶端

    一般是指Android系統上面的應用程序。它可以請求Server中的服務。

5、對象代理

    是指在客戶端應用程序中生成的Server代理(proxy)。從應用程序角度看代理對象和本地對象沒有差別,都可以調用其方法,方法都是同步的,並且返回相應的結果。

大內總管——Service Manager

    Android系統Binder機制的總管是Service Manager,所有的Server(System Server)都需要向他註冊,應用程序需要向其查詢相應的服務。可見其作用是多麼的重要,所以本文首先介紹Service Manager。

    通過上面介紹我們知道ServiceManager非常重要,責任重大。那麼怎樣才能成爲Service Manager呢?是不是誰都可以成爲Service Manager呢?怎樣處理server的註冊和應用程序的查詢和獲取服務呢?爲了回答這些問題先查看,Android中Service Manager的源碼,其源碼位於:

frameworks\base\cmds\servicemanager\service_manager.c

我們發現了main函數,說明他自己就是一個進程,在init.rc中我們發現:

service servicemanager /system/bin/servicemanager
    user system
    critical
    onrestart restart zygote
    onrestart restart media

說明其是Android核心程序,開機就會自動運行。

    下面我們在研究一下它的代碼,main函數很簡單:

int main(int argc, char **argv)
{
    struct binder_state *bs;
    void *svcmgr = BINDER_SERVICE_MANAGER;
 
    bs = binder_open(128*1024);
 
    if (binder_become_context_manager(bs)) {
        LOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }
 
    svcmgr_handle = svcmgr;
    binder_loop(bs, svcmgr_handler);
    return 0;
}

我們看到它先調用binder_open打開binder設備(/dev/binder),其次它調用了binder_become_context_manager函數,這個函數使他自己變爲了“Server大總管”,其代碼如下:

int binder_become_context_manager(struct binder_state *bs)
{
    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}

也就是通過ioctl向binder設備聲明“我就是server大總管”。

    Service Manager作爲一個Server大總管,本身也是一個server。既然是一個server就要時刻準備爲客戶端提供服務。最好Service Manager調用binder_loop進入到循環狀態,並提供了一個回調函數,等待用戶的請求。注意他的ServiceManager的客戶端既包括應用程序(查詢和獲取服務),也包括Server(註冊服務)。

    Service Manager的客戶怎樣才能請求其服務呢?答案是上文我們提到的情景一樣。客戶需要在自己進程中創建一個服務器代理。現在沒有地方去查詢服務,那麼怎樣它的客戶怎樣生成他的服務代理對象呢?答案是binder設備(/devbinder)爲每一個服務維護一個句柄,調用 binder_become_context_manager函數變爲“Server大總管”的服務,他的句柄永遠是0,是一個“衆所周知”的句柄,這樣 每個程序都可以通過binder機制在自己的進程空間中創建一個

Service Manager代理對象了。其他的服務在binder設備在設備中的句柄是不定的,需要向“Server大總管”查詢才能知道。

    現在我們需要研究Server怎樣註冊服務了,還是在其源碼中,我們可以看到在其服務處理函數中(上文提到binder_loop函數註冊給binder設備的回調函數)有如下代碼:

    case SVC_MGR_ADD_SERVICE:
        s = bio_get_string16(msg, &len);
        ptr = bio_get_ref(msg);
        if (do_add_service(bs, s, len, ptr, txn->sender_euid))
            return -1;
        break;

有server向binder設備寫入請求註冊Service時,Service Manager的服務處理回調函數將會被調用。我們在仔細看看do_add_service函數的實現:

int do_add_service(struct binder_state *bs,
                   uint16_t *s, unsigned len,
                   void *ptr, unsigned uid)
{
    struct svcinfo *si;
//    LOGI("add_service('%s',%p) uid=%d\n", str8(s), ptr, uid);
 
    if (!ptr || (len == 0) || (len > 127))
        return -1;
 
    if (!svc_can_register(uid, s)) {
        LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",
             str8(s), ptr, uid);
        return -1;
    }
 
    si = find_svc(s, len);
    if (si) {
        if (si->ptr) {
            LOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED\n",
                 str8(s), ptr, uid);
            return -1;
        }
        si->ptr = ptr;
    } else {
        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
        if (!si) {
            LOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY\n",
                 str8(s), ptr, uid);
            return -1;
        }
        si->ptr = ptr;
        si->len = len;
        memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
        si->name[len] = '\0';
        si->death.func = svcinfo_death;
        si->death.ptr = si;
        si->next = svclist;
        svclist = si;
    }
 
    binder_acquire(bs, ptr);
    binder_link_to_death(bs, ptr, &si->death);
    return 0;
}

我們看到首先檢查是否有權限註冊service,沒權限就對不起了,出錯返回;然後檢查是否已經註冊過,註冊過的 service將不能再次註冊。然後構造一個svcinfo對象,並加入一個全局鏈表中svclist中。最後通知binder設備:有一個 service註冊進來。

    我們再來看看客戶端怎樣通過ServiceManager獲得Service,還是在服務處理函數中(上文提到binder_loop函數註冊給binder設備的回調函數)有如下代碼:

    case SVC_MGR_GET_SERVICE:
    case SVC_MGR_CHECK_SERVICE:
        s = bio_get_string16(msg, &len);
        ptr = do_find_service(bs, s, len);
        if (!ptr)
            break;
        bio_put_ref(reply, ptr);
        return 0;

    我們可以看到通過do_find_service查找Service如果查找到的話,寫入reply中返回給客戶端。

    本文我們簡單分析了一下ServiceManager,後續我們會繼續分析Android binder機制的其他部分。

Android系統的Binder機制之二——服務代理對象(1)

  上文《Android系統的Binder機制之一——ServiceManager》我們學習了Service Manager在Android Binder中的作用——服務(Service)註冊,服務(Service)查詢的功能。本文我們一起學習服務(Service)在客戶端中的代理機制。重點介紹其核心對象BpBinder。

1、服務代理的原理

    如下是客戶端請求service服務的場景:

1、首先客戶端向Service manager查找相應的Service。上文《Android系統的Binder機制之一——ServiceManager》有比較詳細的介紹。注意客戶端和Service可能在兩個不同的進程中。
2、Android系統將會爲客戶端進程中創建一個Service代理。下文將詳細介紹該創建過程。
3、客 戶端視角只有Service代理,他所有對Service的請求都發往Service代理,然後有Service代理把用戶請求轉發給Service本 身。Service處理完成之後,把結果返回給Service代理,Service代理負責把處理結果返回給客戶端。注意客戶端對Service代理的調 用都是同步調用(調用掛住,直到調用返回爲止),這樣客戶端視角來看調用遠端Service的服務和調用本地的函數沒有任何區別。這也是Binder機制 的一個特點。

2、Android進程環境——ProcessState類型和對象

    在Android系統中任進程何,要想使用Binder機制,必須要創建一個ProcessState對象和IPCThreadState對象。當然如果 Android進程不使用Binder機制,那麼這兩個對象是不用創建的。這種情況很少見,因爲Binder機制是整個Android框架的基礎,可以說 影響到Android方方面面。所以說了解這兩個對象的作用非常重要。

    臺灣的高煥堂先生一片文章《認識ProcessState類型和對象》,可以在我的博文《(轉)高煥堂——Android框架底層結構知多少?》中找到。可以先通過這篇文章對ProcessState進行一個大概瞭解。

    ProcessState是一個singleton類型,一個進程只能創建一個他的對象。他的作用是維護當前進程中所有Service代理(BpBinder對象)。一個客戶端進程可能需要多個Service的服務,這樣可能會創建多個Service代理(BpBinder對象),客戶端進程中的ProcessState對象將會負責維護這些Service代理。

我們研究一下創建一個Service代理的代碼:

   1: sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
   2: {
   3:     sp<IBinder> result;
   4:  
   5:     AutoMutex _l(mLock);
   6:  
   7:     handle_entry* e = lookupHandleLocked(handle);
   8:  
   9:     if (e != NULL) {
  10:         // We need to create a new BpBinder if there isn't currently one, OR we
  11:         // are unable to acquire a weak reference on this current one.  See comment
  12:         // in getWeakProxyForHandle() for more info about this.
  13:         IBinder* b = e->binder;
  14:         if (b == NULL || !e->refs->attemptIncWeak(this)) {
  15:             b = new BpBinder(handle); 
  16:             e->binder = b;
  17:             if (b) e->refs = b->getWeakRefs();
  18:             result = b;
  19:         } else {
  20:             // This little bit of nastyness is to allow us to add a primary
  21:             // reference to the remote proxy when this team doesn't have one
  22:             // but another team is sending the handle to us.
  23:             result.force_set(b);
  24:             e->refs->decWeak(this);
  25:         }
  26:     }
  27:  
  28:     return result;
  29: }

   getWeakProxyForHandle函數的作用是根據一個binder句柄(上文《Android系統的Binder機制之一——Service Manager》提到Binder驅動爲每個Service維護一個Binder句柄,客戶端可以通過句柄來和Service通訊)創建對應的Service代理對象。

    當前進程首先調用lookupHandleLocked函數去查看當前進程維護的Service代理對象的列表,該待創建Service代理對象是否已經 在當前進程中創建,如果已經創建過了,則直接返回其引用就可以了。否則將會在Service代理對象的列表增加相應的位置(注意系統爲了減少分配開銷,可 能會多分配一些空間,策略是“以空間換時間”),保存將要創建的代理對象。具體代碼請參考lookupHandleLocked的源碼。

    後面代碼就好理解了,如果Service代理對象已經創建過了,直接增加引用計數就行了。若沒有創建過,則需要創建一個新的Service代理對象。

3、Android進程環境——IPCThreadState類型和對象

    Android進程中可以創建一個ProcessState對象,該對象創建過程中會打開/dev/binder設備,並保存其句柄。並初始化該設備。代碼如下:

   1: ProcessState::ProcessState()
   2:     : mDriverFD(open_driver())
   3:     , mVMStart(MAP_FAILED)
   4:     , mManagesContexts(false)
   5:     , mBinderContextCheckFunc(NULL)
   6:     , mBinderContextUserData(NULL)
   7:     , mThreadPoolStarted(false)
   8:     , mThreadPoolSeq(1)
   9: {
  10:     if (mDriverFD >= 0) {
  11:         // XXX Ideally, there should be a specific define for whether we
  12:         // have mmap (or whether we could possibly have the kernel module
  13:         // availabla).
  14:#if !defined(HAVE_WIN32_IPC)
  15:         // mmap the binder, providing a chunk of virtual address space to receive transactions.
  16:         mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
  17:         if (mVMStart == MAP_FAILED) {
  18:             // *sigh*
  19:             LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
  20:             close(mDriverFD);
  21:             mDriverFD = -1;
  22:         }
  23:#else
  24:         mDriverFD = -1;
  25:#endif
  26:     }
  27:     if (mDriverFD < 0) {
  28:         // Need to run without the driver, starting our own thread pool.
  29:     }
  30: }

   mDriverFD保存了/dev/binder設備的句柄,如果仔細查看ProcessState的源碼會發現這個句柄不會被ProcessState 對象使用。那麼保存這個句柄做什麼用呢?被誰使用呢?非常奇怪。經過查看ProcessState的頭文件,發現如下代碼:

   1:friendclass IPCThreadState;

   發現IPCThreadState是ProcessState的友元類,那麼就可以懷疑這個句柄是被IPCThreadState的對象使用的,然後查看代碼發現確實如此。

    IPCThreadState也是一個singleton的類型,一個進程中也只能有一個這樣的對象。我們查看一下它的talkWithDriver函數:

   1: ...........
   2:if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
   3:     err = NO_ERROR;
   4:else
   5:     err = -errno;
   6: ...........

   IPCThreadState通過ioctl系統調用對ProcessState打開的句柄進行讀寫。這樣我們也可以看出IPCThreadState對象的作用:

1、維護當前進程中所有對/dev/binder的讀寫。換句話說當前進程通過binder機制進行跨進程調用都是通過IPCThreadState對象來完成的。

2、IPCThreadState也可以理解成/dev/binder設備的封裝,用戶可以不直接通過ioctl來操作binder設備,都通過IPCThreadState對象來代理即可。

    我們這裏可以再深入地聊一下,不管是客戶端進程和Service進程都是需要用IPCThreadState來和binder設備通訊的。如果是客戶端進 程則通過服務代理BpBinder對象,調用transact函數,該函數作用就是把客戶端的請求寫入binder設備另一端的Service進程,具體 請參閱IPCThreadState類的transact方法。作爲Service進程,當他完成初始化工作之後,他需要他們需要進入循環狀態等待客戶端 的請求,Service進程調用它的IPCThreadState對象的joinThreadPool方法,開始輪詢binder設備,等待客戶端請求的 到來,後面我們討論Service時候會進一步討論joinThreadPool方法。有興趣的朋友可以先通過查看代碼來了解 joinThreadPool方法。

4、Service代理對象BpBinder

   上文關於ProcessState的介紹提到了,客戶端進程創建的Service代理對象其實就是BpBinder對象。

   我們首先了解怎樣創建BpBinder對象。

   1: BpBinder::BpBinder(int32_t handle)
   2:     : mHandle(handle)
   3:     , mAlive(1)
   4:     , mObitsSent(0)
   5:     , mObituaries(NULL)
   6: {
   7:     LOGV("Creating BpBinder %p handle %d\n", this, mHandle);
   8:  
   9:     extendObjectLifetime(OBJECT_LIFETIME_WEAK);
  10:     IPCThreadState::self()->incWeakHandle(handle);
  11: }

   我們可以看出首先是通過IPCThreadState讀寫binder設備增加中相應binder句柄上的Service的引用計數。然後本地保存代理Service的binder句柄mHandle。

    客戶進程對Service的請求都通過調用BpBinder的transact方法來完成:

   1: status_t BpBinder::transact(
   2:     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
   3: {
   4:     // Once a binder has died, it will never come back to life.
   5:     if (mAlive) {
   6:         status_t status = IPCThreadState::self()->transact(
   7:             mHandle, code, data, reply, flags);
   8:         if (status == DEAD_OBJECT) mAlive = 0;
   9:         return status;
  10:     }
  11:  
  12:     return DEAD_OBJECT;
  13: }

在transact方法中,還是調用客戶進程的IPCThreadState對象來完成對相應Service請求。注意transact方法是同步方法,將會掛住客戶進程的當前線程,直到service把請求處理完成,並返回結果。這時客戶進程當前線程的 transact方法返回。

5、Android系統對Binder機制的抽象——IBinder

    上面我們講解了Binder機制比較底層的機制,這些機制直接用還是比較麻煩的,比如使用binder設備的ioctl,需要記住很多ioctl的代碼。

    Android爲了是Binder機制容易使用,對Binder機制進行了抽象,定義了IBinder接口,該接口在C/C++和Java層都有定義。IBinder定義了一套使用Binder機制使用和實現客戶程序和服務器的通訊協議。可以理解如下定義:

1、向Android註冊的Service也必須是IBinder(繼承擴展IBinder接口)對象。後續文章中我們討論Service的時候我們會介紹到這方面的內容。

2、客戶端得到Service代理對象也必須定義成IBinder(繼承擴展IBinder接口)對象。這也是爲什麼BpBinder就是繼承自IBinder。

3、客戶端發送請求給客戶端,調用接口的Service代理對象IBinder接口的transact方法。

4、Android系統Binder機制將負責把用戶的請求,調用Service對象IBinder接口的onTransact方法。具體實現我們將在以後介紹Service的時候討論。

6、Service Manager代理對象

    我們知道ServiceManager是Android Binder機制的大管家。所有需要通過Binder通訊的進程都需要先獲得Service Manager的代理對象才能進行Binder通訊。Service Manager即在C/C++層面提供服務代理,又在Java層面提供服務代理,本文先介紹一下C/C++層面的服務代理,Java層面的服務代理將在後 續文章中介紹。

    進程在C/C++層面上面,Android在Android命名空間中定義了一個全局的函數defaultServiceManager(定義在framework/base/libs/binder),通過這個函數可以使進程在C/C++層面獲得Service Manager的代理。我們先看一下該函數的定義:

   1: sp<IServiceManager> defaultServiceManager()
   2: {
   3:     if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
   4:     
   5:     {
   6:         AutoMutex _l(gDefaultServiceManagerLock);
   7:         if (gDefaultServiceManager == NULL) {
   8:             gDefaultServiceManager = interface_cast<IServiceManager>(
   9:                 ProcessState::self()->getContextObject(NULL));
  10:         }
  11:     }
  12:     
  13:     return gDefaultServiceManager;
  14: }

    我們可以看到defaultServiceManager是調用ProcessState對象的getContextObject方法獲得Service Manager的getContextObject方法獲得Service Manager代理對象。我們再看一下getContextObject函數的定義:

   1: sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
   2: {
   3:     if (supportsProcesses()) {
   4:         return getStrongProxyForHandle(0);
   5:     } else {
   6:         return getContextObject(String16("default"), caller);
   7:     }
   8: }

    我們可以看出其實是調用我們上面描述過的getStrongProxyForHandle方法,並以句柄0爲參數來獲得Service Manager的代理對象。

   ProcessState::self()->getContextObject(NULL)返回一個IBinder對象,怎樣把它轉化成一個 IServiceManager的對象呢?這就是模板函數interface_cast<IServiceManager>的作用了。調用的是IServiceManager.asInterface方法。IServiceManager的asInterface方法通過 DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE宏來定義,詳細情況請查看IServiceManager類的定義。IMPLEMENT_META_INTERFACE宏關於asInterface的定義如下:

   1: android::sp<I##INTERFACE> I##INTERFACE::asInterface(                \
   2:         const android::sp<android::IBinder>& obj)                   \
   3: {                                                                   \
   4:     android::sp<I##INTERFACE> intr;                                 \
   5:     if (obj != NULL) {                                              \
   6:         intr = static_cast<I##INTERFACE*>(                          \
   7:             obj->queryLocalInterface(                               \
   8:                     I##INTERFACE::descriptor).get());               \
   9:         if (intr == NULL) {                                         \
  10:             intr = new Bp##INTERFACE(obj);                          \
  11:         }                                                           \
  12:     }                                                               \
  13:     return intr;                                                    \
  14: }                                                                   \

    最終asInterface將會用一個IBinder對象創建一個BpServiceManager對象,並且BpServiceManager繼承自 IServiceManager,這樣我們就把IBinder對象轉換成了IServiceManager對象。如果你仔細查看 BpServiceManager的定義,你會發現查詢Service,增加Service等方法其實都是調用底層的IBinder對象來完成的。

    當我們在C/C++層面編寫程序使用Binder機制的時候將會調用defaultServiceManager函數來獲得Service Manager,比如:很多Android系統Service都是在C/C++層面實現的,他們就需要向Service Manager註冊其服務,那麼這些服務將調用defaultServiceManager獲得Service Manager代理對象。我們在後續介紹Android系統Service的時候將會詳細介紹。

7、總結

    本文中我們介紹了C++層面的Service代理,後續文章我們將介紹Java層面的Service代理。

Android系統的Binder機制之三——服務代理對象(2)

上文《Android系統的Binder機制之二——服務代理對象(1)》我們學習了進程的C/C++層面的服務代理對象BpBinder,和Binder底層處理方式。本文我們將深入分析一下在進程的Java層面服務代理對象的創建和使用。

Android進程的C/C++層面和Java層

    Android中程序大部分都是java開發,底層通過JNI調用C/C++的代碼。這樣一個程序就分爲了兩個層面C/C++層面和Java層面。運行狀態下,我們說它們都在一個進程之中,擁有相同的進程屬性(UID,GID等等)。

    Binder客戶程序的C/C++層面的對象和原理我們在上文《Android系統的Binder機制之二——服務代理對象(1)》已經學習。下面我們將介紹客戶程序怎樣在Java層面通過JNI調用底層C/C++代碼的創建服務代理。

ServiceManager類型和對象

    我在《Android系統的Binder機制之一——ServiceManager》中介紹過,客戶端要想獲得服務代理,首先要向ServiceManager查詢Service。在Java層面也是這樣,所以我們首先分析Java層面ServiceManager類。

    我們通過查看ServiceManager的源碼我們發現,ServiceManager類型也是一個Singleton類型。所有的方法都是靜態方法,所有靜態方法都是訪問它的IServiceManager類型的靜態變量sServiceManager,定義如下:

   1:privatestatic IServiceManager sServiceManager;

所以可以理解ServiceManager就是IServiceManager對象的一個代理。爲創建和訪問這個變量都是通過ServiceManager的getIServiceManager方法,定義如下:

   1:privatestatic IServiceManager getIServiceManager() {
   2:     if (sServiceManager != null) {
   3:         return sServiceManager;
   4:     }
   5:  
   6:     // Find the service manager
   7:     sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
   8:     return sServiceManager;
   9: }

    通過上面的代碼,非常清晰的告訴我們ServiceManager類型是一個Singleton類型。現在我們主要研究sServiceManager對象怎樣創建的。如下代碼創建IServiceManager對象:

   1: sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());

我們首先查看BinderInternal類的getContextObject方法的代碼,發現是Native代 碼(哈哈!有終於到達C/C++層面了,我們已經熟悉了),對應的代碼爲android_util_binder.cpp中的android_os_BinderInternal_getContextObject函數,代碼如下:

   1:static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
   2: {
   3:     sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
   4:     return javaObjectForIBinder(env, b);
   5: }

    終於看到我們上文《Android系統的Binder機制之二——服務代理對象(1)》介紹過的ProcessState對象了,我們再去查看ProcessState對象的getContextObject方法,代碼如下:

   1: sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
   2: {
   3:     if (supportsProcesses()) {
   4:         return getStrongProxyForHandle(0);
   5:     } else {
   6:         return getContextObject(String16("default"), caller);
   7:     }
   8: }

    我們看到在當前進程的ProcessState對象其實是調用getStrongProxyForHandle方法來創建binder句柄爲0的服務代理對象——BpBinder對象,我們在《Android系統的Binder機制之一——Service Manager》提到過ServiceManager的binder句柄是一個聞名句柄0。上文《Android系統的Binder機制之二——服務代理對象(1)》已經介紹過ProcessState對象的getStrongProxyForHandle方法,這裏就不多說了。

    我們可以看出Java調用C/C++,創建一個服務代理對象BpBinder,在查看BpBinder的定義我們發現繼承自IBinder接口,然後在 android_util_binder.cpp中的方法android_os_BinderInternal_getContextObject中,把 C/C++層面的IBinder對象封裝成Java層面的IBinder對象。具體實現可以查看上文的 android_os_BinderInternal_getContextObject方法。

    至此我們已經清楚BinderInternal.getContextObject(),返回的是ServiceManager的服務代理對象—— BpBinder對象。那麼ServiceManagerNative類的靜態方法asInterface做什麼用呢?我們還是通過代碼來分析,在 ServiceManagerNative.java中,asInterface的代碼如下:

   1:staticpublic IServiceManager asInterface(IBinder obj)
   2: {
   3:     if (obj == null) {
   4:         return null;
   5:     }
   6:     IServiceManager in =
   7:         (IServiceManager)obj.queryLocalInterface(descriptor);
   8:     if (in != null) {
   9:         return in;
  10:     }
  11:     
  12:     returnnew ServiceManagerProxy(obj);
  13: }

將會用IBinder對象創建一個ServiceManagerProxy對象,ServiceManagerProxy類型繼承了IServiceManager接口,所以asInterface方法最終目的是用一個 IBinder對象創建一個IServiceManager對象。

    爲什麼要用IBinder對象創建一個IServiceManager對象呢?通過ServiceManager的代理對象——IBinder對象(BpBinder對象)應該可以直接請求ServiceManager中的服務了啊?我們在前文《Android系統的Binder機制之二——服務代理對象(1)》簡單介紹了一下IBinder類型,客戶端通過transact方法向Service發送請求,客戶端的onTransact被調用處理客戶端的請求,請求通過請求代碼來區分。具體請參考Android手冊。如果客戶端直接用調用ServiceManager的代理對象的IBinder接口,那麼客戶端必須要記住所有請求的請求代碼,對客戶端來說不太友好。所以在ServiceManagerNative類中就把ServiceManager的代理對象——IBinder對象(BpBinder對象)封裝成 ServiceManagerProxy對象,暴露給客戶程序一個IServiceManager接口,這樣IServiceManager對象將會代理 客戶程序發往ServiceManager的代理對象的請求。並且是調用IServiceManager對象的方法來給ServiceManager發送請求,這樣對客戶程序來講和本地的函數調用是一致的,接口非常友好。比如我們客戶程序需要調用IServiceManager的getService方法 來查詢一個Service,ServiceManagerProxy實現代碼如下:

   1:public IBinder getService(String name) throws RemoteException {
   2:     Parcel data = Parcel.obtain();
   3:     Parcel reply = Parcel.obtain();
   4:     data.writeInterfaceToken(IServiceManager.descriptor);
   5:     data.writeString(name);
   6:     mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
   7:     IBinder binder = reply.readStrongBinder();
   8:     reply.recycle();
   9:     data.recycle();
  10:     return binder;
  11: }

    我們可以非常清晰的看到ServiceManagerProxy對象將客戶程序的請求轉換成對ServiceManager代理對象——IBinder對 象(BpBinder對象)的調用。後文我們將會詳細介紹怎樣通過IServiceManager查詢和獲得一個系統Service代理對象。

    到這裏我們已經分析完了,ServiceManager的Singleton對象——sServiceManager的創建。如果有不清楚的地方請查看代碼。

查詢和獲得Service代理對象

    客戶程序通過調用ServiceManager類型的靜態方法asInterface獲得了IServiceManager對象,但是最終目的一般都是要查詢和獲得其他的Service,一般都是要調用IServiceManager的getService方法,向ServiceManager獲得其他的Service。比如:

   1: IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);

    上面的代碼中就是調用ServiceManager的靜態方法獲得網絡管理服務代理對象。我們順藤摸瓜,看看系統是怎樣生成這個Service代理對象的。這裏只是簡單說明一下調用順序,詳細過程請查看源碼。

1、調用ServiceManager.java中的ServiceManager靜態方法getService。

2、調用ServiceManagerNative.java中的ServiceManagerProxy方法getService。代碼如下:

   1:public IBinder getService(String name) throws RemoteException {
   2:     Parcel data = Parcel.obtain();
   3:     Parcel reply = Parcel.obtain();
   4:     data.writeInterfaceToken(IServiceManager.descriptor);
   5:     data.writeString(name);
   6:     mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
   7:     IBinder binder = reply.readStrongBinder();
   8:     reply.recycle();
   9:     data.recycle();
  10:     return binder;
  11: }

    請注意IBinder的transact方法是同步方法(本例中ServiceManager處理完成請求之後纔會返回),我們可以看出調用transact之後,調用reply.readStrongBinder()來讀取IBinder對象。

3、查看Parcel.java中的readStrongBinder方法,發現是Native方法,將會調用到C/C++的代碼。

4、查看android_util_binder.cpp中的android_os_Parcel_readStrongBinder函數。代碼如下:

   1:static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz)
   2: {
   3:     Parcel* parcel = parcelForJavaObject(env, clazz);
   4:     if (parcel != NULL) {
   5:         return javaObjectForIBinder(env, parcel->readStrongBinder());
   6:     }
   7:     return NULL;
   8: }

parcel->readStrongBinder()將會產生一個IBinder對象。

5、查看Parcel.cpp中,Parcel的方法readStrongBinder。代碼如下:

   1: sp<IBinder> Parcel::readStrongBinder() const
   2: {
   3:     sp<IBinder> val;
   4:     unflatten_binder(ProcessState::self(), *this, &val);
   5:     return val;
   6: }

6、查看Parcel.cpp中,Parcel的方法unflatten_binder。代碼如下:

   1: status_t unflatten_binder(const sp<ProcessState>& proc,
   2:     const Parcel& in, sp<IBinder>* out)
   3: {
   4:     const flat_binder_object* flat = in.readObject(false);
   5:     
   6:     if (flat) {
   7:         switch (flat->type) {
   8:             case BINDER_TYPE_BINDER:
   9:                 *out = static_cast<IBinder*>(flat->cookie);
  10:                 return finish_unflatten_binder(NULL, *flat, in);
  11:             case BINDER_TYPE_HANDLE:
  12:                 *out = proc->getStrongProxyForHandle(flat->handle);
  13:                 return finish_unflatten_binder(
  14:                     static_cast<BpBinder*>(out->get()), *flat, in);
  15:         }        
  16:     }
  17:     return BAD_TYPE;
  18: }

終於看到調用我們的老朋友ProcessState對象的getStrongProxyForHandle方法了,這樣將會創建一個BpBinder對象,然後該BpBinder對象將會被轉換成IBinder對象返回給Java層。

7、Java層爲了用使用Service方便,可以把Service代理對象——BpBinder對象(IBinder對象)封裝成一個對客戶程序友好的代理對象,就如前面ServiceManagerProxy所示那樣。

8、用戶程序就可以通過該代理對象訪問相應Service了。

    通過所述,我們瞭解了Service代理對象在Java層的創建和使用。Android系統的Binder機制博大精深,我在本文中很多方面都是蜻蜓點水,如果想深入學習請參閱Android的源碼。

參考資料:

IPC框架分析 Binder,Service,Service manager

 

 

 

 

Android系統的Binder機制之四——系統Service

前面我們已經介紹了Android Binder機制的ServiceManagerService對象代理1Service對象代理2。本文將介紹一下Android機制的另外一個重要部分——系統Service。

1、系統Service實例——Media server

    首先我們先看一下Android一個實例Media Service,代碼位於framework/base/media/mediaserver/main_mediaserver.cpp文件:

   1:// System headers required for setgroups, etc.
   2:#include <sys/types.h>
   3:#include <unistd.h>
   4:#include <grp.h>
   5:  
   6:#include <binder/IPCThreadState.h>
   7:#include <binder/ProcessState.h>
   8:#include <binder/IServiceManager.h>
   9:#include <utils/Log.h>
  10:  
  11:#include <AudioFlinger.h>
  12:#include <CameraService.h>
  13:#include <MediaPlayerService.h>
  14:#include <AudioPolicyService.h>
  15:#include <private/android_filesystem_config.h>
  16:  
  17:usingnamespace android;
  18:  
  19:int main(int argc, char** argv)
  20: {
  21:     sp<ProcessState> proc(ProcessState::self());
  22:     sp<IServiceManager> sm = defaultServiceManager();
  23:     LOGI("ServiceManager: %p", sm.get());
  24:     AudioFlinger::instantiate();
  25:     MediaPlayerService::instantiate();
  26:     CameraService::instantiate();
  27:     AudioPolicyService::instantiate();
  28:     ProcessState::self()->startThreadPool();
  29:     IPCThreadState::self()->joinThreadPool();
  30: }

    我們發現Media Server是一個進程,並且該程序的實現表面上也挺簡單,其實並不簡單,讓我們慢慢分析一下Media Server。

1、第一句創建創建一個ProcessState的引用,但是這個對象後面並沒有被調用到,那麼爲什麼創建呢?請回想一下我在博文《Android系統的Binder機制之二——服務代理對象(1)》中介紹ProcessState對象時提到:如果一個進程要使用Binder機制,那麼他的進程中必須要創建一個ProcessState對象來負責管理Service的代理對象。

2、第二句調用defaultServiceManager獲得一個Service Manager代理對象,我在《Android系統的Binder機制之二——服務代理對象(1)》已經對此有了詳細的介紹這裏就不贅述了。

3、後面幾行都是創建具體的Service,我們展開之後發現都是一些調用Service Manager的addService進行註冊的函數,以AudioFlinger爲例,instantiate代碼如下:

   1:void AudioFlinger::instantiate() {
   2:     defaultServiceManager()->addService(
   3:             String16("media.audio_flinger"), new AudioFlinger());
   4: }

4、最後調用ProcessState的startThreadPool方法和IPCThreadState的joinThreadPool使Media Server進入等待請求的循環當中。

    我們可以看出一個進程中可以有多個Service,Media Server這個進程中就存在AudioFlinger,MediaPlayerService,CameraService,AudioPolicyService四個Service。

2、系統Service的基礎——BBinder

    我們仔細查看一下MediaServer中定義的四個Service我們將會發現他們都是繼承自BBinder,而BBinder又繼承自IBinder接口,詳細情況請自行查看他們的代碼。每個Service都改寫了BBinder的onTransact虛函數,當用戶發送請求到達Service時,框架將會調用Service的 onTransact函數,後面我們將會詳細的介紹這個機制。

3、Service註冊

    每個Service都需要向“大管家”Service Manager進行註冊,調用Service Manager的addService方法註冊。這樣Service Manager將會運行客戶端查詢和獲取該Service(代理對象),然後客戶端就可以通過該Service的代理對象請求該Service的服務。

4、Service進入等待請求的循環

    每個Service必須要進入死循環,等待客戶端請求的到達,本例中最後兩句就是使Service進行等待請求的循環之中。ProcessState的 startThreadPool方法最終調用的也是IPCThreadState的joinThreadPool方法,具體請查看代碼。 IPCThreadState的joinThreadPool方法的代碼如下:

   1:void IPCThreadState::joinThreadPool(bool isMain)
   2: {
   3:       ......  
   4:       do {
   5:         int32_t cmd;
   6:         
   7:         ......
   8:  
   9:         // now get the next command to be processed, waiting if necessary
  10:         result = talkWithDriver();
  11:         if (result >= NO_ERROR) {
  12:             ......
  13:  
  14:             result = executeCommand(cmd);
  15:         }
  16:         
  17:         ......
  18:     } while (result != -ECONNREFUSED && result != -EBADF);
  19:  
  20:     ......
  21: }

    Service在IPCThreadState的joinThreadPool方法中,調用talkWithDriver方法和Binder驅動進行交互,讀取客戶端的請求。當客戶端請求到達之後調用executeCommand方法進行處理。

    我們再看一下Service怎樣處理客戶端的請求?我們們查看一下executeCommand方法的源碼:

   1: status_t IPCThreadState::executeCommand(int32_t cmd)
   2: {
   3:     BBinder* obj;
   4:     RefBase::weakref_type* refs;
   5:     status_t result = NO_ERROR;
   6:     
   7:     switch (cmd) {
   8:         ...... 
   9:          case BR_TRANSACTION:
  10:         {
  11:             ......
  12:             if (tr.target.ptr) {
  13:                 sp<BBinder> b((BBinder*)tr.cookie);
  14:                 const status_t error = b->transact(tr.code, buffer, &reply, 0);
  15:                 if (error < NO_ERROR) reply.setError(error);
  16:                 
  17:             } 
  18:             ......            
  19:         }
  20:         break;
  21:     
  22:     ......
  23:     }
  24:  
  25:     if (result != NO_ERROR) {
  26:         mLastError = result;
  27:     }
  28:     
  29:     return result;
  30: }

可以看到IPCThreadState將會直接調用BBinder的transact方法來處理客戶端請求,我們再看一下BBinder的transact方法:

   1: status_t BBinder::transact(
   2:     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
   3: {
   4:     data.setDataPosition(0);
   5:  
   6:     status_t err = NO_ERROR;
   7:     switch (code) {
   8:         case PING_TRANSACTION:
   9:             reply->writeInt32(pingBinder());
  10:             break;
  11:         default:
  12:             err = onTransact(code, data, reply, flags);
  13:             break;
  14:     }
  15:  
  16:     if (reply != NULL) {
  17:         reply->setDataPosition(0);
  18:     }
  19:  
  20:     return err;
  21: }

我們發現他將會叫用自己的虛函數onTransact。我們前面提到所有的Service都集成自BBinder,並且都改寫了onTransact虛函數。那麼IPCThreadState將會調用Service定義onTransact方法來響應客戶請求。

5、結論

    本文簡單介紹了一下系統Service的原理,臺灣的高煥堂先生有一篇文章,手把手教怎樣實現一個系統Service,你可以在我的博文《(轉)高煥堂——Android框架底層結構知多少?》中找到。

 


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