AIDL底层原理需要搞明白的三个点

前言

binder通信在Android中一直属于核心机制,前面分析了binder的c层和C++层的通信机制,但是没有分析binder的java层通信机制,但是作为一个资深Android开发人员,这个怎么能不搞懂,这补充一下;

首先要声明一下,Android7.00和8.0的源码其实差别还有点的,binder通信上主要表现在7.0的AMS是继承ActivityManagerNative的,而8.0的AMS是直接实现了IActivityManager.stub接口,也就是直接通过AIDL接口实现的,其实原来的ActivityManagerNative的实现就是一个stub的功能。

三个“搞明白”

想要知道AIDL的底层原理,首先要来三个"搞明白":
(1)搞明白AIDL编译时期生成的文件其中的类和方法的作用
(2)搞明白Java层binder、JavaBBinder、JavaBBinderHolder之间的关系,以及他们的分工和作用
(3)搞明白Parcel在binder机制中的作用

搞明白AIDL编译时期生成的文件其中的类和方法的作用

AIDL是Android interface definition language,因此使用的时候是面向接口的,需要自定义一个接口,例如:

interface IStoreAidl {
    int sell(String pencil);
}
public interface IStoreAidl extends android.os.IInterface{1public static abstract class Stub extends android.os.Binder implements com.xx.leo_service.ILeoAidl{2private static final java.lang.String DESCRIPTOR = "com.android.test.IStoreAidl";2-1public android.os.IBinder asBinder(){......}2-2public static com.xx.leo_service.ILeoAidl asInterface(android.os.IBinder obj)
			{...... return new com.xx.leo_service.ILeoAidl.Stub.Proxy(obj);}2-3public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)){
            switch (code)
            {
                case INTERFACE_TRANSACTION:
                {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_sayhello_to:
                {
                    data.enforceInterface(DESCRIPTOR);
                    java.lang.String _arg0;
                    _arg0 = data.readString();
                    int _result = this.sell(_arg0);
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
		}2-4private static class Proxy implements com.xx.leo_service.ILeoAidl{}2-5}
}

在编译的时候,自动生成AIDL文件,文件中包含三个部分:
(1)自定义接口IStoreAidl自动继承IInterface接口
(2)自动创建抽象类Stub继承Binder并实现IStoreAidl接口,对于客户端来说,stub代表了服务端,服务端继承了stub并实现接口中的方法,客户端通过暴露出的接口调用服务端的方法,Android7.0中的AcrivityManagerNative就扮演了这个角色。
(3)stub中有五个重要的部分:

  • DESCRIPTOR(2-1):定义一个常量描述符,一般用来作为token通过parcel写给binder,binder为啥安全,就因为他们有校验机制
  • asBinder()(2-2):通过parcel实现asBinder()方法,服务端通过该方法来获取Ibinder;
  • asInterface(IBinder iBinder)(2-3):客户端通过该方法得到服务端的代理,proxy就相当于stub在客户端的一个代理,客户端通过这个代理,并其中的方法,将数据封装成功parcel然后写入到binder底层驱动中,然后发送到服务端;
  • onTransact()(2-4):重写onTransact()方法,该方法是binder的方法,用来分发onTransact的,在这里调用服务端实现的方法,并将结果写入parcel的reply中去通过该方法层层传递,返回给客户端;
  • Proxy(2-5):stub的静态内部类,实现了IStoreAidl接口,是服务端stub在客户端的一个代理类,主要用来将客户端的消息封装成parcel数据,然后通过remote.transact()与binder驱动进行交互

搞明白Java层binder、JavaBBinder、JavaBBinderHolder之间的关系,以及他们的分工和作用

首先通过一幅图总结一下:
在这里插入图片描述

public class StoreService extends IStoreAidl.Stub {......}1ServiceManager.addService("hello", new HelloService())2

(1)服务端是继承的IStoreAidl.Stub 其实也就是继承的Binder,因此服务端就是个Binder
(2)从关系图中可以看出,new HelloService()的时候,在Binder的构造中调用init(),调用native层的方法创建JavaBBinderHolder()并将它赋值给Binder的mObject;
(3)JavaBBinderHolder的构造中又创建了JavaBBinder extends BBinder,并赋值给了mBinder
(4)最后又把Binder赋值给了JavaBBinder的mObject
(5)将服务注册到ServiceManager中去,因此这个注册到SM中的Binder,就是JavaBBinder它属于BBinder
因此binder、JavaBBinder、JavaBBinderHolder他们是相互持有,JavaBBinder属于BBinder,IPCThreadState从binder驱动中读取到数据后,调用了注册到SM中的服务端,也就是BBinder

status_t BBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
.....
//实际上就是通过onTransact分发,调用了JavaBBinder中的onTransact方法
//JavaBBinder通过ExecTransact方法分发到了java层binder的onTransact()方法,也就是IHelloService.Stub重写的onTransact()方法,将文章开始部分
err = onTransact(code, data, reply, flags); 
....
   return err;
}

