Android Binder——通过AIDL探究Binder

之前写完了关于View的测量、布局和绘制以及事件的分发,思前想后还是决定要写下关于Binder的理解。提笔容易落笔难,写了几个字就不知道该如何写下去,干脆就这样结束吧(滑稽)。


1. 进程间通信(IPC)

我们都知道Android的Application运行在DVM上,当我们的APP启动时会由Zygote孵化一个新的进程作为APP的进程,所有的APP都独立运行在自己的进程中,他们之间的通信就成了问题。而Binder作为进程间通信的机制则解决了这个问题,Binder由Client、Server、Service Manager和Binder驱动程序组成,其中Client、Server和Service Manager运行在用户空间,Binder驱动程序运行内核空间。其中,核心组件便是Binder驱动程序了,Service Manager提供了辅助管理的功能,Client和Server正是在Binder驱动和Service Manager提供的基础设施上,进行Client-Server之间的通信。网传神图:

Binder

2. AIDL(Android Interface Definition Language)

AIDL全称Android接口定义语言,其设计的目的就是实现进程间的通信。上面我们说Android的IPC是通过Binder机制解决的,AIDL可以理解为Binder的具体实现。当然,AIDL应该算是谷歌爸爸提供给我们的一个简单实现进程间通信的语言,它会由IDE编译后生成代码,大大减少了我们开发所需要的时间。当然了,也可以通过手动编写代码去实现进程间通信,好像API 25和之前的AMS就是手动去实现的,现在API 26已经改为AIDL实现。

3. AIDL的使用

首先说明下,这篇文章并不是AIDL的教程,这里就挑侧重点来说下:

  1. 默认支持的数据类型:
    1.1 Java中的八种基本数据类型
    1.2 String 类型和CharSequence类型
    1.3 List类型:List中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是定义的parcelable
    1.4 Map类型:Map中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是定义的parcelable
  2. 导入其他数据类型:
    2.1 实现Parcelable接口
    2.2 相同包下创建相同名称的AIDL文件
    2.3 import相应的类型,并且作为参数时需要使用in、out、inout来修饰
  3. in、out、inout:
    3.1 参数前面加上in作为修饰的话,代表当前参数作为流入参数,在这里可以修改对象的属性但不会影响原对象的值
    3.2 参数前面加上out作为修饰的话,代表当前的参数作为流出参数,对象是一个属性值都是默认的对象,修改对象的属性会修改原对象属性的值
    3.3 inout是in和out的综合体

关于Map:自己尝试的时候发现使用Map<Xxx,Xxxx>形式时会编译失败,改成Map即可。

4. AIDL的跨进程

AIDL文件定义好,编译一下IDE会自动生成关于AIDL的代码。我们可以从源码来看下究竟是如何跨进程的:


使用

