從Android6.0源碼的角度剖析Binder工作原理

從Android 6.0源碼的角度剖析Activity的啓動過程一文中,我們瞭解到Activity的啓動過程最終由系統服務ActivityManagerService完成,ActivityManagerServer是繼承於Binder且運行在系統進程中,Activity的啓動實質是一次基於Binder機制的跨進程通信。除此之外,Android系統還爲應用程序提供了各種系統服務,比如多媒體播放、音視頻獲取、讀取傳感器數據等,它們之間的交互都是由Binder機制實現的。那麼,所謂的Binder究竟是什麼?實際上,Binder並不是一個確切的概念,它在不同的層次表述大不相同,比如通常意義下,Binder指Android系統中特有的一種跨進程通信方式;從用戶空間的角度來說,對於Server進程,Binder指Binder本地對象,而對於Client進程,Binder指Binder代理對象;從內核空間的角度來說,Binder指Binder驅動;從傳輸通信的角度來說,Binder是可以跨進程傳遞的對象

1. Binder基本原理

1.IPC與Binder簡介

進程是程序的實體,它是程序的一次運行活動,同時也是操作系統資源分配和調度的基本單位。在操作系統中運行着許許多多的進程,爲了保證系統的有序運行和進程間互不干擾,操作系統引入了進程隔離的概念來確保不同進程之間相互獨立。進程隔離使用了虛擬地址空間技術,該技術通過爲不同的進程分配不同的虛擬地址,使得對於每個進程來說都以爲自己獨享了整個系統,完全不知道其他進程的存在,這樣就避免了進程間錯誤的相互寫入數據而導致進程無法正常運行。然而,雖然進程隔離能夠確保每個進程的數據安全,不被惡意破壞,但畢竟操作系統是一個有機的的統一整體,就像人體樣,雖然人體的各個器官也是相互獨立,但是若要完成某一個行爲,就需要在大腦的控制下對相關器官進行調配,同時器官之間也會相互傳遞信號,操作系統亦是如此。操作系統是管理計算機硬件與軟件資源的計算機程序,它由內核、驅動程序、接口庫及外圍組成,其中,內核是操作系統的核心,擁有訪問受保護的內存空間和訪問底層硬件設備的所有權限。當操作系統需要執行某個任務時,必然需要系統中相關進程在內核的控制下進行協作,既然是相互協作,就必然牽涉到進程間的數據交互,爲了實現這個目的,跨進程通信技術開始"閃亮登場"。

1.1 IPC,跨進程通信

跨進程通信(IPC,Interprocess Communication)是一組編程接口,它允許在一個操作系統中不同進程之間傳遞或交換信息,其存儲-轉發方式通信過程大致爲:假設有兩個運行在用戶空間的進程A、B,進程A要給進程B發送數據,那麼進程A會通過系統調用copy_from_user將數據copy到內核空間,然後把內核空間通過系統調用copy_to_user將對應的數據copy到進程B即完成。下圖爲IPC通信模型:
在這裏插入圖片描述

用戶空間內核空間是人們從邏輯上抽離出來的概念,旨在區分操作系統中普通的應用程序和內核。內核是操作系統的核心,它擁有訪問受保護內存空間和底層硬件設備的所有權限,維持着整個操作系統的正常運行。爲了保護內核不受破壞,普通的應用程序被授予有限的資源訪問權限,如果普通的應用程序需要訪問受限的資源,就需要通過系統調用通過內核來訪問這些被保護的資源。用戶空間訪問內核空間通過系統調用實現,用戶空間訪問用戶空間則需要通過內核模塊/驅動來實現。

 Android系統是基於Linux內核實現的,自然支持Linux系統中的IPC方式,這些方式包括管道、System V IPC(包括消息隊列/共享內存/信號燈)和socket。其中,管道是一種半雙工的通信方式,數據只能單向流通且只能在具有父子進程關係的進程間使用; System V IPC是Linux系統爲了彌補管道在進程間通信的不足所引入,它包括消息隊列、信號燈和共享內存三種進程間通信機制,它們共享通用的認證方式,即進程在使用某種類型的IPC資源以前,必須通過系統調用傳遞一個唯一的引用標識符到內核來訪問這些資源;Socket套接字是一種通用的接口,用於跨網絡的進程間通信和本機上進程間的低速通信,並且支持Client-Server的通信方式。
