android aidl 安卓接口定义语言 介绍

xiaoxiao2021-02-28  69

AIDL:Android InterfaceDefinition Language,即Android接口定义语言。其实就是用来生成java层对应的binder 接口,还是以之前的ItestService为例,在android studio中我们创建如下一个aidl文件。

ITestService.aidl

// ITestService.aidl package com.hxiong; // Declare any non-default types here with import statements interface ITestService { // int test(int api); }

点击构建构成后,会在app\build\generated\source\aidl\debug\com\hxiong 目录下生成一个ITestService.java的文件

文件里面的内容如下

package com.hxiong; // Declare any non-default types here with import statements public interface ITestService extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.hxiong.ITestService { private static final java.lang.String DESCRIPTOR = "com.hxiong.ITestService"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.hxiong.ITestService interface, * generating a proxy if needed. */ public static com.hxiong.ITestService asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof com.hxiong.ITestService))) { return ((com.hxiong.ITestService)iin); } return new com.hxiong.ITestService.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 { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_test: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); int _result = this.test(_arg0); reply.writeNoException(); reply.writeInt(_result); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.hxiong.ITestService { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } @Override public int test(int api) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); int _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(api); mRemote.transact(Stub.TRANSACTION_test, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_test = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); } public int test(int api) throws android.os.RemoteException; } 当我们要使用到它时,一般会继承ITestService.Stub

TestService.java

package com.hxiong; import android.os.RemoteException; public class TestService extends ITestService.Stub{ @Override public int test(int api) throws RemoteException { TODO return 0; } } 根据上面的关系,我们画出java层binder 的继承关系

红色框框的部分就是aidl帮我们生成的,对比前面C++层的binder 继承关系,可以看出它们十分相似(可以认为是一样的),java 层的Binder 对象C++层的BBinder,java层BinderProxy对应C++层的BpBinder,通过分析代码,看一下它们是怎么关联到一起的。

1、首先还是从获取binder proxy入手,Parcel的readStrongBinder()会得到IBinder

Parcel.java

public final IBinder readStrongBinder() { return nativeReadStrongBinder(mNativePtr); }

android_os_parcel.cpp

static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr) { Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); if (parcel != NULL) { return javaObjectForIBinder(env, parcel->readStrongBinder()); } return NULL; }

android_util_binder.cpp

jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) { //同一个进程中 if (val->checkSubclass(&gBinderOffsets)) { // One of our own! jobject object = static_cast<JavaBBinder*>(val.get())->object(); LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object); return object; } // For the rest of the function we will hold this lock, to serialize // looking/creation/destruction of Java proxies for native Binder proxies. AutoMutex _l(mProxyLock); // Someone else's... do we know about it? jobject object = (jobject)val->findObject(&gBinderProxyOffsets); if (object != NULL) { jobject res = jniGetReferent(env, object); if (res != NULL) { ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res); return res; } LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get()); android_atomic_dec(&gNumProxyRefs); val->detachObject(&gBinderProxyOffsets); env->DeleteGlobalRef(object); } //这里创建了BinderProxy对象 object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor); if (object != NULL) { LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object); // The proxy holds a reference to the native object. env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get()); //val 是C++层的BpBinder实例 val->incStrong((void*)javaObjectForIBinder); // The native object needs to hold a weak reference back to the // proxy, so we can retrieve the same proxy if it is still active. jobject refObject = env->NewGlobalRef( env->GetObjectField(object, gBinderProxyOffsets.mSelf)); val->attachObject(&gBinderProxyOffsets, refObject, jnienv_to_javavm(env), proxy_cleanup); // Also remember the death recipients registered on this proxy sp<DeathRecipientList> drl = new DeathRecipientList; drl->incStrong((void*)javaObjectForIBinder); env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get())); // Note that a new object reference has been created. android_atomic_inc(&gNumProxyRefs); incRefsCreated(env); } return object; }

担心有些同学还看不明白,我简单描述一下,java层的BinderProxy对象是在jni中创建的,所以最终返回的是BinderProxy对象,C++层得到的BpBinder实例会保存在BinderProxy的mObject,可以简单的把mObject理解成指向C++层BpBinder实例的指针。

env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());   //val 是C++层的BpBinder实例