JavaBBinder中重写了onTransact,其实就是通过ExecTransact方法,继续向java层的binder中的onTransact分发,其实就是调用了IHelloService.Stub中的onTransact()方法,然后再那里调用服务端的接口实现代码:

import android.util.Slog;
public class HelloService extends IHelloService.Stub {
    private static final String TAG = "HelloService";
    public int sell(java.lang.String shoe) throws android.os.RemoteException {
        Slog.i(TAG, "sell "+shoe);
        return 100;
    }
}

搞明白Parcel在binder机制中的作用

java层的parcel其实就是对C层Parcel的一个封装,Parcel在binder机制中的作用除了能够封装数据之外,主要是因为他有传递binder对象的功能:
parcel.writeStrongBinder():flatten_binder
ReadStringBinder():unFlatten_binder

这两个方法对binder对象进行序列化和反序列化;

parcel.writeStrongBinder(service)

我们在之前讲到,这个service是我们自己的服务,也就是BinderrProxy——>JavaBBinder::BBinder
java层的writeStrongBinder其实就是调用native的android_os_Parcel_writeStrongBinder

static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if (parcel != NULL) {
        const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
        if (err != NO_ERROR) {
            signalExceptionForError(env, clazz, err);
        }
    }
}

sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{   //gBinderOffsets.mClass指向BinderProxy——>JavaBBinder::BBinder
    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
        JavaBBinderHolder* jbh = (JavaBBinderHolder*)
            env->GetLongField(obj, gBinderOffsets.mObject);
        return jbh != NULL ? jbh->get(env, obj) : NULL;
    }
    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
        return (IBinder*)
            env->GetLongField(obj, gBinderProxyOffsets.mObject);
    }
    return NULL;
}

所以这个parcel->writeStrongBinder(ibinderForJavaObject(env, object));其实就是parcel->writeStrongBinder(new JavaBBinder(env, obj));

status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
    return flatten_binder(ProcessState::self(), val, this);
}
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
    const sp<IBinder>& binder, Parcel* out)
{
    flat_binder_object obj;
    if (IPCThreadState::self()->backgroundSchedulingDisabled()) {
        obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
    } else {
        obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    }
    if (binder != NULL) {
        IBinder *local = binder->localBinder(); //binder是BBinder,所以得到的时this,所以走的else
        if (!local) {
            BpBinder *proxy = binder->remoteBinder();
            if (proxy == NULL) {
                ALOGE("null proxy");
            }
            const int32_t handle = proxy ? proxy->handle() : 0;
            obj.type = BINDER_TYPE_HANDLE;
            obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
            obj.handle = handle;
            obj.cookie = 0;
        } else {
            obj.type = BINDER_TYPE_BINDER;
            obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
            obj.cookie = reinterpret_cast<uintptr_t>(local);
        }
    } else {
        obj.type = BINDER_TYPE_BINDER;
        obj.binder = 0;
        obj.cookie = 0;
    }
    return finish_flatten_binder(binder, obj, out);
}