下表爲上述5種IPC方式區別:

**IPC ** 實現方式 數據拷貝次數 安全性 其他特點
管道 存儲-轉發 2 僅限父子進程間通信
共享內存 內存映射 0 控制複雜
消息隊列 存儲-轉發 2 克服信號傳遞信息少,管道只能承載無格式字節流以及緩衝區大小受限的缺點
信號量 計數器 0 作爲一種共享資源訪問的同步手段
Socket 特殊文件 2 跨網絡傳輸,效率低、開銷大

(1) C/S結構:Client-Server結構是一種網絡架構,它把客戶端與服務器區分開來。客戶端發送請求到服務器,服務器接收並處理請求,然後返回結果給客戶端。在Android系統中,大部分系統服務都是通過這種架構爲應用程序提供服務,從而讓應用程序擁有豐富的功能。
(2) 存儲-轉發方式:數據先從發送方緩存區拷貝到內核開闢的緩存區中,然後再從內核緩存區拷貝到接收方緩存區,因此整個過程需要拷貝兩次。

1.2 Binder簡介

 雖然Android系統是基於Linux系統實現的,但它並沒有使用上述的5種方式作爲系統的進程間通信方式,主要是由這幾種方式要麼是開銷過大,要麼就是安全性低。因爲Android系統作爲一種嵌入式系統,設備資源相對有限,因此對相關的性能要求也非常高,過大的開銷會嚴重影響系統的運行性能。另外,Android系統是開放式的,擁有衆多的開發者平臺,應用程序的來源也非常廣泛,同時傳統的IPC方式無法獲得對方進程可靠的UID/PID進行身份校驗,這會直接影響智能設備的安全。基於此,Android系統建立了一套新的IPC機制來滿足系統中對較高的傳輸性能和安全性通信要求,這種Android特有的IPC機制就是Binder機制。
 Binder是基於OpenBinder實現的,OpenBinder由Google公司的Dianne Hackborn開發,旨在提供一個簡單的進程間互相通訊的途徑。Binder機制採用C/S通信模型,它使用Binder來作爲Server服務對外的訪問接入點和Client向Server發起服務請求的"地址",並且在進程間通信的過程中,數據傳輸只需拷貝一次,並且Client的身份驗證標誌(UID/PID)只能由Binder機制在內核中添加,因此具有安全性高傳輸性能好等優勢。與其他IPC機制不同,Binder使用了面向對象的思想來描述Server端的訪問接入點和Client端的服務請求發起地址,具體來說就是Server端的訪問接入點實質是位於Server進程中的一個Binder實體對象,該對象提供了一套方法用於向Client端提供各種服務;Client端的“地址”即爲Binder實體對象的引用,Client將持有該引用向Server端發起服務請求。下圖爲Binder機制的C/S模型:
在這裏插入圖片描述
 雖說Binder機制的底層代碼由C實現,但面向對象思想的引入將進程間通信轉化爲通過對某個Binder對象的引用並調用該對象的方法,而其獨特之處在於Binder對象是一個可以跨進程引用的對象,它的實體位於一個進程中,而它的引用卻遍佈於系統的各個進程之中