const char* const kBinderProxyPathName = "android/os/BinderProxy"; clazz = FindClassOrDie(env, kBinderProxyPathName); gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz); gBinderProxyOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>", "()V"); gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice", "(Landroid/os/IBinder$DeathRecipient;)V"); gBinderProxyOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J"); gBinderProxyOffsets.mSelf = GetFieldIDOrDie(env, clazz, "mSelf","Ljava/lang/ref/WeakReference;");

通过上面的介绍,我们知道传到Proxy里面的IBinder是BinderProxy对象,那么ava层调用aidl中定义的接口,会走那些流程

Binder.java

public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { Binder.checkParcel(this, code, data, "Unreasonably large binder buffer"); if (Binder.isTracingEnabled()) { Binder.getTransactionTracker().addTrace(); } return transactNative(code, data, reply, flags); } android_util_binder.cpp

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException { ... IBinder* target = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject); if (target == NULL) { jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!"); return JNI_FALSE; } ... //printf("Transact from Java code to %p sending: ", target); data->print(); status_t err = target->transact(code, *data, reply, flags); //if (reply) printf("Transact from Java code to %p received: ", target); reply->print(); ... return JNI_FALSE; } 看吧,不就是把C++层的BpBinder实例取出来,调用它 transact() 接口,之后的流程前面有讲过。

2、另外一边,作为binder的server端,我们看ITestService.Stub是怎么和BBinder关联起来的

binder.java

public Binder(){

        init();

       …

    }

private nativefinal void init();

android_util_binder.cpp

static void android_os_Binder_init(JNIEnv* env, jobject obj) { JavaBBinderHolder* jbh = new JavaBBinderHolder(); if (jbh == NULL) { jniThrowException(env, "java/lang/OutOfMemoryError", NULL); return; } ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh); jbh->incStrong((void*)android_os_Binder_init); env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh); }

class JavaBBinderHolder : public RefBase { public: sp<JavaBBinder> get(JNIEnv* env, jobject obj) { AutoMutex _l(mLock); sp<JavaBBinder> b = mBinder.promote(); if (b == NULL) { b = new JavaBBinder(env, obj); mBinder = b; ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n", b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount()); } return b; } sp<JavaBBinder> getExisting() { AutoMutex _l(mLock); return mBinder.promote(); } private: Mutex mLock; wp<JavaBBinder> mBinder; };

虽然new的是一个JavaBBinderHolder,但是在调用get()函数的时候会创建一个JavaBBinder实例, JavaBBinder继承BBinder。

class JavaBBinder : public BBinder{

virtual status_t onTransact(

       uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags =0)

    {

       JNIEnv* env = javavm_to_jnienv(mVM);

       ALOGV("onTransact() on %p calling object %p in env %p vm%p\n", this, mObject, env, mVM);

       IPCThreadState* thread_state = IPCThreadState::self();

       const int32_t strict_policy_before =thread_state->getStrictModePolicy();

       //printf("Transact from %p to Java code sending: ", this);

       //data.print();

       //printf("\n");

       jbooleanres = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,

            code,reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply),flags);

       …

       // Need to always call through the native implementation of

       // SYSPROPS_TRANSACTION.

       if (code == SYSPROPS_TRANSACTION) {

           BBinder::onTransact(code, data, reply, flags);

       }

       //aout << "onTransact to Java code; result=" <<res << endl

       //    << "Transact from" << this << " to Java code returning "

       //    << reply <<": " << *reply << endl;

       return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;

    }

}; 前面的博客有讲到过,server端从binder driver读到数据后,会回调到BBinder::onTransact(),因为子类 JavaBBinder重写了onTransact(),所有会调用JavaBBinder 的onTransact(),红色标注的代码,就是jni call到java层的实现。

 jboolean res =env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,

            code,reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply),flags);

最后,我们把上面的流程和相关联的模块绘制成结构图,前面写了那么多的文字,贴了那么多的代码,就是描述了下图。

转载请注明原文地址: https://www.6miu.com/read-43913.html

最新回复(0)