Android aidl流程

一、JAVA aidl流程

1.aidl源码

创建 IIpcService.aidl和IIpcServiceListener.aidl,具体源码和aidl工具生成的IIpcService.java和IIpcServiceListener.java
见:https://blog.csdn.net/kk3087961/article/details/136051743

1 aidl生成的IIpcService.java源码文件如下,其中核心内部类 Stub 继承了Binder类同时实现了IIpcService接口。
Service的onBind方法返需要回IIpcService.Stub的实现类。

2 客户端

2.1bindService时ServiceConnection.onServiceConnected(ComponentName name, IBinder service)回调
需要将 服务端返回的IBinder,通过 mIpcService = IIpcService.Stub.asInterface(service)转换成IIpcService对象。
com.android.demo.aidl.IIpcService asInterface 方法 返回new com.android.demo.aidl.IIpcService.Stub.Proxy(obj),即返回IIpcService.Stub.Proxy实例。
Proxy 构造方法将服务端返回的IBinder 赋值给变量mRemote。
2.1 客户端请求
例如:mIpcService.processClientRequest(mPackageName, clientRequest,pfd);即调用IIpcService.Stub.Proxy.processClientRequest 方法。
IpcService.Stub.Proxy.processClientRequest 方法调用 mRemote.transact(Stub.TRANSACTION_processClientRequest, _data, _reply, 0);
这个mRemote 就是1.2描述的 服务端返回的IBinder,这里是aidl跨进程通信最核心内容。
服务端Binder对象被创建,同时会在Binder驱动中创建一个 mRemote对象,该对象的类型也是一个Binder类;客户端就是通过mRemote 来访问远程服务。
所以这里的mRemote对象实际上是服务端 在 Binder驱动中创建的 mRemote对象,调用mRemote.transact 即调用Binder驱动transact方法,然后调用了服务端的transact方法
IIpcService.Stub.onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) 方法,
这里的code参数对应 客户端传递的Stub.TRANSACTION_processClientRequest,即使调用 this.processClientRequest(_arg0, _arg1, _arg2);
因为Service端 实现了IIpcService.Stub接口,即最终调用了服务端IIpcService.Stub的实现类方法。

至此客户端通过mIpcService完成和服务端binder通信了。

简单总结
1.服务端 实现接口内部抽象类IIpcService.Stub,并在服务 onBind 返回,
2.客户端 通过包名、类名bindService获取服务端IBinder,然后通过IIpcService.Stub.asInterface获取com.android.demo.aidl.IIpcService.Stub.Proxy(IBinder)对象,Proxy内部将 IBinder 赋值给mRemote
3.客户端调用IIpcService.Stub.Proxy.processClientRequest 最终调用IBinder.transact(Stub.TRANSACTION_processClientRequest, _data, _reply, 0);
通过biner驱动调用IIpcService.Stub.onTransact,最终调用1中服务端 实现接口。
IIpcService.java

public interface IIpcService extends android.os.IInterface
{
    ...
    //内部类Stub定义了binder 服务端 接口,服务端需要实现该接口
    public static abstract class Stub extends android.os.Binder implements com.android.demo.aidl.IIpcService
    {    
    ...
        public static com.android.demo.aidl.IIpcService asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.android.demo.aidl.IIpcService))) {
                return ((com.android.demo.aidl.IIpcService) iin);
            }
            return new com.android.demo.aidl.IIpcService.Stub.Proxy(obj);
        }
    
        @Override
        public android.os.IBinder asBinder() {
            return this;
        }
        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            java.lang.String descriptor = DESCRIPTOR;
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(descriptor);
                    return true;
                }
                ...
                case TRANSACTION_processClientRequest: {
                    data.enforceInterface(descriptor);
                    java.lang.String _arg0;
                    _arg0 = data.readString();
                    java.lang.String _arg1;
                    _arg1 = data.readString();
                    android.os.ParcelFileDescriptor _arg2;
                    if ((0 != data.readInt())) {
                        _arg2 = android.os.ParcelFileDescriptor.CREATOR.createFromParcel(data);
                    } else {
                        _arg2 = null;
                    }
                    java.lang.String _result = this.processClientRequest(_arg0, _arg1, _arg2);
                    reply.writeNoException();
                    reply.writeString(_result);
                    if ((_arg2 != null)) {
                        reply.writeInt(1);
                        _arg2.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                    } else {
                        reply.writeInt(0);
                    }
                    return true;
                }
                ...
            }
        }
        private static class Proxy implements com.android.demo.aidl.IIpcService {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }
            
            @Override
            public android.os.IBinder asBinder() {
                return mRemote;
            }
             ...
            @Override
            public java.lang.String processClientRequest(java.lang.String packageName, java.lang.String clientRequest, android.os.ParcelFileDescriptor pfd) 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);
                    _data.writeString(packageName);
                    _data.writeString(clientRequest);
                    if ((pfd != null)) {
                        _data.writeInt(1);
                        pfd.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    boolean _status = mRemote.transact(Stub.TRANSACTION_processClientRequest, _data, _reply, 0);
                    if (!_status && getDefaultImpl() != null) {
                        return getDefaultImpl().processClientRequest(packageName, clientRequest, pfd);
                    }
                    _reply.readException();
                    _result = _reply.readString();
                    if ((0 != _reply.readInt())) {
                        pfd = android.os.ParcelFileDescriptor.CREATOR.createFromParcel(_reply);
                    }
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
             ...
         }    
   }
}

