C++层Binder——Bn、Bp

  我们知道,Binder之间通信,需要一个服务端和一个客户端,而C++层的Binder,Bn端为服务端,Bp端为客户端。所谓Bn、Bp端,实际就是以Bn、Bp为前缀的C++类。

  以cameraservice为例,cameraservice作为服务端,其继承于BnCameraService。

// av/services/camera/libcameraservice/CameraService.h
class CameraService :public BinderService<CameraService>,public virtual ::android::hardware::BnCameraService,public virtual IBinder::DeathRecipient,public virtual CameraProviderManager::StatusListener
{……

一、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服务的客户端了。

 // /home/zfm/work/aosp/out/soong/.intermediates/frameworks/av/camera/libcamera_client/android_x86_64_shared/gen/aidl/android/hardware/BpCameraService.h
class BpCameraService : public ::android::BpInterface<ICameraService> {public:explicit BpCameraService(const ::android::sp<::android::IBinder>& _aidl_impl);virtual ~BpCameraService() = default;::android::binder::Status getNumberOfCameras(int32_t type, int32_t* _aidl_return) override;::android::binder::Status getCameraInfo(int32_t cameraId, ::android::hardware::CameraInfo* _aidl_return) override;……::android::binder::Status supportsCameraApi(const ::android::String16& cameraId, int32_t apiVersion, bool* _aidl_return) override;::android::binder::Status isHiddenPhysicalCamera(const ::android::String16& cameraId, bool* _aidl_return) override;::android::binder::Status setTorchMode(const ::android::String16& cameraId, bool enabled, const ::android::sp<::android::IBinder>& clientBinder) override;::android::binder::Status notifySystemEvent(int32_t eventId, const ::std::vector<int32_t>& args) override;::android::binder::Status notifyDeviceStateChange(int64_t newState) override;
};  // class BpCameraService// Bp端的具体实现则在out/soong/.intermediates/frameworks/av/camera/libcamera_client/android_x86_64_shared/gen/aidl/frameworks/av/camera/aidl/android/hardware/ICameraService.cppz中可以看到

  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。

// frameworks/native/libs/binder/include/binder/Binder.h
class BpRefBase : public virtual RefBase
{protected:explicit                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);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有一个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端。

status_t Parcel::readStrongBinder(sp<IBinder>* val) const
{status_t status = readNullableStrongBinder(val);if (status == OK && !val->get()) {status = UNEXPECTED_NULL;}return status;
}status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const
{return unflatten_binder(ProcessState::self(), *this, val);
}status_t unflatten_binder(const sp<ProcessState>& proc,const Parcel& in, sp<IBinder>* out)
{const flat_binder_object* flat = in.readObject<flat_binder_object>(); //从Parcel包中读取出Binder的flat_binder_object结构体,该结构体中会包含Binder对应的Binder索引值。if (flat) {switch (flat->hdr.type) {case BINDER_TYPE_BINDER:*out = reinterpret_cast<IBinder*>(flat->cookie); //将cookie值封装成Bp端return finish_unflatten_binder(nullptr, *flat, in);case BINDER_TYPE_HANDLE:*out = proc->getStrongProxyForHandle(flat->handle);return finish_unflatten_binder(static_cast<BpHwBinder*>(out->get()), *flat, in);}}return BAD_TYPE;
}

  当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中则是:

class ICameraService : public ::android::IInterface {public:DECLARE_META_INTERFACE(CameraService)

  而仔细看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相关推荐

  1. android transact,Android Native层Binder.transact()函数调用 Binder.onTransact() 函数失败分析...

    Q:Android Native层Binder.transact()函数调用 Binder.onTransact() 函数失败? 在Android Native层调用Camera.h中的api实现一个 ...

  2. 安卓高手之路之java层Binder

    很多人一提到Binder就说代理模式,人云亦云的多,能理解精髓的少. 本篇文章就从设计角度分析一下java层BInder的设计目标,以及设计思路,设计缺陷,从而驾驭它. 对于[邦德儿]的理解, 从通信 ...