调用方法
public interface IUserManager extends android.os.IInterface {
    public static abstract class Stub extends android.os.Binder implements com.nick.remoteservice.IUserManager {
        private static final java.lang.String DESCRIPTOR = "com.nick.remoteservice.IUserManager";
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        public static com.nick.remoteservice.IUserManager asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            // 通过描述查找是否为binder,如果不为空则判断是否实现了IUserManager接口
            // 如果为空,则创建代理类
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.nick.remoteservice.IUserManager))) {
                // 传入的就是我们的Stub对象(在service中初始化),我们可以直接调用方法
                // 这时候没有涉及到进程间通信
                return ((com.nick.remoteservice.IUserManager) iin);
            }
            // 代理类
            return new com.nick.remoteservice.IUserManager.Stub.Proxy(obj);
        }

        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        // 代理类通过transact方法调用onTransact方法
        // 根据code来判断具体执行哪个操作
        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            switch (code) {
                ......
                case TRANSACTION_addIn: {
                    data.enforceInterface(DESCRIPTOR);
                    com.nick.remoteservice.model.UserModel _arg0;
                    // 根据Parcel来反序列化对象
                    if ((0 != data.readInt())) {
                        _arg0 = com.nick.remoteservice.model.UserModel.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    // 调用addIn方法,addIn方法的具体实现是在service中实现
                    com.nick.remoteservice.model.UserModel _result = this.addIn(_arg0);
                    reply.writeNoException();
                    // 写入结果
                    if ((_result != null)) {
                        reply.writeInt(1);
                        _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                    } else {
                        reply.writeInt(0);
                    }
                    return true;
                }
                ......
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.nick.remoteservice.IUserManager {
            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 com.nick.remoteservice.model.UserModel addIn(com.nick.remoteservice.model.UserModel userModel) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                com.nick.remoteservice.model.UserModel _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    if ((userModel != null)) {
                        _data.writeInt(1);
                        userModel.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    // native层调用transact方法,最终会调用Stub的onTransact方法,并将返回值写入_reply
                    mRemote.transact(Stub.TRANSACTION_addIn, _data, _reply, 0);
                    _reply.readException();
                    if ((0 != _reply.readInt())) {
                        // 序列化创建对象
                        _result = com.nick.remoteservice.model.UserModel.CREATOR.createFromParcel(_reply);
                    } else {
                        _result = null;
                    }
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            ......
        }

        static final int TRANSACTION_addIn = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
                ......
    }

    public com.nick.remoteservice.model.UserModel addIn(com.nick.remoteservice.model.UserModel userModel) throws android.os.RemoteException;
        ......
}

上面的代码是由IDE通过AIDL自动生成的代码,我们可以看到:

  • IDE生成了与我们定义的AIDL文件同名的java接口文件,并且该接口继承IInterface接口,同时该接口内部包括了抽象内部类Stub(实现了该接口),Proxy(代理类,同样实现了该接口并且方法全部实现)
  • 创建Stub类对象时需要实现我们在AIDL中定义的方法,需要在远端Service中的onBind方法中实现,通过bindService方法中的ServiceConnection来获得IBinder实现类的引用,最终通过静态方法IUserManager.Stub.asInterfaceIBinder实现类的引用生成Proxy(远端调用的情况)
  • asInterface通过查找我们在创建对象是传入的描述(DESCRIPTOR)是否存在来判断是否为当前的Stub对象,如果不是的话需要创建一个代理类Proxy
  • Proxy类中的构造方法需要传入一个IBinder的对象,当需要调用Server中的某个方法时会通过Proxy调用远端Binder对象的transact方法,通过native层最终调用Stub中的onTransact方法,StubonTransact方法会根据传入的code来判断需要调用哪个具体的方法,并且将结果写入Parcel对象中。

流程图:


流程图

5. Debug证明

每次写文章都想要把每个地方都弄清楚,起码说能够自己这关过得去。所以,有时候写一篇文章需要找好多资料,看很多源码。最简单的证明流程是正确的我觉得就是Debug大法,下面看下debug下asInterface的调用:

asInterface

从上图中可以看到我们传入的IBinder实例是BinderProxy,最终会创建一个Stub.Proxy对象。
这里说下Binder和BinderProxy:

public class Binder implements IBinder {}
final class BinderProxy implements IBinder {}

从名字上就可以知道:Binder是IBinder的具体实现,而BinderProxy作为Binder的代理类,可以通过BinderProxy调用Binder中的方法。
接着我们看下asInterface的调用方法:

image.png

我们看到我们调用的是LoadedApk$ServiceDispatcher$RunConnection对象的run方法:
RunConnection

run方法中调用了LoadedApk$ServiceDispatcherdoConnected方法:

public void doConnected(ComponentName name, IBinder service, boolean dead) {
    ......
    // If there is a new service, it is now connected.
    if (service != null) {
        mConnection.onServiceConnected(name, service);
    }
}

最终调用我们的onServiceConnected方法。这里面的方法调用是在bindService中调用的,其中创建IBinder对象是在ActivityThread中:

image.png

在这里也可以看到我们传入的IBinder对象是我们的RemoteService匿名内部类,而我们通过ServiceConnection获得的是BinderProxy对象,这里猜测:由于Service在一个新的进程中,所以由native层给我们返回了BinderProxy对象。native层的代码并不是很懂,但是我在查看ParcelwriteStrongBinderreadStrongBinder方法中看到了关于BinderProxy的创建,这里不多说。
接着我们调用下远端Service的方法:
addIn

addIn方法执行到mRemote.transact方法接着会执行:
onTransact

onTransact最终调用Service中的addIn方法完成操作:
Service中addIn方法

执行完成

6. native层分析(不是很了解,给自己写的)

关于Binder层的分析,有需要的还是去看老罗的讲解,非常详细。这里还是将自己探索的过程记录下(在线源码在线全局源码全局搜索)。
我们知道我们写的AIDL生成的代码会继承Binder,所以在创建对象的时候会调用Binder的初始化:

public Binder() {
    init();
    ......
}
private native final void init();

对应native层代码:

/frameworks/base/core/jni/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);
}
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);
    // gBinderOffsets是native层对java层Binder映射的结构体
    // gBinderProxyOffsets是native层对java层BinderProxy映射的结构体
    // 这里创建了JavaBBinderHolder对象,并将mObject对象设置成JavaBBinderHolder的地址
    env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
}
class JavaBBinderHolder : public RefBase
{
public:
    // 重写了get方法,返回JavaBBinder
    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;
};