3.service端实现

创建服务 继承Service类,在onBind方法返回IIpcService.Stub的实现类,服务端在IpcService.Stub的实现类 方法中处理客户端的请求。

 public class IpcService extends Service {
    ...
   @Override
    public IBinder onBind(Intent intent) {
        return mIpcService;
    }
    
    private IIpcService.Stub mIpcService = new IIpcService.Stub() {
        ...
        @Override
        public String processClientRequest(String packageName, String clientRequest, ParcelFileDescriptor pfd) throws RemoteException {
            Log.d(TAG,  "processClientRequest");
            return LocalIpcRepositoryImpl.getInstance().processClientRequest(packageName, clientRequest,pfd);
        }
        ...
    };
}   

 
绑定服务端流程
客户端先调用startService启动服务,然后调用bindService绑定服务,在服务连接回调中调用mIpcService = IIpcService.Stub.asInterface(service);
获取服务端接口对象,即可通过mIpcService aidl请求服务端方法,例如:  mIpcService.processClientRequest(mPackageName, clientRequest,pfd);

Intent intent = new Intent();
intent.setComponent(new ComponentName(IpcServiceConstant.SERVICE_PKG_NAME,
IpcServiceConstant.SERVICE_DATA_COLLECTION_NAME));
mContext.startService(intent);
mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mIpcService = IIpcService.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    };

二、c++ aidl流程    

1.    aidl源码

创建 IIpcService.aidl和IIpcServiceListener.aidl,具体源码和aidl工具生成的BnIpcService.h、BpIpcService.h、IIpcService.h、IIpcService.cpp 等
见:https://blog.csdn.net/kk3087961/article/details/136051743

2.c++ 服务端实现

需要继承BinderService和aidl 文件生成的BnIpcService,然后调用 TestIpcService::instantiate() 将名称为test.ipcservice的TestIpcService 实例注册到Android系统的servicemanager。
instantiate 是在BinderService中定义,不再赘述,流程可参考https://blog.csdn.net/kk3087961/article/details/135992303
例如 

class TestIpcService :
    public BinderService<TestIpcService>,
    public BnIpcService
{
    ...
    static char const* getServiceName() { return "test.ipcservice"; }
    
}

3.c++ 客户端

3.1 IIpcService.h 调用 DECLARE_META_INTERFACE(IpcService)
以及IIpcService.cpp 调用 
DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(IpcService, "com.android.demo.aidl.IIpcService")
以及 IInterface.h 中的宏定义展开可知 ::android::sp<ITYPE> ITYPE::asInterface(const ::android::sp<::android::IBinder>& obj)
中 ITYPE对应I##INTERFACE即IIpcService ,BPTYPE 对应Bp##INTERFACE即:BpIpcService 。

