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

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的文件

android aidl 安卓接口定义语言 介绍_第1张图片

文件里面的内容如下

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 的继承关系

android aidl 安卓接口定义语言 介绍_第2张图片

红色框框的部分就是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(nativePtr);
    if (parcel != NULL) {
        return javaObjectForIBinder(env, parcel->readStrongBinder());
    }
    return NULL;
}

android_util_binder.cpp

jobject javaObjectForIBinder(JNIEnv* env, const sp& val)
{
    //同一个进程中
    if (val->checkSubclass(&gBinderOffsets)) {
        // One of our own!
        jobject object = static_cast(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 drl = new DeathRecipientList;
        drl->incStrong((void*)javaObjectForIBinder);
        env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast(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, "", "()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 get(JNIEnv* env, jobject obj)
    {
        AutoMutex _l(mLock);
        sp 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 getExisting()
    {
        AutoMutex _l(mLock);
        return mBinder.promote();
    }

private:
    Mutex           mLock;
    wp 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(&data), reinterpret_cast(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=" <

       //    << "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(&data), reinterpret_cast(reply),flags);


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

android aidl 安卓接口定义语言 介绍_第3张图片












你可能感兴趣的:(binder)