所以服务端的BinderProxy——>JavaBBinder()::BBinder也就被拆分成了type、binder和cookie存到了parcel中

parcel.ReadStringBinder(service)

read其实就是write的逆向走势;
readStrongBinder其实就是调用native层的nativeReadStrongBinder方法,调用C++层的readNullableStrongBinder——>unflatten_binder方法;

static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if (parcel != NULL) {
    //readStrongBinder调用了Parcel中的unflatten_binder方法
        return javaObjectForIBinder(env, parcel->readStrongBinder());
    }
    return NULL;
}
status_t unflatten_binder(const sp<ProcessState>& proc,
    const Parcel& in, sp<IBinder>* out)
{
    const flat_binder_object* flat = in.readObject(false);
    if (flat) {
        switch (flat->type) {
            case BINDER_TYPE_BINDER:
                *out = reinterpret_cast<IBinder*>(flat->cookie);
                return finish_unflatten_binder(NULL, *flat, in);
            case BINDER_TYPE_HANDLE: //这里是从服务端获取,因此走的这个分支
            //因为ServiceManager注册的时候,也调用了ProcessState.getStrongProxyHander()方法,返回new BpBinder(0)
            //但是new BpBinder(0)的0是SM专属的,因此这里返回的是new BpBinder(handler),handler肯定不为0
                *out = proc->getStrongProxyForHandle(flat->handle);
                return finish_unflatten_binder(
                    static_cast<BpBinder*>(out->get()), *flat, in);
        }
    }
    return BAD_TYPE;
}

因为ServiceManager注册的时候,也调用了ProcessState.getStrongProxyHander()方法,返回new BpBinder(0),0是SM专属的,因此这里返回的是new BpBinder(handler),handler肯定不为0;所以

sp<IBinder>* out = proc->getStrongProxyForHandle(flat->handle);
相当于
sp<IBinder>* out = new BpBinder(handler);
所以:
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if (parcel != NULL) {
        return javaObjectForIBinder(env, new BpBinder(handler));
    }
    return NULL;
}
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
//如果是服务端的binder也就是BBinder就返回JavaBBinder,这里显然不是了
    if (val->checkSubclass(&gBinderOffsets)) {
        jobject object = static_cast<JavaBBinder*>(val.get())->object();
        return object;
    }
    AutoMutex _l(mProxyLock);
    //如果之前已经获取过,就返回BinderProxy,第一次的话肯定是没有获取过的
    jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
    if (object != NULL) {
        jobject res = jniGetReferent(env, object);
        if (res != NULL) {
            return res;
        }
        android_atomic_dec(&gNumProxyRefs);
        val->detachObject(&gBinderProxyOffsets);
        env->DeleteGlobalRef(object);
    }
    //如果是第一次进入,就创建一个BinderProxy并将new BpBinder(handler)对象赋值给BinderProxy的object
    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
    if (object != NULL) {
        env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
        val->incStrong((void*)javaObjectForIBinder);
        jobject refObject = env->NewGlobalRef(
                env->GetObjectField(object, gBinderProxyOffsets.mSelf));
        val->attachObject(&gBinderProxyOffsets, refObject,
                jnienv_to_javavm(env), proxy_cleanup);
        sp<DeathRecipientList> drl = new DeathRecipientList;
        drl->incStrong((void*)javaObjectForIBinder);
        env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));
        android_atomic_inc(&gNumProxyRefs);
        incRefsCreated(env);
    }
    return object;
}

所以当通过Parcel的unflatten_binder方法拿到远程服务的binder对象(new BpBinder(handler)handler非0)后,然后封装成java层客户端的代理BinderProxy()对象返回给客户端
调用链太长用时序图总结一下:
在这里插入图片描述
最后通过之前讲的IstoreAidl.stub.asInterface(BinderProxy())方法得到IstoreAidl.stub.Proxy对象,且BinderProxy中的remote属性指向new BpBinder(handler)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值