Android C++層使用Binder通訊的方法
文章目錄
本文以Audio系統為例,基於Android 7.1
1. 規範制定者 IInterface.h
IInterface.h是C++層Binder通訊的規範定製者, 客戶端和服務端都要包含該標頭檔案。
IInterface.h中提供了C++層Binder通訊必要的工具。
1. 客戶端規範
客戶端需要繼承BpInterface 和IInterface,這個是個模板類,作用其實是使客戶端物件繼承自模板物件,如下:
//frameworks/native/include/binder/IInterface.h
//IInterface 中定義了對Binder的轉換操作
class IInterface : public virtual RefBase
{
public:
IInterface();
static sp<IBinder> asBinder(const IInterface*);
static sp<IBinder> asBinder(const sp<IInterface>&);
protected:
virtual ~IInterface();
virtual IBinder* onAsBinder() = 0;
};
//BpInterface
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase //**BpRefBase 中有個remote()函式,
//直接指向服務端Bind而物件
{
public:
//remote使服務端Binder物件
BpInterface(const sp<IBinder>& remote);
protected:
virtual IBinder* onAsBinder();
};
BpRefBase
BpRefBase 繼承自RefBase,所以在首次引用的時候會呼叫onFirstRef方法
//frameworks/native/include/binder/Binder.h
class BpRefBase : public virtual RefBase
{
protected:
BpRefBase(const sp<IBinder>& o);
virtual ~BpRefBase();
virtual void onFirstRef();
virtual void onLastStrongRef(const void* id);
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
//remote()函式直接使用,就是代表了服務端物件
inline IBinder* remote() { return mRemote; }
inline IBinder* remote() const { return mRemote; }
private:
BpRefBase(const BpRefBase& o);
BpRefBase& operator=(const BpRefBase& o);
IBinder* const mRemote;
RefBase::weakref_type* mRefs;
std::atomic<int32_t> mState;
};
//構造實現
BpRefBase::BpRefBase(const sp<IBinder>& o)
//mRemote來自子類的傳遞
: 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.
}
}
2. 服務端規範
服務端要繼承BnInterface ,這個是個模板類,作用其實是使服務端物件繼承自模板物件,如下:
//frameworks/native/include/binder/IInterface.h
template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
virtual sp<IInterface> queryLocalInterface(const String16& _descriptor);
virtual const String16& getInterfaceDescriptor() const;
protected:
virtual IBinder* onAsBinder();
};
3. 兩個重要的巨集
Android提供的這兩個巨集是方便Binder介面的統一實現
需要以‘I’開頭加上傳入的介面變數來做宣告/實現
DECLARE_META_INTERFACE
: 宣告介面構造
#define DECLARE_META_INTERFACE(INTERFACE) \
static const android::String16 descriptor; \
static android::sp<I##INTERFACE> asInterface( \
const android::sp<android::IBinder>& obj); \
virtual const android::String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE(); \
IMPLEMENT_META_INTERFACE
:
實現介面構造(和DECLARE_META_INTERFACE宣告對應,實現其宣告的介面構造和變數)
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
//descriptor是客戶端和服務端的對接識別符號,以傳入的NAME作為初始化內容
const android::String16 I##INTERFACE::descriptor(NAME); \
const android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
//服務端的Binder物件是通過介面的asInterface傳入的,所以在找服務端介面的時候,可以使用
//I##INTERFACE::asInterface來查詢
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) { \
//建立客戶端物件,傳入服務端Binder物件
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { } \
---------------------------------------------------------------------------------------
//一個方便的函式,將Binder物件轉換為對應的客戶端介面
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);//也是呼叫對應模板的asInterface方法的
}
2. 以AudioFlinger為例
1. 客戶端 IAudioFlinger
//frameworks/av/include/media/IAudioFlinger.h
class IAudioFlinger : public IInterface
{
public:
DECLARE_META_INTERFACE(AudioFlinger);//宣告巨集
}
//服務端實現介面的規範
class BnAudioFlinger : public BnInterface<IAudioFlinger>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
//frameworks/av/media/libmedia/IAudioFlinger.cpp
class BpAudioFlinger : public BpInterface<IAudioFlinger>
{
public:
BpAudioFlinger(const sp<IBinder>& impl)
: BpInterface<IAudioFlinger>(impl)//這裡的構造中的Binder物件是在上面的
//IMPLEMENT_META_INTERFACE巨集中傳入的
{
}
IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
}
獲取IAudioFlinger服務端的例子:
//frameworks/av/media/libmedia/AudioSystem.cpp
const sp<IAudioFlinger> AudioSystem::get_audio_flinger()
{
sp<IAudioFlinger> af;
sp<AudioFlingerClient> afc;
{
Mutex::Autolock _l(gLock);
if (gAudioFlinger == 0) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
//獲取AudioFlinger Binder物件
binder = sm->getService(String16("media.audio_flinger"));
if (binder != 0)
break;
...
} while (true);
...
//轉化為IAudioFlinger 介面,作為服務端代理
gAudioFlinger = interface_cast<IAudioFlinger>(binder);
...
}
af = gAudioFlinger;
}
...
return af;
}
客戶端資訊總結:
- 客戶端介面:
IAudioFlinger
- 客戶端d代理物件:
BpAudioFlinger
- descriptor:
android.media.IAudioFlinger
- 服務端:
AudioFlinger
- remote() : 即服務端
AudioFlinger
2. 服務端 AudioFlinger
//frameworks/av/services/audioflinger/AudioFlinger.h
class AudioFlinger :
public BinderService<AudioFlinger>, //這個介面會將AudioFlinger 註冊到ServiceManager中
public BnAudioFlinger //繼承自BnInterface
{
friend class BinderService<AudioFlinger>; // for AudioFlinger()
public:
//服務端在ServiceManager註冊的時候的服務賬號,客戶端用這個賬號從ServiceManager中獲取服務端Binder物件。
static const char* getServiceName() ANDROID_API { return "media.audio_flinger"; }
}
服務端資訊總結
- 服務端介面:
IAudioFlinger
(和客戶端對應,這樣才轉換為客戶端介面IAudioFlinger) - 服務端物件:
AudioFlinger
- 服務註冊賬號:
media.audio_flinger
3. 總結
- 客戶端檔案需要Include IInterface.h 檔案, 客戶端需要繼承自IInterface介面,這個介面主要規定了一些對Binder的轉換操作;
- 客戶端中的remote()函式指的是服務端在客戶端的介面代理(I##INTERFACE),呼叫直接到服務端的onTransact()函式中;
- 客戶端繼承規則: public Bp##INTERFACE : public I##INTERFACE : public IInterface
- 服務端繼承規則: (INTERFACE : ) public Bn##INTERFACE: public I##INTERFACE : public IInterface
- 服務端需要繼承自Bn##INTERFACE介面,在獲取服務端之後使用
inerface_cast
介面或者I##INTERFACE::asInterface
轉換為客戶端介面I##INTERFACE,在客戶端直接使用的體現是remote()函式;
相關文章
- Android Binder實現示例(C/C++層)AndroidC++
- 理解 Android Binder 機制(二):C++層AndroidC++
- Android 系統原始碼-2:Binder 通訊機制Android原始碼
- Binder通訊機制
- Android多程式之Binder的使用Android
- Binder通訊機制與IPC通訊.md
- Android高階進階之路【五】深入剖析Android系統Binder通訊機制Android
- c++ binderC++
- Android native程式間通訊例項-binder結合共享記憶體Android記憶體
- Binder Java層分析Java
- C++程式間通訊的十一種方法C++
- 使用者層與驅動層通訊
- Android Binder之旅Android
- Android IPC機制(三):淺談Binder的使用Android
- 【 karle 專欄 】Android 初探底層知識系列——Binder原理。Android
- Android系統服務編寫例項-Binder(Java層AIDL)AndroidJavaAI
- Android-Binder(一)Android
- Binder Java層的實現原理分析Java
- 【React】元件通訊 - 跨層通訊React元件
- C++使用libcurl進行http通訊C++HTTP
- Android Socket連線,使用Socket進行通訊(Android)Android
- 圖解Android中的binder機制圖解Android
- Binder驅動的使用
- Android與物聯網裝置通訊-網路模型分層Android模型
- 藉助 AIDL 理解 Android Binder 機制——AIDL 的使用和原理分析AIAndroid
- Binder總結篇2-Binder使用
- Android Socket 通訊Android
- Android入門教程 | Fragment (載入方法與通訊)AndroidFragment
- HTTPS通訊的C++實現HTTPC++
- 藉助 AIDL 理解 Android Binder 機制——Binder 來龍去脈AIAndroid
- Android Binder機制文章轉載Android
- Android進階(六)Binder機制Android
- Android跨程式通訊Android
- Android 串列埠通訊Android串列埠
- Android 多程式通訊Android
- Android中的執行緒通訊Android執行緒
- Flutter與android之間的通訊FlutterAndroid
- 使用 Frida 逆向分析 Android 應用與 BLE 裝置的通訊Android