可以看到,初始化的过程就是创建了一个JavaBBinderHolder对象,并将对象的指针赋值给gBinderOffsets.mObject
关于gBinderOffsets:

/frameworks/base/core/jni/android_util_Binder.cpp:
static struct bindernative_offsets_t
{
    // Class state.
    jclass mClass;
    jmethodID mExecTransact;

    // Object state.
    jfieldID mObject;

} gBinderOffsets;
// 各种方法
static const JNINativeMethod gBinderMethods[] = {
     /* name, signature, funcPtr */
    { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid },
    { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },
    { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
    { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity },
    { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },
    { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy },
    { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands },
    { "init", "()V", (void*)android_os_Binder_init },
    { "destroy", "()V", (void*)android_os_Binder_destroy },
    { "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable }
};
// 注册
static int int_register_android_os_Binder(JNIEnv* env)
{
    jclass clazz = FindClassOrDie(env, kBinderPathName);

    gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    // 将execTransact的methodId赋值,最后就是调用此方法来调用java层的Binder对象的execTransact方法
    gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");
    // 这个mObject就是Binder的mObject的fieldId
    gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");

    return RegisterMethodsOrDie(
        env, kBinderPathName,
        gBinderMethods, NELEM(gBinderMethods));
}

接着我们会调用BinderProxytransact方法:

/frameworks/base/core/jni/android_util_Binder.cpp:
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
    // code = 1(FIRST_CALL_TRANSACTION) flags = 0
    ......
    // 获得BinderProxy,在这里是BpBinder(p代表proxy的意思)
    IBinder* target = (IBinder*)
        env->GetLongField(obj, gBinderProxyOffsets.mObject);
    
    ......
    // 调用BpBinder的transact方法
    status_t err = target->transact(code, *data, reply, flags);
    //if (reply) printf("Transact from Java code to %p received: ", target); reply->print();

    if (kEnableBinderSample) {
        if (time_binder_calls) {
            conditionally_log_binder_call(start_millis, target, code);
        }
    }

    if (err == NO_ERROR) {
        return JNI_TRUE;
    } else if (err == UNKNOWN_TRANSACTION) {
        return JNI_FALSE;
    }

    signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/, data->dataSize());
    return JNI_FALSE;
}

我们看到这里获取了gBinderProxyOffsetsmObject对象的值,作为IBinder的指针(这里其实是BpBinder)。接着调用了BpBindertransact方法,下面看下gBinderProxyOffsetsBpBinder

/frameworks/base/core/jni/android_util_Binder.cpp:
static struct binderproxy_offsets_t
{
    // Class state.
    jclass mClass;
    // BinderProxy构造方法的方法Id
    jmethodID mConstructor;
    // BinderProxy的sendDeathNotice方法Id
    jmethodID mSendDeathNotice;

