C++层Binder——Bn、Bp
C++層Binder——Bn、Bp
??我們知道,Binder之間通信,需要一個服務端和一個客戶端,而C++層的Binder,Bn端為服務端,Bp端為客戶端。所謂Bn、Bp端,實際就是以Bn、Bp為前綴的C++類。
??以cameraservice為例,cameraservice作為服務端,其繼承于BnCameraService。
一、AIDL
??而BnCameraService的相關代碼在源碼中是找不到的,因為它是通過C++層的AIDL自動生成的(想到不到吧,C++層也有AIDL)。
// av/camera/aidl/android/hardware/ICameraService.aidl interface ICameraService {const int ERROR_PERMISSION_DENIED = 1;const int ERROR_ALREADY_EXISTS = 2;const int ERROR_ILLEGAL_ARGUMENT = 3;const int ERROR_DISCONNECTED = 4;const int ERROR_TIMED_OUT = 5;const int ERROR_DISABLED = 6;const int ERROR_CAMERA_IN_USE = 7;const int ERROR_MAX_CAMERAS_IN_USE = 8;const int ERROR_DEPRECATED_HAL = 9;const int ERROR_INVALID_OPERATION = 10;const int CAMERA_TYPE_BACKWARD_COMPATIBLE = 0;const int CAMERA_TYPE_ALL = 1;int getNumberOfCameras(int type);CameraInfo getCameraInfo(int cameraId);const int USE_CALLING_UID = -1;const int USE_CALLING_PID = -1;ICamera connect(ICameraClient client,int cameraId,String opPackageName,int clientUid, int clientPid);ICameraDeviceUser connectDevice(ICameraDeviceCallbacks callbacks,String cameraId,String opPackageName,@nullable String featureId,int clientUid);const int CAMERA_HAL_API_VERSION_UNSPECIFIED = -1;ICamera connectLegacy(ICameraClient client,int cameraId,int halVersion,String opPackageName,int clientUid);CameraStatus[] addListener(ICameraServiceListener listener);ConcurrentCameraIdCombination[] getConcurrentCameraIds();boolean isConcurrentSessionConfigurationSupported(in CameraIdAndSessionConfiguration[] sessions);void removeListener(ICameraServiceListener listener);CameraMetadataNative getCameraCharacteristics(String cameraId);VendorTagDescriptor getCameraVendorTagDescriptor();VendorTagDescriptorCache getCameraVendorTagCache();String getLegacyParameters(int cameraId);const int API_VERSION_1 = 1;const int API_VERSION_2 = 2;boolean supportsCameraApi(String cameraId, int apiVersion);boolean isHiddenPhysicalCamera(String cameraId);void setTorchMode(String cameraId, boolean enabled, IBinder clientBinder);const int EVENT_NONE = 0;const int EVENT_USER_SWITCHED = 1; oneway void notifySystemEvent(int eventId, in int[] args);oneway void notifyDeviceStateChange(long newState);const int DEVICE_STATE_NORMAL = 0;const int DEVICE_STATE_BACK_COVERED = 1;const int DEVICE_STATE_FRONT_COVERED = 2;const int DEVICE_STATE_FOLDED = 4;const int DEVICE_STATE_LAST_FRAMEWORK_BIT = 0x80000000; // 1 << 31;}??查找BnCameraService代碼需要在產物中去找。ICameraService.aidl會生成三個.h文件,分別是ICameraService.h、BnCameraService.h、BpCameraService.h。
二、接口類
??ICameraService.h有一個ICameraService類,該類是一個接口類,其中所有定義的接口、枚舉等都是aidl中所定義的內容,顯然它用于定義是Binder機制中的業務接口的,它屬于的Binder機制中的接口屬性。
// out/soong/.intermediates/frameworks/av/camera/libcamera_client/android_x86_64_shared/gen/aidl/android/hardware/ICameraService.h class ICameraService : public ::android::IInterface { public:DECLARE_META_INTERFACE(CameraService) //這是一個宏,里面定義了實例化Bp客戶端的方法asInterfaceenum : int32_t {ERROR_PERMISSION_DENIED = 1,ERROR_ALREADY_EXISTS = 2,ERROR_ILLEGAL_ARGUMENT = 3,ERROR_DISCONNECTED = 4,ERROR_TIMED_OUT = 5,ERROR_DISABLED = 6,……virtual ::android::binder::Status getNumberOfCameras(int32_t type, int32_t* _aidl_return) = 0;virtual ::android::binder::Status getCameraInfo(int32_t cameraId, ::android::hardware::CameraInfo* _aidl_return) = 0;virtual ::android::binder::Status connect(const ::android::sp<::android::hardware::ICameraClient>& client, int32_t cameraId, const ::android::String16& opPackageName, int32_t clientUid, int32_t clientPid, ::android::sp<::android::hardware::ICamera>* _aidl_return) = 0;……virtual ::android::binder::Status setTorchMode(const ::android::String16& cameraId, bool enabled, const ::android::sp<::android::IBinder>& clientBinder) = 0;virtual ::android::binder::Status notifySystemEvent(int32_t eventId, const ::std::vector<int32_t>& args) = 0;virtual ::android::binder::Status notifyDeviceStateChange(int64_t newState) = 0; }; // class ICameraService??ICameraService接口類繼承于IInterface類,而IInterface又繼承于RefBase,是的,每個C++層Binder必須繼承于RefBase,以保證智能指針的使用。
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; };sp<IBinder> IInterface::asBinder(const IInterface* iface) {if (iface == nullptr) return nullptr;return const_cast<IInterface*>(iface)->onAsBinder(); }// static sp<IBinder> IInterface::asBinder(const sp<IInterface>& iface) {if (iface == nullptr) return nullptr;return iface->onAsBinder(); }??可以看到,IInterface主要提供兩個靜態接口asBinder。在java層的Binder中,也有asBinder接口,這里也體現了Binder的設計思想,一個Binder客戶端/服務端,必須帶有接口屬性與Binder通信屬性,且這兩者的類型可以互相轉換。asbinder顯然是接口屬性向Binder通信屬性的轉換,這也是可以理解的,畢竟看類名就知道,IInterface顯然是Binder機制中的帶有接口屬性的類。
??
三、Bn端
??在C++層面的Binder相關類中,所謂的Bn端就是Binder的服務端,在此例中,Cameraservice的Bn端,顯然就是之前AIDL自動生成的BnCameraService。
// out/soong/.intermediates/frameworks/av/camera/libcamera_client/android_x86_64_shared/gen/aidl/android/hardware/BnCameraService.h class BnCameraService : public ::android::BnInterface<ICameraService> { public:explicit BnCameraService();::android::status_t onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) override; }; // class BnCameraService??BnCameraService繼承于BnInterface,這是一個模板類,它的模板參數是Binder中的接口類,此例中當然就是ICameraService了。不過從功能上來看,BnInterface顯然是作為Bn端的統一父類而存在的。
template<typename INTERFACE> class BnInterface : public INTERFACE, public BBinder { public:virtual sp<IInterface> queryLocalInterface(const String16& _descriptor);virtual const String16& getInterfaceDescriptor() const;protected:typedef INTERFACE BaseInterface;virtual IBinder* onAsBinder(); };// Bn端的具體實現則在out/soong/.intermediates/frameworks/av/camera/libcamera_client/android_x86_64_shared/gen/aidl/frameworks/av/camera/aidl/android/hardware/ICameraService.cppz中可以看到??可以看到,BnInterface繼承了連個類,一個是它的模板(即Binder機制中的接口類),另外一個是BBinder,它是為Binder通信而存在的。從這里就可以找到Bn端作為Binder服務端所需要的兩個屬性了——接口屬性和Binder通信屬性。
??但是單看代碼,顯然這個BnCameraService作為一個服務端是殘缺的,因為它自身所需的接口屬性中,其業務接口都沒有實現,這是因為CameraService類繼承自BnCameraService,Bn端的所有接口業務全部在CameraService這個子類中實現了。
四、Bp端
??Bp端是C++層Binder機制中的客戶端,如果明白了Bn端的大致結構,那么Bp端的也很理解了,它們大同小異。
??在此例中,BpCameraService顯然就是CameraService服務的客戶端了。
??BpCameraService繼承自BpInterface,而BpInterface又繼承自它的模板類(接口類)和BpRefBase。
template<typename INTERFACE> class BpInterface : public INTERFACE, public BpRefBase { public:explicit BpInterface(const sp<IBinder>& remote);protected:typedef INTERFACE BaseInterface;virtual IBinder* onAsBinder(); };??從類結構上來看,到現在為止Bn端和Bp都高度對稱,除了一點,Bn端Binder通信的類是BBinder,而Bp端關于Binder通信的類則是BpRefBase。這樣好理解,畢竟一個是客戶端,一個是服務端,在Binder的通信機制上一個是發送端另外一個是接收端,這兩個端負責Binder通信的類在功能上理所當然會有出入。
??再看Bp端的Binder通信屬性相關的父類BpRefBase。
??可以看到,BpRefBase有一個IBinder類型的成員變量mRemote,有趣的是,在java層的Binder客戶端Proxy,也有一個用于Binder通信的成員變量remote。所以無論是java層還是c++層,在對Binder客戶端和服務端的設計手法上都有著驚人的相似,服務端都會選擇繼承兩個類(接口類和Binder通信類),而客戶端卻都會采用代理的形式去實現Binder通信。
??話說回來,這個BpRefBase的成員函數mRemote,其所指向的究竟是個什么對象呢?這要從Bp端的獲取說起。我們知道,在Binder客戶端的獲取,本質上是從驅動層獲取所需Binder的cookie值,然后在應用層會對將該cookie值封裝成一個Bp端,而獲取cookie值的地方正是在Parcel類中。通過調用Parcel類中的readStrongBinder方法來獲取到cookie值,同時也會在該方法中將cookie值封裝成Bp端。
??當switch進入BINDER_TYPE_BINDER時,表示要獲取本地已經存在的一個IBinder類,這個IBinder一般是Bn服務端。而當進入BINDER_TYPE_HANDLE時,則意味著要通過句柄來創建一個新的IBinder,而這個新的IBinder就是Bp客戶端了。Bp客戶端是在getStrongProxyForHandle方法中創建的。
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) {sp<IBinder> result;AutoMutex _l(mLock);handle_entry* e = lookupHandleLocked(handle);if (e != nullptr) {// We need to create a new BpBinder if there isn't currently one, OR we// are unable to acquire a weak reference on this current one. The// attemptIncWeak() is safe because we know the BpBinder destructor will always// call expungeHandle(), which acquires the same lock we are holding now.// We need to do this because there is a race condition between someone// releasing a reference on this BpBinder, and a new reference on its handle// arriving from the driver.IBinder* b = e->binder;if (b == nullptr || !e->refs->attemptIncWeak(this)) {if (handle == 0) {// Special case for context manager...// The context manager is the only object for which we create// a BpBinder proxy without already holding a reference.// Perform a dummy transaction to ensure the context manager// is registered before we create the first local reference// to it (which will occur when creating the BpBinder).// If a local reference is created for the BpBinder when the// context manager is not present, the driver will fail to// provide a reference to the context manager, but the// driver API does not return status.//// Note that this is not race-free if the context manager// dies while this code runs.//// TODO: add a driver API to wait for context manager, or// stop special casing handle 0 for context manager and add// a driver API to get a handle to the context manager with// proper reference counting.Parcel data;status_t status = IPCThreadState::self()->transact(0, IBinder::PING_TRANSACTION, data, nullptr, 0);if (status == DEAD_OBJECT)return nullptr;}b = BpBinder::create(handle); //該方法會實例化一個BpBindere->binder = b;if (b) e->refs = b->getWeakRefs();result = b;} else {// This little bit of nastyness is to allow us to add a primary// reference to the remote proxy when this team doesn't have one// but another team is sending the handle to us.result.force_set(b);e->refs->decWeak(this);}}return result; }BpBinder* BpBinder::create(int32_t handle) {int32_t trackedUid = -1;if (sCountByUidEnabled) {trackedUid = IPCThreadState::self()->getCallingUid();AutoMutex _l(sTrackingLock);uint32_t trackedValue = sTrackingMap[trackedUid];if (CC_UNLIKELY(trackedValue & LIMIT_REACHED_MASK)) {if (sBinderProxyThrottleCreate) {return nullptr;}} else {if ((trackedValue & COUNTING_VALUE_MASK) >= sBinderProxyCountHighWatermark) {ALOGE("Too many binder proxy objects sent to uid %d from uid %d (%d proxies held)",getuid(), trackedUid, trackedValue);sTrackingMap[trackedUid] |= LIMIT_REACHED_MASK;if (sLimitCallback) sLimitCallback(trackedUid);if (sBinderProxyThrottleCreate) {ALOGI("Throttling binder proxy creates from uid %d in uid %d until binder proxy"" count drops below %d",trackedUid, getuid(), sBinderProxyCountLowWatermark);return nullptr;}}}sTrackingMap[trackedUid]++;}return new BpBinder(handle, trackedUid); }??總結起來,當本地服務端接受到客戶端傳過來的一個Binder請求時,會在本地創建一個對應的Bp客戶端(此時針對這個傳遞的Binder而言,客戶端會保留它的Bn服務端,而服務端則會創建一個Bp客戶端,有點繞),而該Bp客戶端的實例化流程,首先會先通過Parcel的readStrongBinder實例化一個BpBinder,然后一般會通過調用對應接口類中的asInterface方法將BpBinder轉化為一個真正的Bp客戶端,其實這個轉化就是實例化一個Bp客戶端,實例化時,會將BpBinder作為構造傳參傳入Bp客戶端中。
??目前還有一個盲點,就是將BpBinder轉化為Bp客戶端的方法在哪里還沒有講過。之前說該方法是asInterface是被定義在接口類中,但單純的看代碼,是找不到asInterface方法的,這是因為這個方法被統一封裝到了一個宏中DECLARE_META_INTERFACE,在ICameraService中則是:
??而仔細看DECLARE_META_INTERFACE宏的內容如下:
#define DECLARE_META_INTERFACE(INTERFACE) \ public: \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(); \static bool setDefaultImpl(std::unique_ptr<I##INTERFACE> impl); \static const std::unique_ptr<I##INTERFACE>& getDefaultImpl(); \ private: \static std::unique_ptr<I##INTERFACE> default_impl; \ public: ::android::sp<I##INTERFACE> I##INTERFACE::asInterface( \const ::android::sp<::android::IBinder>& obj) \{ \::android::sp<I##INTERFACE> intr; \if (obj != nullptr) { \intr = static_cast<I##INTERFACE*>( \obj->queryLocalInterface( \I##INTERFACE::descriptor).get()); \if (intr == nullptr) { \intr = new Bp##INTERFACE(obj); \} \} \return intr; \} \??以上就可以看出Bp客戶端是如何通過asInterface實例化的了。
總結
以上是生活随笔為你收集整理的C++层Binder——Bn、Bp的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 国货新品牌的量产之路!徒有产能的工厂老板
- 下一篇: iview使用方法