3.2 客户端调用defaultServiceManager 获取Android IServiceManager对象,
然后调用getService方法,根据服务名称字符串,获取对应的binder对象。
这里interface_cast<::com::android::demo::aidl::IIpcService>(binder)调用根据binder获取 IIpcService 接口对象,
IInterface.h 中 interface_cast 方法调用了INTERFACE::asInterface(obj),即调用 IIpcService.::asInterface(binder),
ITYPE::asInterface方法 调用 ::android::sp<BPTYPE>::make(obj), 即调 IIpcService.::asInterface(binder) ,  
对应的::android::sp<ITYPE> ITYPE::asInterface方法中先调用obj->queryLocalInterface(ITYPE::descriptor)获取本地对象,
如果为空则调用:android::sp<BPTYPE>::make(obj) ,这里的BPTYPE 对应Bp##INTERFACE
即返回 BpIpcService 对象实例。

3.3 gTestIpcService  ->processClientRequest(...)调用BpIpcService::processClientRequest 方法,该方法
调用 remote()->transact(BnIpcService::TRANSACTION_processClientRequest, _aidl_data, &_aidl_reply, 0),
由BpInterface构造函数及BpRefBase 类定义可知,remote()为从ServiceManager获取的binder对象,即通过biner驱动调用2中服务端接口。

简单总结
1.服务端 继承BnIpcService和BinderService<TestIpcService>,需要参考CameraService 调用TestIpcService::instantiate(), 将IpcService开机注册到系统IServiceManager。
2.客户端 通过服务字符串 获取服务端binder对象,然后通过interface_cast获取:android::sp<BpIpcService>::make(binder)对象,BpInterface内部将 binder 赋值BpRefBase中的mRemote
3. gTestIpcService  ->processClientRequest(...)    最终调用binder->transact(BnIpcService::TRANSACTION_processClientRequest, _aidl_data, &_aidl_reply, 0)
通过biner驱动调用IIpcService.cpp 中的BnIpcService::onTransact,最终调用2中服务端 TestIpcService实现接口。

客户端调用示例代码:

const char*               kTestIpcServiceName      = "test.ipcservice";
sp<::com::android::demo::aidl::IIpcService> gTestIpcService;
sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder;
        do {
            binder = sm->getService(String16(kTestIpcServiceName));//根据服务名称字符串,获取对应的binder对象
            if (binder != 0) {
                break;
            }
        } while(true);
        if (gDeathNotifier == NULL) {
            gDeathNotifier = new DeathNotifier();
        }
        binder->linkToDeath(gDeathNotifier);
        gTestIpcService = interface_cast<::com::android::demo::aidl::IIpcService>(binder);  //根据binder获取 IIpcService 对象()

         gTestIpcService  ->processClientRequest(...);  

BnIpcService.h

class BnIpcService : public ::android::BnInterface<IIpcService> {
public:
  static constexpr uint32_t TRANSACTION_register2Server = ::android::IBinder::FIRST_CALL_TRANSACTION + 0;
  static constexpr uint32_t TRANSACTION_unregister2Server = ::android::IBinder::FIRST_CALL_TRANSACTION + 1;
  static constexpr uint32_t TRANSACTION_processClientRequest = ::android::IBinder::FIRST_CALL_TRANSACTION + 2;
  static constexpr uint32_t TRANSACTION_processClientRequestOneway = ::android::IBinder::FIRST_CALL_TRANSACTION + 3;
  explicit BnIpcService();
  ::android::status_t onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) override;
};  // class BnIpcService

class IIpcServiceDelegator : public BnIpcService {
public:
  explicit IIpcServiceDelegator(::android::sp<IIpcService> &impl) : _aidl_delegate(impl) {}
  ...
  ::android::binder::Status processClientRequest(const ::android::String16& packageName, const ::android::String16& clientRequest, ::android::os::ParcelFileDescriptor* pfd, ::android::String16* _aidl_return) override {
    return _aidl_delegate->processClientRequest(packageName, clientRequest, pfd, _aidl_return);
  }

private:
  ::android::sp<IIpcService> _aidl_delegate;
};  // class IIpcServiceDelegator

BpIpcService.h

class BpIpcService : public ::android::BpInterface<IIpcService> {
public:
  explicit BpIpcService(const ::android::sp<::android::IBinder>& _aidl_impl);
  virtual ~BpIpcService() = default;
  ...
  ::android::binder::Status processClientRequest(const ::android::String16& packageName, const ::android::String16& clientRequest, ::android::os::ParcelFileDescriptor* pfd, ::android::String16* _aidl_return) override;

};  // class BpIpcService


