1. 程式人生 > >interface_cast和asBinder原始碼分析

interface_cast和asBinder原始碼分析

研究Android底層程式碼時,尤其是Binder跨程序通訊時,經常會發現interface_cast和asBinder,很容易被這兩個函式繞暈,下面通過分析原始碼來講解一下:

interface_cast

下面根據下述ICameraClient例子進行分析一下:

//虛擬碼
sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(BpBinder(handle));

看下interface_cast的實現,其程式碼在IInterface.h中

template<typename INTERFACE>
inline
sp<INTERFACE> interface_cast(const sp<IBinder>& obj) { return INTERFACE::asInterface(obj); } //這是一個模板函式,展開即為: inline sp<ICameraClient > interface_cast(const sp<IBinder>& obj) { return ICameraClient ::asInterface(obj); }

那ICameraClient的asInterface在哪實現的呢?發現找了ICameraClient.h和ICameraClient.cpp只有下面兩個定義:

//frameworks/av/include/camera/android/hardware/ICameraClient.h
DECLARE_META_INTERFACE(CameraClient);

//frameworks/av/camera/ICameraClient.cpp
IMPLEMENT_META_INTERFACE(CameraClient, "android.hardware.ICameraClient");

DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE函式是其父類IInterface(frameworks\native\include\binder\IInterace.h)的巨集定義:

//宣告asInterface函式
#define DECLARE_META_INTERFACE(INTERFACE)
    static const android::String16 descriptor;
    //宣告asInterface函式
    static android::sp<I##INTERFACE> asInterface( 
            const android::sp<android::IBinder>& obj);
    virtual const android::String16& getInterfaceDescriptor() const;
    I##INTERFACE();
    virtual ~I##INTERFACE();

展開為:
#define DECLARE_META_INTERFACE(CameraClient)
    //增加一個描述符
    static const android::String16 descriptor;
    //宣告asInterface函式
    static android::sp<ICameraClient> asInterface( 
            const android::sp<android::IBinder>& obj);
    //獲取描述符函式
    virtual const android::String16& getInterfaceDescriptor() const;
    //建構函式以及折構函式
    ICameraClient();
    virtual ~ICameraClient();

//實現asInterface函式
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)
    const android::String16 I##INTERFACE::descriptor(NAME); 
    const android::String16& 
            I##INTERFACE::getInterfaceDescriptor() const { 
        return I##INTERFACE::descriptor; 
    }                                               
    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); //展開即為intr = new BpServiceManager(obj);
            }
        }
        return intr;
    }
    I##INTERFACE::I##INTERFACE() { }
    I##INTERFACE::~I##INTERFACE() { }

展開為:
#define IMPLEMENT_META_INTERFACE(CameraClient, "android.hardware.ICameraClient")
    //定義ICameraClient的描述符為"android.hardware.ICameraClient"
    const android::String16 ICameraClient ::descriptor("android.hardware.ICameraClient"); 
    //獲取描述符"android.hardware.ICameraClient"
    const android::String16& 
            ICameraClient ::getInterfaceDescriptor() const { 
        return ICameraClient ::descriptor; 
    }                        
    //實現asInterface函式
    android::sp<ICameraClient> ICameraClient::asInterface(
            const android::sp<android::IBinder>& obj)
    {
        android::sp<ICameraClient> intr; 
        if (obj != NULL) {
            intr = static_cast<ICameraClient*>(
                //queryLocalInterface是在IBinder中定義的,預設返回NULL,但在BBinder的子類BnInterface中,過載了該方法,返回this,而BpBinder沒有過載,使用IBinder的預設實現,返回NULL
                obj->queryLocalInterface( 
                        ICameraClient::descriptor).get()); 
            if (intr == NULL) {
                //構建INTERFACE的Bp端代理物件
                intr = new BpCameraClient(obj);
            }
        }
        return intr;
    }
    ICameraClient::ICameraClient() { }
    ICameraClient::~ICameraClient() { }

總結一下, 如果interface_cast的引數obj是BnInterface,則返回其自身,如果引數obj是BpInterface,則new一個Bp代理物件並返回。這裡我們用的是ICameraClient例子來講解的,則返回BpCameraClient,別的介面也是同樣分析的,比如IServiceManager,也會有類似宣告如下,則返回BpServiceManager。

//frameworks\native\include\binder\IServiceManager.h
DECLARE_META_INTERFACE(ServiceManager);

//frameworks\native\libs\binder\IServiceManager.cpp
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");

asBinder

接著使用上面ICameraClient例子進行分析一下:

//虛擬碼,根據interface_cast的分析,知道cameraClient即為BpCameraClient(BpBinder(handle))
sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder());
IInterface::asBinder(cameraClient);

看下asBinder的方法,在IInterface.cpp中

sp<IBinder> IInterface::asBinder(const IInterface* iface)
{
    if (iface == NULL) return NULL;
    return const_cast<IInterface*>(iface)->onAsBinder();
}

sp<IBinder> IInterface::asBinder(const sp<IInterface>& iface)
{
    if (iface == NULL) return NULL;
    return iface->onAsBinder();
}

都會走到onAsBinder方法

BnInterface

BnInterface的onAsBinder方法,直接返回自身,因為BnInterface繼承自BBinder,而BBinder又繼承自IBinder

template<typename INTERFACE>
IBinder* BnInterface<INTERFACE>::onAsBinder()
{
    return this;
}

根據例子展開為:
template<typename ICameraClient>
IBinder* BnInterface<ICameraClient>::onAsBinder()
{
    return this;
}

BpInterface

BpInterface的onAsBinder方法,呼叫remote()方法並返回

template<typename INTERFACE>
inline IBinder* BpInterface<INTERFACE>::onAsBinder()
{
    return remote();
}

根據例子展開為:
template<typename ICameraClient >
inline IBinder* BpInterface<ICameraClient>::onAsBinder()
{
    return remote();
}

remote()方法在其父類BpRefBase中實現,就是返回mRemote變數

inline  IBinder*        remote()                { return mRemote; }

而mRemote變數是在建立BpInterface物件時,將remote變數傳給了其父類BpRefBase,我們這個例子裡面remote就是BpBinder(handle)

template
inline BpInterface::BpInterface(const sp& remote)
: BpRefBase(remote)
{
}

