一、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;
};