IIpcService.h
class IIpcService : public ::android::IInterface {
public:
  DECLARE_META_INTERFACE(IpcService)
  ...
  virtual ::android::binder::Status processClientRequest(const ::android::String16& packageName, const ::android::String16& clientRequest, ::android::os::ParcelFileDescriptor* pfd, ::android::String16* _aidl_return) = 0;

};  // class IIpcService

class IIpcServiceDefault : public IIpcService {
public:
  ::android::IBinder* onAsBinder() override {
    return nullptr;
  }
  ...
  ::android::binder::Status processClientRequest(const ::android::String16& /*packageName*/, const ::android::String16& /*clientRequest*/, ::android::os::ParcelFileDescriptor* /*pfd*/, ::android::String16* /*_aidl_return*/) override {
    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
  }

  }
};  // class IIpcServiceDefault

IIpcService.cpp

DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(IpcService, "com.android.demo.aidl.IIpcService")
BpIpcService::BpIpcService(const ::android::sp<::android::IBinder>& _aidl_impl)
    : BpInterface<IIpcService>(_aidl_impl){
}

::android::binder::Status BpIpcService::processClientRequest(const ::android::String16& packageName, const ::android::String16& clientRequest, ::android::os::ParcelFileDescriptor* pfd, ::android::String16* _aidl_return) {
    ...
      ::android::binder::Status _aidl_status;
  _aidl_ret_status = remote()->transact(BnIpcService::TRANSACTION_processClientRequest, _aidl_data, &_aidl_reply, 0);
  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IIpcService::getDefaultImpl())) {
     return IIpcService::getDefaultImpl()->processClientRequest(packageName, clientRequest, pfd, _aidl_return);
  }
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
   ...
  return _aidl_status;
}

BnIpcService::BnIpcService()
{
  ::android::internal::Stability::markCompilationUnit(this);
}

::android::status_t BnIpcService::onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) {
  ::android::status_t _aidl_ret_status = ::android::OK;
  switch (_aidl_code) {
   ...
  case BnIpcService::TRANSACTION_processClientRequest:
  {
    ::android::String16 in_packageName;
    ::android::String16 in_clientRequest;
    ::android::os::ParcelFileDescriptor in_pfd;
    ::android::String16 _aidl_return;
    ...
    ::android::binder::Status _aidl_status(processClientRequest(in_packageName, in_clientRequest, &in_pfd, &_aidl_return));
    _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
    if (((_aidl_ret_status) != (::android::OK))) {
      break;
    }
    ...
  }
  break;

  }
  if (_aidl_ret_status == ::android::UNEXPECTED_NULL) {
    _aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeOverParcel(_aidl_reply);
  }
  return _aidl_ret_status;
}

/frameworks/native/include/binder/IInterface.h

template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

#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(::android::sp<I##INTERFACE> impl);                                 \
    static const ::android::sp<I##INTERFACE>& getDefaultImpl();                                   \
                                                                                                  \
private:                                                                                          \
    static ::android::sp<I##INTERFACE> default_impl;   

// Macro to be used by both IMPLEMENT_META_INTERFACE and IMPLEMENT_META_NESTED_INTERFACE
#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0(ITYPE, INAME, BPTYPE)                     \
    const ::android::String16& ITYPE::getInterfaceDescriptor() const { return ITYPE::descriptor; } \
    ::android::sp<ITYPE> ITYPE::asInterface(const ::android::sp<::android::IBinder>& obj) {        \
        ::android::sp<ITYPE> intr;                                                                 \
        if (obj != nullptr) {                                                                      \
            intr = ::android::sp<ITYPE>::cast(obj->queryLocalInterface(ITYPE::descriptor));        \
            if (intr == nullptr) {                                                                 \
               // 创建一个Bp对象       
                intr = ::android::sp<BPTYPE>::make(obj);                                           \
            }                                                                                      \
        }                                                                                          \
        return intr;                                                                               \
    }                                                                                              \
    ::android::sp<ITYPE> ITYPE::default_impl;                                                      \
    bool ITYPE::setDefaultImpl(::android::sp<ITYPE> impl) {                                        \
        /* Only one user of this interface can use this function     */                            \
        /* at a time. This is a heuristic to detect if two different */                            \
        /* users in the same process use this function.              */                            \
        assert(!ITYPE::default_impl);                                                              \
        if (impl) {                                                                                \
            ITYPE::default_impl = std::move(impl);                                                 \
            return true;                                                                           \
        }                                                                                          \
        return false;                                                                              \
    }                                                                                              \
    const ::android::sp<ITYPE>& ITYPE::getDefaultImpl() { return ITYPE::default_impl; }            \
    ITYPE::INAME() {}                                                                              \
    ITYPE::~INAME() {}