    // Object state.
    // mObject的fieldId
    jfieldID mObject;
    // mSelf的fieldId
    jfieldID mSelf;
    // mOrgue的fieldId
    jfieldID mOrgue;

} gBinderProxyOffsets;
// 各种方法
static const JNINativeMethod gBinderProxyMethods[] = {
     /* name, signature, funcPtr */
    {"pingBinder",          "()Z", (void*)android_os_BinderProxy_pingBinder},
    {"isBinderAlive",       "()Z", (void*)android_os_BinderProxy_isBinderAlive},
    {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor},
    {"transactNative",      "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
    {"linkToDeath",         "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
    {"unlinkToDeath",       "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
    {"destroy",             "()V", (void*)android_os_BinderProxy_destroy},
};
static int int_register_android_os_BinderProxy(JNIEnv* env)
{
    jclass clazz = FindClassOrDie(env, "java/lang/Error");
    gErrorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);

    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;");
    gBinderProxyOffsets.mOrgue = GetFieldIDOrDie(env, clazz, "mOrgue", "J");

    clazz = FindClassOrDie(env, "java/lang/Class");
    gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");

    return RegisterMethodsOrDie(
        env, kBinderProxyPathName,
        gBinderProxyMethods, NELEM(gBinderProxyMethods));
}
/frameworks/native/libs/binder/BpBinder.cpp:
status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    // Once a binder has died, it will never come back to life.
    if (mAlive) {
        // 调用了IPCThreadState的transact方法
        status_t status = IPCThreadState::self()->transact(
            mHandle, code, data, reply, flags);
        if (status == DEAD_OBJECT) mAlive = 0;
        return status;
    }

    return DEAD_OBJECT;
}

我们可以看到BpBinder调用了IPCThreadStatetransact方法:

/frameworks/native/libs/binder/IPCThreadState.cpp:
status_t IPCThreadState::transact(int32_t handle,
                                  uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags)
{
    status_t err = data.errorCheck();

    flags |= TF_ACCEPT_FDS;
    ......
    if (err == NO_ERROR) {
        LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
            (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");
        // 写入数据
        err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
    }
    ......
    if ((flags & TF_ONE_WAY) == 0) {
        ......
        if (reply) {
            // 等待响应
            err = waitForResponse(reply);
        } else {
            Parcel fakeReply;
            err = waitForResponse(&fakeReply);
        }
        ......
     
    } else {
        err = waitForResponse(NULL, NULL);
    }

    return err;
}
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
    int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
    binder_transaction_data tr;

    tr.target.ptr = 0; /* Don't pass uninitialized stack data to a remote process */
    tr.target.handle = handle;
    tr.code = code;
    tr.flags = binderFlags;
    tr.cookie = 0;
    tr.sender_pid = 0;
    tr.sender_euid = 0;

    const status_t err = data.errorCheck();
    if (err == NO_ERROR) {
        tr.data_size = data.ipcDataSize();
        tr.data.ptr.buffer = data.ipcData();
        tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
        tr.data.ptr.offsets = data.ipcObjects();
    } else if (statusBuffer) {
        tr.flags |= TF_STATUS_CODE;
        *statusBuffer = err;
        tr.data_size = sizeof(status_t);
        tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer);
        tr.offsets_size = 0;
        tr.data.ptr.offsets = 0;
    } else {
        return (mLastError = err);
    }
    //数据写入mOut
    mOut.writeInt32(cmd);
    mOut.write(&tr, sizeof(tr));

    return NO_ERROR;
}

数据写入完成后就开始等待响应:

/frameworks/native/libs/binder/IPCThreadState.cpp:
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
    uint32_t cmd;
    int32_t err;

    while (1) {
        // 这里面会进行ioctl操作,不是很懂。。。
        if ((err=talkWithDriver()) < NO_ERROR) break;
        err = mIn.errorCheck();
        if (err < NO_ERROR) break;
        if (mIn.dataAvail() == 0) continue;

        cmd = (uint32_t)mIn.readInt32();

        IF_LOG_COMMANDS() {
            alog << "Processing waitForResponse Command: "
                << getReturnString(cmd) << endl;
        }
        // cmd = BC_TRANSACTION,这里执行default
        switch (cmd) {
        ......

        default:
            // 调用executeCommand方法
            err = executeCommand(cmd);
            if (err != NO_ERROR) goto finish;
            break;
        }
    }

finish:
......
    return err;
}

因为我们传入的是BC_TRANSACTION命令,所以最后进入executeCommand方法:

/frameworks/native/libs/binder/IPCThreadState.cpp:
status_t IPCThreadState::executeCommand(int32_t cmd)
{
    BBinder* obj;
    RefBase::weakref_type* refs;
    status_t result = NO_ERROR;

    switch ((uint32_t)cmd) {
    ......
    case BR_TRANSACTION:
        {
            binder_transaction_data tr;
            // 把之前写入out中的数据读取出来
            result = mIn.read(&tr, sizeof(tr));
            ALOG_ASSERT(result == NO_ERROR,
                "Not enough command data for brTRANSACTION");
            if (result != NO_ERROR) break;

            Parcel buffer;
            buffer.ipcSetDataReference(
                reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                tr.data_size,
                reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
                tr.offsets_size/sizeof(binder_size_t), freeBuffer, this);

            const pid_t origPid = mCallingPid;
            const uid_t origUid = mCallingUid;
            const int32_t origStrictModePolicy = mStrictModePolicy;
            const int32_t origTransactionBinderFlags = mLastTransactionBinderFlags;

            mCallingPid = tr.sender_pid;
            mCallingUid = tr.sender_euid;
            mLastTransactionBinderFlags = tr.flags;

            Parcel reply;
            status_t error;
            ......
            if (tr.target.ptr) {
                //
                if (reinterpret_cast<RefBase::weakref_type*>(
                        tr.target.ptr)->attemptIncStrong(this)) {
                    // 这里我认为会调用JavaBBinder的transact方法
                    error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
                            &reply, tr.flags);
                    reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
                } else {
                    error = UNKNOWN_TRANSACTION;
                }

            } else {
                error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
            }
            ......
            
            mCallingPid = origPid;
            mCallingUid = origUid;
            mStrictModePolicy = origStrictModePolicy;
            mLastTransactionBinderFlags = origTransactionBinderFlags;
            ......
        }
        break;
        ......
    }
        ......
    return result;
}

紧接着会将我们写入的数据读取出来,并调用JavaBBindertransact方法(没有重写此方法,所以调用BBinder中的transact方法):
/frameworks/native/libs/binder/Binder.cpp:
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
data.setDataPosition(0);

status_t err = NO_ERROR;
switch (code) {
    case PING_TRANSACTION:
        reply->writeInt32(pingBinder());
        break;
    default:
        err = onTransact(code, data, reply, flags);
        break;
}

if (reply != NULL) {
    reply->setDataPosition(0);
}

return err;

}

最终调用``JavaBBinder``中的``onTransact``方法:
/frameworks/base/core/jni/android_util_Binder.cpp:
JavaBBinder:
virtual status_t onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
{
    JNIEnv* env = javavm_to_jnienv(mVM);

    IPCThreadState* thread_state = IPCThreadState::self();
    const int32_t strict_policy_before = thread_state->getStrictModePolicy();
    // 调用Binder的execTransact方法
    jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
        code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
    ......
    return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
}

JavaBBinder中会执行env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);方法,了解JNI的话就会知道这里会调用方法id是mExecTransact的方法,这对应就是Binder中的execTransact方法:

private boolean execTransact(int code, long dataObj, long replyObj,
        int flags) {
    // 根据内存地址生成数据
    Parcel data = Parcel.obtain(dataObj);
    Parcel reply = Parcel.obtain(replyObj);
    boolean res;
    final boolean tracingEnabled = Binder.isTracingEnabled();
    try {
        if (tracingEnabled) {
            Trace.traceBegin(Trace.TRACE_TAG_ALWAYS, getClass().getName() + ":" + code);
        }
        // 调用onTransact方法
        res = onTransact(code, data, reply, flags);
    } catch (RemoteException|RuntimeException e) {
        ......
    } catch (OutOfMemoryError e) {
        ......
    } finally {
        ......
    }
    checkParcel(this, code, reply, "Unreasonably large binder reply buffer");
    reply.recycle();
    data.recycle();
    StrictMode.clearGatheredViolations();

    return res;
}

如我们所料,这里面调用了Binder的onTransact方法最终执行我们远端Service的方法,整个流程到这里就结束了。

7. 总结

对于native层我了解不是很多,这次算是硬着头皮一点点分析出来的(主要是想给自己说的过去的理由,不然根本不会写这篇文章),如果不分析native层的话,整个流程还是比较简单的:

  1. 客户端获取远端服务的代理,通过IXxx.Stub.asInterface()创建代理类。
  2. 客户端通过调用远端代理类的transact方法调用远端服务的具体方法。
  3. native层通过反射调用Binder类的execTransact方法,最终调用Binder类的onTransact方法完成本次方法,并将结果写入reply
  4. 客户端通过reply来获取数据。

至此,整个流程已经完毕。


OK
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容