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客户端的方法asInterface
enum : 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); //该方法会实例化一个BpBinder
e->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实例化的了。