// Macro for an interface type.
#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                        \
    const ::android::StaticString16 I##INTERFACE##_descriptor_static_str16(                     \
            __IINTF_CONCAT(u, NAME));                                                           \
    const ::android::String16 I##INTERFACE::descriptor(I##INTERFACE##_descriptor_static_str16); \
    DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0(I##INTERFACE, I##INTERFACE, Bp##INTERFACE)    

template<typename INTERFACE>
inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(
        const String16& _descriptor)
{
    if (_descriptor == INTERFACE::descriptor) return sp<IInterface>::fromExisting(this);
    return nullptr;
}
...    
template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
    : BpRefBase(remote)
{
}

/system/core/libutils/include/utils/StrongPointer.h

template <typename T>
template <typename... Args>
sp<T> sp<T>::make(Args&&... args) {
    T* t = new T(std::forward<Args>(args)...);
    sp<T> result;
    result.m_ptr = t;
    t->incStrong(t);  // bypass check_not_on_stack for heap allocation
    return result;
}

template <typename T>
sp<T> sp<T>::fromExisting(T* other) {
    if (other) {
        check_not_on_stack(other);
        other->incStrongRequireStrong(other);
        sp<T> result;
        result.m_ptr = other;
        return result;
    }
    return nullptr;
}


/frameworks/native/libs/binder/Binder.cpp

BpRefBase::BpRefBase(const sp<IBinder>& o)
    : mRemote(o.get()), mRefs(nullptr), mState(0)
{
    extendObjectLifetime(OBJECT_LIFETIME_WEAK);

    if (mRemote) {
        mRemote->incStrong(this);           // Removed on first IncStrong().
        mRefs = mRemote->createWeak(this);  // Held for our entire lifetime.
    }
}

/frameworks/native/libs/binder/include/binder/Binder.h

class BpRefBase : public virtual RefBase
{
protected:
    ...
    inline IBinder* remote() const { return mRemote; }
   

private:
    IBinder* const          mRemote;
     ...
};

三、java客户端 调用 c++的服务端

c++ 编译aidl生成接口文件的方法和java  编译aidl生成接口文件的方法 稍微有些差异。
从如下示例 文件可知:
生成的 java接口方法 processClientRequest结构 和aidl 完全一致,
生成的c++  接口方法 processClientRequest结构 和aidl 不完全一致,返回值变成了 ::android::binder::Status类型,同时将方法返回值放到了方法中 参数::android::String16* _aidl_return。

如果是java客户端 调用 c++的服务端,
java 客户端 调用String result = mIpcService.processClientRequest(mPackageName, clientRequest,pfd); 即调用
c++ 服务端的 virtual ::android::binder::Status processClientRequest(const ::android::String16& packageName, const ::android::String16& clientRequest, ::android::os::ParcelFileDescriptor* pfd, ::android::String16* _aidl_return) 方法

例如:IIpcService.aidl

interface IIpcService {
    ...
    String processClientRequest(String packageName,String clientRequest,inout ParcelFileDescriptor pfd);
}

生成的java接口文件 IIpcService.java

public interface IIpcService extends android.os.IInterface
{
    ...
    public java.lang.String processClientRequest(java.lang.String packageName, java.lang.String clientRequest, android.os.ParcelFileDescriptor pfd) throws android.os.RemoteException;
}


生成的c++接口文件 IIpcService.h

class IIpcService : public ::android::IInterface {
public:
    ...
  virtual ::android::binder::Status processClientRequest(const ::android::String16& packageName, const ::android::String16& clientRequest, ::android::os::ParcelFileDescriptor* pfd, ::android::String16* _aidl_return) = 0;
};  


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值