新的Android 通信规范中,C++层使用AIDL替代HIDL实现Framework和Vendor层之间调用解耦。
我们知道,Binder之间通信,需要一个服务端和一个客户端.
【Binder】
Binder架构分成四层,应用层,Framework层,Native层和内核层
应用层:Java应用层通过调用IActivityManager.bindService,经过层层调用到AMS.bindService;
Framework层:Jave IPC Binder通信采用C/S架构,在Framework层实现BinderProxy和Binder;
Native层:Native IPC,在Native层的C/S架构,实现了BpBinder和BBinder(JavaBBinder);
Kernel层:Binder驱动,运行在内核空间,可共享。其它三层是在用户空间,不可共享。
Binder IPC原理:
Binder Service流程:
创建Proxy:
private static class Proxy implements android.app.IActivityManager {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
...
@Override
public int bindService(android.app.IApplicationThread caller, android.os.IBinder token, android.content.Intent service, String resolvedType, android.app.IServiceConnection connection, int flags, String callingPackage, int userId) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain(); //创建数据Parcel实例
android.os.Parcel _reply = android.os.Parcel.obtain();//创建返回Parcel实例
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
//将ApplicationThread对象传递给systemserver,caller在binder前初始化创建?
_data.writeStrongBinder((((caller != null)) ? (caller.asBinder()) : (null)));
_data.writeStrongBinder(token);
if ((service != null)) {
_data.writeInt(1);
service.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
_data.writeString(resolvedType);
//将InnerConnection对象传递给systemserver
_data.writeStrongBinder((((connection != null)) ? (connection.asBinder()) : (null)));
_data.writeInt(flags);
_data.writeString(callingPackage);
_data.writeInt(userId);
//通过bind调用,进入到systemserver
mRemote.transact(Stub.TRANSACTION_bindService, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
...
}
【AIDL】
是一个基于Binder通信的接口封装工具(直通式例外,另说),通过定义AIDL接口文件确定Binder客户端和服务通信接口。在软件编译时,AIDL工具根据AIDL接口文件自动生成Interface,客户端Proxy和服务端Stub代码, 模块间调用关系如图:
Interface: 服务端接口 + binder功能接口(asBinder)
Proxy: 服务端对应用端提供的客户端代理类(= Binder 客户端 + Inteface transact实现)。服务对外提供接口不直接提供创建的服务实例本身,而是会通过底层Binder服务创建的一个代理服务(伪服务)实例返回给应用端调用。因此伪服务除了继承Interface外,还实现了如何远程调用真服务的接口(基于binder的transact)
private static class Proxy implements com.test.IAIService
{
@Override public java.lang.String getServerState() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_getServerState, _data, _reply, 0);
if (!_status) {
if (getDefaultImpl() != null) {
return getDefaultImpl().getServerState();
}
}
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
Stub:服务端真正继承实现接口的类 + Binder服务端。(onTransact统一接受来自Proxy端的数据,并读取数据调度到真正的服务实现接口)。
而C++层的Binder,Bn端为服务端,Bp端为客户端。所谓Bn、Bp端,实际就是以Bn、Bp为前缀的C++类, 在aidl自动生成工具的接口产物中可以看到(补充产物截图)。以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
{
……
【接口类】
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端的统一父类而存在的。类似于AIDL java生成的Stub.
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中可以看到
【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();
};
// 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对应于AIDL Java端生成的Proxy。这个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客户端进程保留服务端缓存,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; \
} \
参考阅读 | |
BpBinder.cpp | Native层BP客户端源码 |
Binder.cpp | |
android_os_Parcel.cpp | Parcel对javal层提供的接口注册,Binder数据传输被包在Parcel中 |
【参考转载】
C++层Binder——Bn、Bp_bn bp_真的不懂呀的博客-CSDN博客
深入理解Binder机制4-bindService过程分析_bindserviceasuser_skytoby的博客-CSDN博客