2.Binder通信框架

 基於Binder機制的進程間通信,其通信框架主要涉及四個角色,即Server進程、Client進程、ServerManager進程以及Binder驅動,其中,Server、Client和ServerManager運行在用戶空間,Binder驅動運行在內核空間。Binder驅動是Binder通信框架的核心,它工作於內核空間,主要負責進程間Binder通信的建立、Binder在進程之間的傳遞、Binder引用計數管理以及數據包在進程之間的傳遞和交互等一系列底層支持;Server進程用於向Client進程提供遠程服務,該進程會創建一個Binder實體(對象),併爲其取一個字符串形式的名字,當該Binder實體被Binder驅動在ServerManger進行實名註冊後,我們又稱這個Binder實體爲“實名Binder”,它將擔負起向Client提供具體的遠程服務;Client進程即爲我們的APP,它將通過遠程Binder實體的引用訪問遠程Server,獲取相關的服務,這裏爲什麼不是直接通過Binder實體訪問,我們在後面的Binder機制原理再詳述;ServerManager是一個系統進程,它管理着一張“查詢表”,該表記錄了Server進程中Binder實體名字到Client中對該Binder實體引用的對應關係,以便使Client能夠通過Binder名字獲得對Server中Binder實體的引用。Binder通信框架結構圖如下:
在這裏插入圖片描述
 在Binder機制通信模型中,Server、Client、ServerManager以及Binder驅動的關係有點類似於互聯網,它們分別對應於互聯網中的服務器、客戶端、域名服務器(DNS)以及路由器,其中,服務器用於向客戶端提供服務且對外接入點爲IP地址;客戶端用於向服務器發起請求服務,且發起"地址"通常爲域名;域名服務器提供遠程服務器的IP地址與其域名映射關係,便於客戶端能夠通過域名直接訪問服務器;路由器用於網絡管理、數據處理等,是互聯網絡的樞紐。Binder通信框架流程圖如下:
在這裏插入圖片描述
大致過程爲:

  • 首先,系統中某個進程向Binder驅動發起申請爲ServerManager進程,該進程將建立一張系統中相關Server進程“名字”及其“地址”的映射表(查詢表);
  • 其次,Server進程將自己“名字”和“地址”添加到ServerManager進程的查詢表中;
  • 最後,Client進程從ServerManager進程獲取到遠程Server進程的真實“地址”,即建立Binder通信完畢。
3.Binder機制原理

 前面談論到大部分傳統的IPC都是基於存儲-轉發的方式實現的,即進程A通過系統調用copy_from_user將數據從用戶空間拷貝到內核空間,然後再通過系統調用copy_to_user將數據拷貝從內核空間拷貝到進程B,整個通信過程數據需要拷貝2次。但是Binder機制卻不是這麼做的,而是把所有的工作均交給Binder驅動來完成,並且Binder本質上只是一種底層通信方式和具體服務沒有關係。爲了提供具體服務(或稱能力),Server必須提供一套接口函數以便Client通過遠程訪問使用各種服務,這裏使用代理(Proxy)模式來實現,即**將接口函數定義在一個抽象類中,Server和Client均以該抽象類爲基類實現所有的接口函數,其中Server端是真正的功能實現併爲每個函數進行一一編號以便Client精準調用,而Client端則是對這些函數遠程調用請求的包裝。此外,Server端還定義了一個Binder抽象類來處理來自Client的Binder請求數據包,其中最重要的成員函數是虛函數onTransact(),該函數將用於分析收到的數據包,調用相應的接口函數處理請求,並將最終的調用結果返回給Client。整個通信過程都是在Binder驅動的控制下完成的,並且Binder在Server中的實體是通過採用繼承方式以接口類和Binder抽象類爲基類構建的。**接下來,我們藉助Binder學習指南一文中的一張圖來詳細剖析下Binder機制通信過程,瞭解Binder驅動、ServerManager(SM)在整個通信過程中所起的作用。
在這裏插入圖片描述
 爲了深入理解基於Binder機制的進程間通信原理,這裏假設Server進程中有個Object對象(即Binder實體),它提供一個add方法供遠程調用,Client進程將通過Binder機制的方式訪問Server進程中Object對象的add方法,具體的通信過程如下:

3.1 Server在SM中註冊實名Binder

 在Server進程中有一個Object對象(即Binder實體,下述均以Binder實體描述),它提供一個add方法,爲了Client能夠找到自己並與之通信,Server進程爲Binder實體創建了一個字符形式的名字,然後再將Binder實體及其名字以數據包的形式通過Binder驅動發送給ServerManager進行註冊,其註冊過程爲:
 首先,Binder驅動接收到Server發過來的數據包後,會取出數據包中的Binder實體及其名字,併爲該Binder實體創建位於內核中的實體節點,並生成與其名字對應的引用
 然後,Binder驅動將Binder的名字和新建的引用打包傳遞給ServerManager,ServerManager收到數據包後從中取出名字和引用填入一張查找表中,這張表就像一個“通訊錄”且是系統唯一的,它記錄了系統中各種Server的名字(Binder實體字符形式名字)和地址(Binder實體的引用),而被註冊的這個Binder實體也稱爲實名Binder。

3.2 Client從SM獲得實名Binder的引用

 Client進程要想訪問Server進程的Binder實體的add方法,會將要訪問Binder實體的名字以數據包的形式發送給Binder驅動,Binder驅動取出名字查詢ServerManager中的查詢表即可獲得Binder實體及其引用。但是Binder驅動並沒有將真正的Binder實體返回給Client,而是“照着”Binder實體的樣子仿造一個一模一樣的對象作爲代理返回給Client,這個對象又被稱之爲代理對象ProxyBinder,它持有Binder實體的引用,且擁有與Binder實體完全相同能力(即方法),只是這些能力只是個“空殼”,真正的具體實現還是在Server進程的Binder實體中。由於驅動返回的代理對象(ProxyBinder)與Server進程中的Binder實體如此相似,給人的感覺好像是直接把Server進程Binder實體(對象)傳遞到了Client進程,因此,我們可以說Binder對象是可以跨進程傳遞的對象,而實際上Binder對象並沒有傳遞,傳遞的僅僅是Binder對象的引用,它將通過代理對象來承載。也就是說,Server進程中Binder對象指Binder實體(也稱Binder本地對象),Client進程中Binder對象指的是Binder代理對象。在Binder對象進行跨進程傳遞的時候,Binder驅動會自動完成這兩種類型的轉換。
 需要注意的是,Binder驅動返回一個Binder實體的代理對象給Client是基於Client與Server歸屬於不同進程而言的,如果Client和Server歸屬於同一個進程,Binder驅動將直接將Server進程的Binder實體返回給Client。由於本文主要是考慮Client與Server歸屬於不同進程情況,因此待Client獲得代理對象ProxyBinder的那一刻,基於Binder機制的Client與Server遠程通信鏈路建立完畢。

3.3 Client與Server跨進程通信

 在Binder驅動返回一個Binder的代理對象給Client進程後,Client進程就可以通過該代理對象與遠程Server進程進行通信。Binder代理對象繼承了Server提供的公共接口類並實現公共函數(注:並不是真正的實現,真正的實現在Server進程的Binder實體中),是對遠程函數調用的包裝。接下來,我們分析下Client訪問Server中方法通信過程:(1) Client進程首先會將函數參數和Binder實體的引用以數據包的形式進行打包,然後將數據包發送給Binder驅動向指定Server發送請求,此後Client進程進入掛起狀態,以等待返回值;(2) Binder驅動收到Client進程發送過來的數據包後,取出Binder實體的引用,獲得目的Server並將其喚醒,再將數據包發送給它處理。這裏需要提下的是,由於該引用本來就是Binder驅動創建並交給ServerManager註冊用的,因此Binder驅動自然很容易就能夠通過該引用找到能夠接收數據包的Server和獲得指向Binder實體對應的內存空間;(3) Server進程收到Binder驅動發送過來的Binder請求數據包後,Server進程會利用之前開闢好線程池中的線程來處理該請求,通過調用Binder實體中的onTransact()函數,對收到的數據包進行分析,即取出數據包中請求的函數接口編碼,case-by-case地解析code值,待解析成功後,再從數據包中取出函數參數並調用相應的接口函數處理請求,然後Server進程會將調用結果發送給Binder驅動;(4) Binder驅動收到Server進程返回的調用結果後,就會喚醒處於等待中的Client進程,並將結果返回給它,至此,一次跨進程通信完畢。