  3. 【Binder 机制】Native 层 Binder 机制分析 ( binder_loop | svcmgr_handler | binder.c | binder_parse )

    文章目录 前言 一.binder_loop 方法调用 二.binder_loop 方法参数 svcmgr_handler 三.binder_loop 方法 四.binder_parse 方法 前言 在 ...

  4. 【PyTorch】eval() ==>主要是针对某些在train和predict两个阶段会有不同参数的层,比如Dropout层和BN层

    model的eval方法主要是针对某些在train和predict两个阶段会有不同参数的层.比如Dropout层和BN层 torch为了方便大家,设计这个eval方法就是让我们可以不用手动去针对这些层 ...

  5. Java层Binder使用(ServiceManager)

    转自:http://blog.csdn.net/jacklam200/article/details/37567409 跟上篇Binder使用一样,先通过例子来跟踪Java层Binder机制.本文参考 ...

  6. 目标检测 YOLOv5 - 卷积层和BN层的融合

    目标检测 YOLOv5 - 卷积层和BN层的融合 即Conv2d和 BatchNorm2d融合 flyfish 为了减少模型推理时间,YOLOv5源码中attempt_load已经包括两层的合并,主要 ...

  7. 卷积层与BN层的融合方式

    BN(批归一化)层常用于在卷积层之后,对feature maps进行归一化,从而加速网络学习,也具有一定的正则化效果.训练时,BN需要学习一个minibatch数据的均值.方差,然后利用这些信息进行归 ...

  8. pytorch实现卷积层和BN层融合

    批归一化 数据的规范化也即(x−mean(x)/var(x))(x-mean(x)/var(x))(x−mean(x)/var(x)) 可以将数据的不同特征规范到均值为0,方差相同的标准正态分布,这就 ...

  9. PyTorch之—卷积层、激活层、BN

    文章目录 一.卷积层 二.池化层 三.归一化(BN) 一.卷积层 class torch.nn.Conv2d(in_channels, out_channels, kernel_size, strid ...

最新文章

  1. 宅家学习,如何进行Kubernetes Ingress控制器的技术选型?
  2. STL中基本容器有: string、vector、list、deque、set、map
  3. 学习笔记Flink(一)—— Flink简介(介绍、基本概念、应用场景)
  4. SQL语句求解同一人物不同日期,某一属性的差值
  5. 10 windows 启动虚拟机报错_Windows 系统如何安装 Docker
  6. C语言试题九十一之写一个程序,用公式π/4=1-1/3+1/5-1/7+...,求π的近似值,直到最后一项的绝对值小于10^-8为止。
  7. bzoj5090[lydsy11月赛]组题
  8. 计算机维修案例分析题,14-15年春季高考信息技术题(组装维修部分)
  9. 系统架构设计师 - 系统可靠性设计
  10. 使用Google App Engine开始新的网站开发学习
  11. json字符串-单、双引号
  12. heroku_如何通过5个步骤在Heroku上部署机器学习UI
  13. IDEA中部署Tomcat及原理
  14. Kylin启动报错 ERROR: Check hive‘s usability failed, please check the status of your cluster
  15. 神威太湖之光——世界超算冠军
  16. 识别图片上的文字,如何在线识别?
  17. 西安工大计算机学院李颖,李颖 -西安交通大学人文社会科学学院
  18. 编程趣味知识:固执的“and”和变通的“or”
  19. java response 输出word_如何使用java代码导出word
  20. 注册公司经营范围还不知道怎么写?看这一篇就够了!

热门文章

  1. 邮箱地址注册,163邮箱登陆登录入口在哪里?
  2. 工欲善其事,必先利其器(Eclipse篇)
  3. NOI / 2.5基本算法之搜索-6044:鸣人和佐助详解
  4. 按键弹起、按下的事件
  5. H5 (React) 移动端监听软键盘弹起、收起
  6. php添加本地搜索,十分钟,在本地搭建一个搜索引擎
  7. unity2d游戏开发系列教程:一、环境安装
  8. 记FTP链接:Server Reply: SSH-2.0-OpenSSH_8.0
  9. 360视频加速器官方版
  10. Linux管理日记(一)