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_cast和asBinder原始碼分析
研究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://
資料結構(三)Stack和Vector原始碼分析
一、基本概念: 1、棧是什麼? 是一個只能在某一端進行插入、刪除操作的線性表。 * 從棧頂插入一個元素稱之為入棧(push) * 從棧頂刪除一個元素稱之為出棧(pop) 2、圖解: 3、棧的實現: 鏈式儲存(連結串列) 順序儲存(陣列) 4
30.以太坊原始碼分析(30)eth-bloombits和filter原始碼分析
以太坊的布隆過濾器 以太坊的區塊頭中包含了一個叫做logsBloom的區域。 這個區域儲存了當前區塊中所有的收據的日誌的布隆過濾器,一共是2048個bit。也就是256個位元組。 而我們的一個交易的收據包含了很多的日誌記錄。 每個日誌記錄包含了 合約的地址, 多個Topic。 而在我
Comparable和Comparator原始碼分析與對比
Comparable使用 Comparable只是一個簡單的介面, public interface Comparable<T> { public int compareTo(T o); } 使用如下: public class Person imp
javaIO(4):Reader,InputStreamReader和FileReader原始碼分析
前言 前面把OutputStream,InputStream和Writer體系講了,同時也講了“裝飾者模式”在IO體系中的應用。Reader體系跟前面的很相似。本文就將最後一個Reader體系給講了。 正文 一,Reader原始碼 package
javaIO(1):OutputStream和FileOutputStream原始碼分析及“裝飾者模式”在IO中的應用
前言 一,IO體系 從現在起,我們將基於JDK1.8詳細介紹java.io包中的關於輸入輸出有關的類。瞭解過這個包的都知道,裡面的類繼承關係錯綜複雜,光是弄清楚這些類的關係就夠喝一壺的了。說實話,我也沒有什麼好的方法來一下子就能弄清這些類,但是如果你瞭解“裝
Java集合框架之Map---HashMap和LinkedHashMap原始碼分析
1、HashMap概述: HashMap是基於雜湊表的Map介面的非同步實現。此實現提供所有可選的對映操作,並允許使用null值和null鍵。此類不保證對映的順序,特別是它不保證該順序恆久不變。 2、HashMap的資料結構 資料結構中有陣列和連結串列來實現對資料的
Window 和windowManager原始碼分析
所有需要顯示在螢幕上的內容都要通過windowManager windowManager 是一個介面 三個方法 add remove update 他的具體實現類是windowManagerImpl類(橋接模式) 具體的實現是交給了windowManag
以太坊原始碼分析(30)eth-bloombits和filter原始碼分析
## 以太坊的布隆過濾器以太坊的區塊頭中包含了一個叫做logsBloom的區域。 這個區域儲存了當前區塊中所有的收據的日誌的布隆過濾器,一共是2048個bit。也就是256個位元組。而我們的一個交易的收據包含了很多的日誌記錄。 每個日誌記錄包含了 合約的地址, 多個Topic。 而在我們的收據中也存在一個布隆
android中window和windowManager原始碼分析(android-api-23)
一、前言 在android中window無處不在,如activity、dialog、toast等。它是view所依附的載體,每個window都對應於一個View和一個ViewRootImpl。ViewRootImpl就是Window和view的連線紐帶。windowMana
Android Settings和SettingsProvider原始碼分析與修改
StringACCESSIBILITY_DISPLAY_INVERSION_ENABLEDSetting that specifies whether display color inversion is enabled. StringACCESSIBILITY_ENABLEDIf accessibili
Mybatis原始碼分析(4)—— Mapper的建立和獲取
Mybatis我們一般都是和Spring一起使用的,它們是怎麼融合到一起的,又各自發揮了什麼作用? 就拿這個Mapper來說,我們定義了一個介面,聲明瞭一個方法,然後對應的xml寫了這個sql語句, 它怎麼就執行成功了?這傢伙是怎麼實現的,帶著這個好奇心,我一步步跟蹤,慢慢揭開了它的
NSQ原始碼分析(四)——inFlightPqueue和PriorityQueue優先順序佇列
在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 框架是開源的