BpRefBase::BpRefBase(const sp& o)
: mRemote(o.get()), mRefs(NULL), mState(0)
{
extendObjectLifetime(OBJECT_LIFETIME_WEAK);

if (mRemote) {
    mRemote->incStrong(this);           // Removed on first IncStrong().
    mRefs = mRemote->createWeak(this);  // Held for our entire lifetime.
}

}
“`

總結一下, 如果asBinder的引數iface是BnInterface型別,則返回其自身,如果引數iface是BpInterface型別,則返回其mRemote遠端代理物件BpBinder(handle) 。

相關推薦

interface_castasBinder原始碼分析

研究Android底層程式碼時,尤其是Binder跨程序通訊時,經常會發現interface_cast和asBinder,很容易被這兩個函式繞暈,下面通過分析原始碼來講解一下: interface_cast 下面根據下述ICameraClient例子進行分析

原始碼】防抖節流原始碼分析

前言 防抖、節流主要用於頻繁事件觸發,例如滑鼠移動、改變視窗大小等。lodash等函式庫具備相對應的api, _.debounce 、_.throttle。 核心技術:閉包。 區別: 防抖, 連續觸發, 第一次和最後一次觸發有效 節流, 一段時間內僅觸發一次(第一次) 本文以防抖函式為

python3 整數型別PyLongObject PyObject原始碼分析

python3 整數型別PyLongObject 和PyObject原始碼分析一 測試環境介紹和準備測試環境:作業系統:windows10Python版本:3.7.0 下載地址VS版本:vs2015社群版(免費) 下載地址win10SDK(安裝vs2015是可以選擇,如果沒有安裝則需要獨立安裝)http://

資料結構(三)StackVector原始碼分析

一、基本概念: 1、棧是什麼? 是一個只能在某一端進行插入、刪除操作的線性表。 * 從棧頂插入一個元素稱之為入棧(push) * 從棧頂刪除一個元素稱之為出棧(pop) 2、圖解: 3、棧的實現: 鏈式儲存(連結串列) 順序儲存(陣列) 4

30.以太坊原始碼分析(30)eth-bloombitsfilter原始碼分析

以太坊的布隆過濾器 以太坊的區塊頭中包含了一個叫做logsBloom的區域。 這個區域儲存了當前區塊中所有的收據的日誌的布隆過濾器,一共是2048個bit。也就是256個位元組。 而我們的一個交易的收據包含了很多的日誌記錄。 每個日誌記錄包含了 合約的地址, 多個Topic。 而在我

ComparableComparator原始碼分析與對比

Comparable使用  Comparable只是一個簡單的介面, public interface Comparable<T> { public int compareTo(T o); } 使用如下: public class Person imp

javaIO(4):Reader,InputStreamReaderFileReader原始碼分析

前言 前面把OutputStream,InputStream和Writer體系講了,同時也講了“裝飾者模式”在IO體系中的應用。Reader體系跟前面的很相似。本文就將最後一個Reader體系給講了。 正文 一,Reader原始碼 package

javaIO(1):OutputStreamFileOutputStream原始碼分析及“裝飾者模式”在IO中的應用

前言 一,IO體系 從現在起,我們將基於JDK1.8詳細介紹java.io包中的關於輸入輸出有關的類。瞭解過這個包的都知道,裡面的類繼承關係錯綜複雜,光是弄清楚這些類的關係就夠喝一壺的了。說實話,我也沒有什麼好的方法來一下子就能弄清這些類,但是如果你瞭解“裝

Java集合框架之Map---HashMapLinkedHashMap原始碼分析

1、HashMap概述:    HashMap是基於雜湊表的Map介面的非同步實現。此實現提供所有可選的對映操作,並允許使用null值和null鍵。此類不保證對映的順序,特別是它不保證該順序恆久不變。 2、HashMap的資料結構 資料結構中有陣列和連結串列來實現對資料的

Window windowManager原始碼分析

所有需要顯示在螢幕上的內容都要通過windowManager windowManager 是一個介面 三個方法 add remove update 他的具體實現類是windowManagerImpl類(橋接模式) 具體的實現是交給了windowManag

以太坊原始碼分析(30)eth-bloombitsfilter原始碼分析

## 以太坊的布隆過濾器以太坊的區塊頭中包含了一個叫做logsBloom的區域。 這個區域儲存了當前區塊中所有的收據的日誌的布隆過濾器,一共是2048個bit。也就是256個位元組。而我們的一個交易的收據包含了很多的日誌記錄。 每個日誌記錄包含了 合約的地址, 多個Topic。 而在我們的收據中也存在一個布隆

android中windowwindowManager原始碼分析(android-api-23)

一、前言 在android中window無處不在,如activity、dialog、toast等。它是view所依附的載體,每個window都對應於一個View和一個ViewRootImpl。ViewRootImpl就是Window和view的連線紐帶。windowMana

Android SettingsSettingsProvider原始碼分析與修改

StringACCESSIBILITY_DISPLAY_INVERSION_ENABLEDSetting that specifies whether display color inversion is enabled. StringACCESSIBILITY_ENABLEDIf accessibili

Mybatis原始碼分析(4)—— Mapper的建立獲取

Mybatis我們一般都是和Spring一起使用的,它們是怎麼融合到一起的,又各自發揮了什麼作用? 就拿這個Mapper來說,我們定義了一個介面,聲明瞭一個方法,然後對應的xml寫了這個sql語句, 它怎麼就執行成功了?這傢伙是怎麼實現的,帶著這個好奇心,我一步步跟蹤,慢慢揭開了它的

NSQ原始碼分析(四)——inFlightPqueuePriorityQueue優先順序佇列

   在Channel結構體中用到了兩種優先順序佇列pqueue.PriorityQueue和inFlightPqueue。 deferredMessages map[MessageID]*pqueue.Item deferredPQ pqueue.Priorit

Android原始碼分析之為什麼在onCreate() onResume() 獲取不到 View 的寬高

轉載自:https://www.jianshu.com/p/d7ab114ac1f7 先來看一段很熟悉的程式碼,可能在最開始接觸安卓的時候,大部分人都寫過的一段程式碼;即嘗試在 onCreate() 和 onResume() 方法中去獲取某個 View 的寬高資訊: 但是列印輸出後,我們會發

Android IntentService用法原始碼分析

關於IntentService的介紹,我個人覺得還是先看官方描述比較好: IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) o

zigbee 之ZStack-2.5.1a原始碼分析(三)無線資料傳送接收

前面說過SampleApp_Init和SampleApp_ProcessEvent是我們重點關注的函式,接下來分析無線傳送和接收相關的程式碼: 在SampleApp_ProcessEvent函式中: if ( events & SYS_EVENT_MSG ) {  &nbs

spring cloud EurekaClient 多網絡卡 ip 配置 原始碼分析

1、前言 對於spring cloud,各個服務例項需要註冊到Eureka註冊中心。 一般會配置ip註冊,即eureka.instance.prefer-ip-address=true。 但是,如果服務例項所在的環境存在多個網絡卡,經常會出現註冊過去的ip不是我們想要的ip。

jersey子資源api使用原始碼分析

1、前言 1.1 描述 檢視eureka server原始碼時候,用到了jersey實現api功能,其中包含了子資源路由api功能。 這裡主要分析下子資源的實現邏輯。 1.2 jersey簡介 jersey Jersey RESTful 框架是開源的