2. Java層Binder框架解析

 在Android系統中,Binder框架由C/C++底層和Java上層構成,其中C/C++底層提供功能實現,Java上層爲應用進程間的通信提供接口。由於C/C++層底層實現極其複雜,本文暫不涉及這部分內容,本節將詳細剖析Java層部分。根據Binder機制原理,Binder框架Java層部分主要包含四部分,即公共接口(IIterface)Binder接口(IBinder)Binder實體(或稱Binder本地對象)以及Binder代理對象(BinderProxy),它們各自的作用如下:

  • IIterface

 IIterface是Android提供的一個接口,它表明遠程Server對象具有什麼樣的能力,可理解爲Server和Client契約,Binder本地對象和Binder代理對象均需實現該接口。Interface接口中只包含一個asBinder方法,該方法用於返回與該IInterface綁定的Binder本地對象。IIterface源碼如下:

public interface IInterface
{
    // 返回與該IIterface綁定的Binder實體對象
    public IBinder asBinder();
}

 代表了一種跨進程傳輸的能力,實現該接口就能將這個對象進行跨進程傳遞,IBinder負責數據傳遞。在跨進程數據流經驅動的時候,驅動會識別IBinder類型的數據,從而自動完成不同進程Binder本地對象以及Binder代理對象的轉換。


public interface IBinder {
   	// 代碼省略
    ...
    // 返回綁定在該Binder對象的IInterface有關的描述
    public @Nullable String getInterfaceDescriptor() throws RemoteException;
	// 判斷Binder通信鏈路是否斷開
    public boolean isBinderAlive();
 	// 獲取descriptor對應的本地IIterface,如果返回爲空,說明
    // Client和Server歸屬於不同進程
    public @Nullable IInterface queryLocalInterface(@NonNull String descriptor);
	// 代碼省略
    ...
    // 處理Binder請求
    // 	code:要執行的函數編碼
    //  data:函數參數
    //  reply:返回值
    //  flags:附加標誌,暫時忽略
    public boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply,
                            int flags)throws RemoteException;
	
    // Binder鏈接死亡(斷開)回調接口
    public interface DeathRecipient {
        public void binderDied();
    }

    // 註冊Binder鏈接斷開通知
    // 即當Binder鏈接斷開時,DeathRecipient接口的binderDied方法會被回調
    public void linkToDeath(@NonNull DeathRecipient recipient, int flags)
            throws RemoteException;
	// 移除已註冊的Binder鏈接斷開通知
    public boolean unlinkToDeath(@NonNull DeathRecipient recipient, int flags);
}
  • Binder

 Binder實體對象,位於Server進程中,它繼承了IBinder,從而具有跨進程傳輸的能力,但在實際通信過程中,Binder實體對象並沒有傳輸,傳輸的只是該對象的引用。

  • Binder代理對象

 遠程進程Binder對象的代理,位於Client進程中,它持有IBinder引用,也可以理解擁有跨進程傳輸的能力。

AIDL工作原理

 AIDL(Android Interface Definition Language),即Android接口定義語言,是Android系統爲了便於開發具備跨進程通信的應用,專門提供的且用於自動生成Java層Binder通信框架的技術。AIDL的使用比較簡單,我們只需要編寫符合AIDL開發規範的源碼文件,AS就會自動生成用於跨進程通信的相關文件。這裏以Server端向Client提供"加法計算"服務(能力)爲例,詳細剖析Java層Binder通信框架原理。
 首先,我們在工程中創建一個以".aidl"爲後綴的源文件,文件命名爲IComputeInterface,並提供一個add方法;

