AIDL & Binder机制和原理

新的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.cppNative层BP客户端源码
Binder.cpp
android_os_Parcel.cppParcel对javal层提供的接口注册,Binder数据传输被包在Parcel中


 

 【参考转载】

C++层Binder——Bn、Bp_bn bp_真的不懂呀的博客-CSDN博客

深入理解Binder机制4-bindService过程分析_bindserviceasuser_skytoby的博客-CSDN博客

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值