package com.jiangdg.hellobinder;

interface IComputeInterface {
    int add(int a,int b);
}

 其次,"Build->make project"工程後AS就會自動在"app/build/generated/…/com/jiangdg/hellobuilder"目錄生成一個名爲IComputeInterface.java接口文件。代碼框架大致如下:

public interface IComputeInterface extends android.os.IInterface{
    // Binder實體
    public static abstract class Stub extends android.os.Binder implements 
        com.jiangdg.hellobinder.IComputeInterface{
        ...
            
        // Binder實體的代理對象
    	private static class Proxy implements 
            			com.jiangdg.hellobinder.IComputeInterface{
        	...
    	}
    }
    
    // 公共方法
	public int add(int a, int b) throws android.os.RemoteException;
}

 從IComputeInterface.java源碼我們可以大致看出,它主要包含三部分,即接口IComputeInterface,靜態抽象類Stub、靜態類Proxy,並由此構成Java層的Binder通信框架。接下來,我們就來分析它們之間有何關聯以及起到的作用是什麼?

(1) IComputeInterface:公共接口

 IComputeInterface繼承於接口IInterface,它包含一個add方法且拋出RemoteException異常,由此可知add方法應該是一個被遠程訪問的方法。根據Binder機制原理,我們自然容易明白IComputeInterface接口就是一個“契約”接口,它表明Server端能夠像Client端提供哪些服務,也是Binder機制中的代理訪問的實現基礎,Server中的Binder實體和Client中的Binder實體的代理均需要實現它,其中,在Binder實體中爲add方法真正的實現,在Binder實體的代理對象中只是對add方法的遠程調用請求包裝,在接下來的分析中可以驗證這一點。

public interface IComputeInterface extends android.os.IInterface{
	public int add(int a, int b) throws android.os.RemoteException;
}

(2) IComputeInterface.Stub:Binder本地對象

 從 IComputeInterface的源碼可知,Stub是IComputeInterface的一個靜態抽象內部類,但是這不是關鍵的,也僅是AIDL中的生成代碼的一種形式而已,真正重要的是Stub繼承了Binder類和IComputeInterface接口,而Binder又繼承於IBinder。根據Binder機制原理,我們就可以得出Stub就是位於Server端中的Binder實體或稱Binder本地對象,它的源碼如下:

public static abstract class Stub extends android.os.Binder implements 
    com.jiangdg.hellobinder.IComputeInterface{
    // 表明IComputeInterface是本地接口描述
	private static final java.lang.String DESCRIPTOR = 
        							"com.jiangdg.hellobinder.IComputeInterface";
	// 將Stub本身(即Binder實體對象)綁定到接口Interface
	public Stub(){
		this.attachInterface(this, DESCRIPTOR);
	}
    // 將Binder實體對象轉換爲IInterface,即創建Binder實體的代理對象,如果需要的話
	public static com.jiangdg.hellobinder.IComputeInterface 
        							asInterface(android.os.IBinder obj){
		if ((obj==null)) {
			return null;
		}
		android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
		if (((iin!=null)&&(iin instanceof com.jiangdg.hellobinder.IComputeInterface))){
			return ((com.jiangdg.hellobinder.IComputeInterface));
		}
		return new com.jiangdg.hellobinder.IComputeInterface.Stub.Proxy(obj);
	}
	
    // 返回Binder實體對象本身
    @Override 
    public android.os.IBinder asBinder(){
		return this;
	}
	
    // 分析處理Binder請求數據包,根據code找到相應的節點
    // 調用相應的方法處理請求
    @Override 
    public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException{
		switch (code){
			case INTERFACE_TRANSACTION:
			{
				reply.writeString(DESCRIPTOR);
				return true;
			}
            case TRANSACTION_add:
            {
            	data.enforceInterface(DESCRIPTOR);
            	int _arg0;
            	_arg0 = data.readInt();
            	int _arg1;
            	_arg1 = data.readInt();
            	int _result = this.add(_arg0, _arg1);
            	reply.writeNoException();
            	reply.writeInt(_result);
            	return true;
            }
		}
		return super.onTransact(code, data, reply, flags);
	}
	static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}

 接下來,我們着重分析下Stub類的工作原理,這裏從asInterface方法入手,該方法主要的作用是判斷Binder驅動傳遞過來的Binder對象obj類型,來決定是否想需要返回Binder對象的代理對象Proxy,即調用obj的queryLocalInterface方法判斷傳入的DESCRIPTOR(接口描述)是否與obj綁定的一致,如果一致,則表明Client與Server歸屬於同一個進程,直接將Binder本地對象返回給Client;如果不一致,則表明Client與Server不屬於同一個進程,就需要將obj作爲參數實例化一個Binder本地對象的代理Proxy給Client。onTransact方法用於分析處理Binder驅動發來的請求數據包,如果Client與Server屬於同一個進程,當Client要訪問Server中的add方法時,onTransact就會被直接調用,不再經歷代理調用步驟。

(3) IComputeInterface.Stub.Proxy

 Proxy是Stub的一個靜態內部類,同樣也不是關鍵的,僅是AIDL中的生成代碼的一種形式而已,真正重要的是Proxy繼承了IComputeInterface接口,並持有一個IBinder對象的引用。根據Binder機制原理,我們就可以得出Proxy就是位於Client端中的Binder本地對象的代理。從Proxy的源碼可知,它不僅持有遠程Binder實體的引用,還重寫了公共方法add,該方法將Client要訪問遠程方法的參數封裝在Parcel對象中,然後調用遠程Binder實體的transact方法發起跨進程調用。通過查看Android源碼可知,transact方法的實現位於native層,它最終調用talkwithDriver函數將請求參數打包交給Binder驅動,Binder驅動識別後,最終會調用遠程Server中Binder實體的onTransact方法,即Stub的onTransact方法進行處理。需要注意的是,在實際開發中,Stub中onTransact方法所調用的add方法將由我們自己實現,待add執行完畢會將結果填入Parcel中以便Binder驅動返回給Client。Proxy源碼如下:

private static class Proxy implements com.jiangdg.hellobinder.IComputeInterface
{
	// 遠程Binder實體對象
	private android.os.IBinder mRemote;
	Proxy(android.os.IBinder remote){
		mRemote = remote;
	}
	
	// 返回與代理對象對應的Binder實體
	@Override 
	public android.os.IBinder asBinder(){
		return mRemote;
	}

	public java.lang.String getInterfaceDescriptor(){
		return DESCRIPTOR;
	}
	
	// 對遠程調用的封裝
	@Override 
	public int add(int a, int b) throws android.os.RemoteException{
		android.os.Parcel _data = android.os.Parcel.obtain();
		android.os.Parcel _reply = android.os.Parcel.obtain();
		int _result;
		try {
			_data.writeInterfaceToken(DESCRIPTOR);
			_data.writeInt(a);
			_data.writeInt(b);
			// 調用遠程Binder實體的transact方法
			// 開始處理訪問請求
			mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
			_reply.readException();
			_result = _reply.readInt();
		}
		finally {
			_reply.recycle();
			_data.recycle();
		}
		return _result;
	}
}

 至此,關於對Binder機制的分析將告一段落,最後,我們採用Android Binder設計與實現中的一段原話爲Binder機制作個總結:Binder模糊了進程邊界,淡化了進程間通信過程,整個系統彷彿運行於同一個面向對象的程序之中,形形色色的Binder對象及其星羅棋佈的引用彷彿粘接各個應用程序的膠水,這也是Binder在英文的原意。

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