Android 8.0系统源码分析--Binder进程间通信(一)

     开始我们的沉淀之路,老罗的书中第二章讲的是Android HAL层的知识,而且直接自己实现了一个虚拟的freg驱动程序,后面的几节是分别从native、java层如何访问这个虚拟的驱动程序接口,我这里没有这样的环境,所以就不分析这节了,第三章的智能指针我对比8.0系统源码和老罗的书,基本修改很小,大家如果要学习的话,就直接看老罗的书吧,这也反映出一个问题,就是我们学到的知识肯定是有用的,老罗在自己博客下面回答博友的提问时也一直在强调这点,我们学过的、学会的知识不可能浪费,没有用,肯定是有用的,即使上层再如何变化,但是涉及到核心的东西,变化也是很小的。老罗书中的第四章讲的是Log驱动的实现,对比Log来说,我们一般也就是会使用就可以了,所以也不打算在这一章节上花时间。

     那么我们就进入第五章--Binder进程间通信。这是最有分量的一节,难度也非常大,之前自己也看过老罗的Binder系列博客很久了,但是对其中的各各环节还是理解的不透,我们就从这里开始学习吧。

     老罗分析Binder进程间通信的实现时,开始讲解了很多Binder的结构体,我个人讲不清这个,我就按照自己的思路来学吧。如果大家搞过应用层的开发,相信大家都很清楚,我们使用的最多的就是Activity,它的启动过程就是一个完整的Binder调用,那么我们就以这个过程为学习路线,来分析一下startActivity的过程中Application应用层是怎么通过Binder进程间通信调用到ActivityManagerServie当中的。

     我们的入口函数当然就是Activity类的startActivity方法了。Activity类的startActivity方法实现很简单,就是直接调用两个参数的startActivity方法,此时传入的第二个参数options为空,该方法的实现如下:

@Override
public void startActivity(Intent intent) {
    this.startActivity(intent, null);
}

@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        // Note we want to go through this call for compatibility with
        // applications that may have overridden the method.
        startActivityForResult(intent, -1);
    }
}

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
    startActivityForResult(intent, requestCode, null);
}
    
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
    @Nullable Bundle options) {
    if (mParent == null) {
        options = transferSpringboardActivityOptions(options);
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        if (requestCode >= 0) {
            // If this start is requesting a result, we can avoid making
            // the activity visible until the result is received.  Setting
            // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
            // activity hidden during this time, to avoid flickering.
            // This can only be done when a result is requested because
            // that guarantees we will get information back when the
            // activity is finished, no matter what happens to it.
            mStartedActivity = true;
        }
        cancelInputsAndStartExitTransition(options);
        // TODO Consider clearing/flushing other event sources and events for child windows.
    } else {
        if (options != null) {
            mParent.startActivityFromChild(this, intent, requestCode, options);
        } else {
            // Note we want to go through this method for compatibility with
            // existing applications that may have overridden it.
            mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
}
     按照我们正常的启动逻辑,第二个参数options为空,所以进入else分支,调用startActivityForResult来进一步处理,再次调用三个参数的同名方法,mParent变量一般为空,所以会进入第一个if分支,这里最重要的就是mInstrumentation.execStartActivity、mMainThread.sendActivityResult这两句逻辑了。mInstrumentation.execStartActivity这句就会进入到我们的目标,将Activity的启动数据封装完成后,通过binder机制发送到Server端,也就是ActivityManagerService;mMainThread.sendActivityResult这句在判断调用正常的情况下,通知应用主线程ActivityThread来处理启动后的结果,mMainThread是一个ActivityThread类型的成员变量,它是在当前的Activity启动成功后,通过应用程序主线程ActivityThread类的performLaunchActivity方法来赋值的。我们就追踪mInstrumentation.execStartActivity的实现就可以了。mInstrumentation是Activity类的成员变量,它的类型是Instrumentation,它有三个execStartActivity重名方法,而当前的调用是第四个参数为Activity类型的,该方法的实现如下:

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    Uri referrer = target != null ? target.onProvideReferrer() : null;
    if (referrer != null) {
        intent.putExtra(Intent.EXTRA_REFERRER, referrer);
    }
    if (mActivityMonitors != null) {
        synchronized (mSync) {
            final int N = mActivityMonitors.size();
            for (int i=0; i= 0 ? am.getResult() : null;
                    }
                    break;
                }
            }
        }
    }
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess(who);
        int result = ActivityManager.getService()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

     这个方法中最重要的就是最后的try/catch了,通过调用ActivityManager.getService().startActivity来启动目标Activity,然后调用checkStartActivityResult方法来检查启动结果。我们继续跟踪ActivityManager.getService().startActivity,它需要分两段来分析。

     第一段调用ActivityManager.getService()来获取binder代理对象,它的实现如下:

/**
 * @hide
 */
public static IActivityManager getService() {
    return IActivityManagerSingleton.get();
}

private static final Singleton IActivityManagerSingleton =
        new Singleton() {
            @Override
            protected IActivityManager create() {
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                final IActivityManager am = IActivityManager.Stub.asInterface(b);
                return am;
            }
        };

     IActivityManagerSingleton是ActivityManager类中类型为Singleton的静态成员变量,get()方法是单例模式Singleton来实现的,当调用get()方法时,就会执行范型 T 的create()方法,Singleton类的代码如下:

public abstract class Singleton {
    private T mInstance;

    protected abstract T create();

    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}

     ActivityManager这里以Context.ACTIVITY_SERVICE为key值获取到一个IBinder对象,然后调用IActivityManager.Stub.asInterface(b)进行转换,就会得到一个BinderProxy对象,IActivityManager.aidl文件经过编译后就会生成IActivityManager.java,但是源码中没有,我就自己写了一个ICameraService.aidl文件,然后生成对应的ICameraService.java,我们可以用它来对比分析一下,ICameraService.java源码如下:

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: D:\\Work\\Project\\workstudio\\CameraService\\app\\src\\main\\aidl\\com\\huawei\\cameraservice\\ICameraService.aidl
 */
package com.huawei.cameraservice;
// Declare any non-default types here with import statements

public interface ICameraService extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.huawei.cameraservice.ICameraService {
        private static final java.lang.String DESCRIPTOR = "com.huawei.cameraservice.ICameraService";

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.huawei.cameraservice.ICameraService interface,
         * generating a proxy if needed.
         */
        public static com.huawei.cameraservice.ICameraService asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.huawei.cameraservice.ICameraService))) {
                return ((com.huawei.cameraservice.ICameraService) iin);
            }
            return new com.huawei.cameraservice.ICameraService.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_getMainCameraId: {
                    data.enforceInterface(DESCRIPTOR);
                    int _result = this.getMainCameraId();
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
                case TRANSACTION_openCamera: {
                    data.enforceInterface(DESCRIPTOR);
                    int _arg0;
                    _arg0 = data.readInt();
                    int _result = this.openCamera(_arg0);
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.huawei.cameraservice.ICameraService {
            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 getMainCameraId() 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);
                    mRemote.transact(Stub.TRANSACTION_getMainCameraId, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public int openCamera(int id) 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(id);
                    mRemote.transact(Stub.TRANSACTION_openCamera, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_getMainCameraId = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_openCamera = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }

    public int getMainCameraId() throws android.os.RemoteException;

    public int openCamera(int id) throws android.os.RemoteException;
}
     DESCRIPTOR就是当前Server的描述符,比如ActivityManagerService的描述符就是“activity”,queryLocalInterface方法会在本进程中查找,假如我们想要获取到ActivityManagerService,而且我们是在SystemServer进程当中 ,那肯定就直接找到了,我们当前的声明中,启动Activity时本进程肯定是找不到,所以 iin 结果为空,那么就以obj对参数创建一个Proxy对象返回给我们,实际上这个Proxy对象就是BinderProxy,它定义在frameworks\base\core\java\android\os\Binder.java文件当中。好,这里我们获取到BinderProxy对象之后,继续往下读代码。那么就调用它的startActivity方法,因为没有IActivityManager编译出来的java文件,我们就以openCamera方法为例来继续我们的流程。Proxy类的代码如下:

        private static class Proxy implements com.huawei.cameraservice.ICameraService {
            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 getMainCameraId() 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);
                    mRemote.transact(Stub.TRANSACTION_getMainCameraId, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public int openCamera(int id) 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(id);
                    mRemote.transact(Stub.TRANSACTION_openCamera, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }
     像这样的aidl生成的方法全部都是这种格式:1、获取到两个Parcel对象,一个用于存储我们调用方法时的数据,一个用于存储方法执行完成后的返回结果;2、依次写入我们的通信数据;3、执行transact方法;4、读取返回结果,如果有异常,则抛出异常,如果没有异常,则说明通信成功,将结果返回到Client端。这里要特别说明的就是,Parcel用于存储通信数据和取返回结果时,一定完全按照服务器定义好的顺序,否则数据就会出错。这是为什么呢?要查这个原因,就要看看Parcel这个数据载体的实现了。

     首先来看一下Parcel.obtain()方法的实现,源码如下:

    /**
     * Retrieve a new Parcel object from the pool.
     */
    public static Parcel obtain() {
        final Parcel[] pool = sOwnedPool;
        synchronized (pool) {
            Parcel p;
            for (int i=0; i
     这里就是用了池的概念,sOwnedPool是Parcel类的成员变量,它的类型是Parcel[]数组,初始化长度为6,首次执行Parcel类的obtain方法时,sOwnedPool中的成员全部为空,所以直接新建对象返回,但是从这里看不出来和对象池有什么关系,sOwnedPool中每个元素是怎么赋值的?奇妙的地方就在recycle()方法当中了,我们来看一下recycle()方法的实现:

    /**
     * Put a Parcel object back into the pool.  You must not touch
     * the object after this call.
     */
    public final void recycle() {
        if (DEBUG_RECYCLE) mStack = null;
        freeBuffer();

        final Parcel[] pool;
        if (mOwnsNativeParcelObject) {
            pool = sOwnedPool;
        } else {
            mNativePtr = 0;
            pool = sHolderPool;
        }

        synchronized (pool) {
            for (int i=0; i
     从注释也可以看出来,是将一个即将要回收的对象放入对象池中,而释放的只是它所占用的内存空间而已,这里最奇妙的就是第一个if分支给局部变量pool赋值了,因为pool在声明时没有初始化,所以直接将成员变量sOwnedPool赋值给局部变量pool之后,那么它们两个就是同一个对象了,而且hashcode值也相同,所以接下来给pool的元素赋值时就相当于为sOwnedPool元素赋值了,这样sOwnedPool中的6个元素就会依次在回收6个新建对象时依次被填充上了!!真是非常巧妙,但是写法上不容易理解!

     好,我们继续回到主流程中,当新建一个Parcel对象时,传入的参数nativePtr为0,表示该对象还没有在native层创建,于是接着调用nativeCreate来执行native层的创建。native层的创建很简单,就是直接新建了一个Parcel的对象,然后将该对象的指针返回来,我们随便来看一下nativeWriteString方法的实现,以更好的理解Parcel写入数据时必须按照顺序的原因。nativeWriteString方法的JNI定义是由android_os_Parcel_writeString来执行的,android_os_Parcel_writeString的实现代码如下:

static void android_os_Parcel_writeString(JNIEnv* env, jclass clazz, jlong nativePtr, jstring val)
{
    Parcel* parcel = reinterpret_cast(nativePtr);
    if (parcel != NULL) {
        status_t err = NO_MEMORY;
        if (val) {
            const jchar* str = env->GetStringCritical(val, 0);
            if (str) {
                err = parcel->writeString16(
                    reinterpret_cast(str),
                    env->GetStringLength(val));
                env->ReleaseStringCritical(val, str);
            }
        } else {
            err = parcel->writeString16(NULL, 0);
        }
        if (err != NO_ERROR) {
            signalExceptionForError(env, clazz, err);
        }
    }
}
     nativePtr就是在创建C++层对象时的指针,首先将我们传入的String字符串转换为char数组,然后调用parcel类的writeString16方法进行写入。writeString16方法的实现在frameworks\native\libs\binder\Parcel.cpp文件当中,源码如下:

status_t Parcel::writeString16(const String16& str)
{
    return writeString16(str.string(), str.size());
}

status_t Parcel::writeString16(const char16_t* str, size_t len)
{
    if (str == NULL) return writeInt32(-1);

    status_t err = writeInt32(len);
    if (err == NO_ERROR) {
        len *= sizeof(char16_t);
        uint8_t* data = (uint8_t*)writeInplace(len+sizeof(char16_t));
        if (data) {
            memcpy(data, str, len);
            *reinterpret_cast(data+len) = 0;
            return NO_ERROR;
        }
        err = mError;
    }
    return err;
}
      看到这里我们就非常清楚了,当写入一个String字符串时,会先写入该字符串的长度len,然后才调用memcpy系统函数将字符串内容复制申请好的内存空间中,所以千万不能乱读乱写,否则读出来的数据肯定就是错误的数据了。

     Parcel的分析就暂时到这里,我们继续回到主流程当中。mRemote获取到的就是一个BinderProxy的对象,那我们就继续看它的transact方法的实现逻辑。BinderProxy类的定义在frameworks\base\core\java\android\os\Binder.java文件中,它的transact方法的实现如下:

    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");

        if (mWarnOnBlocking && ((flags & FLAG_ONEWAY) == 0)) {
            // For now, avoid spamming the log by disabling after we've logged
            // about this interface at least once
            mWarnOnBlocking = false;
            Log.w(Binder.TAG, "Outgoing transactions from this process must be FLAG_ONEWAY",
                    new Throwable());
        }

        final boolean tracingEnabled = Binder.isTracingEnabled();
        if (tracingEnabled) {
            final Throwable tr = new Throwable();
            Binder.getTransactionTracker().addTrace(tr);
            StackTraceElement stackTraceElement = tr.getStackTrace()[1];
            Trace.traceBegin(Trace.TRACE_TAG_ALWAYS,
                    stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName());
        }
        try {
            return transactNative(code, data, reply, flags);
        } finally {
            if (tracingEnabled) {
                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
            }
        }
    }
     该方法首先对输入数据data的大小进行检查,是通过调用checkParcel方法来完成的,它当中执行if (CHECK_PARCEL_SIZE && parcel.dataSize() >= 800*1024) 判断,也就是说Binder进程间通信的传输数据最大为800K,如果超过800K,就会打印出Unreasonably large binder buffer异常。所以我们在使用Binder进程间通信时,如果数据量过大,就要考虑其他方案来实现我们的目的。第一个参数code就指我们调用Server端的方法请求码,它是以android.os.IBinder.FIRST_CALL_TRANSACTION为基数递增的,最后一个参数flags的意思是此次请求是否同步。比如我们现在分析的场景,启动Activity时,不仅要求ActivityManagerService完成Activity的启动,而且还要等待它给我们返回结果才能继续往下执行,也就是同步的,因此它的值为0;而假如我们要使用音乐播放器播放一段音乐,不需要它给我们返回结果,我们只需要将命令发送给MediaServer就直接返回继续处理我们的逻辑了,这种场景下就是异步的,那么它的值就是1。最后继续调用transactNative来处理我们的请求。

     transactNative方法的实现在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
{
    if (dataObj == NULL) {
        jniThrowNullPointerException(env, NULL);
        return JNI_FALSE;
    }

    Parcel* data = parcelForJavaObject(env, dataObj);
    if (data == NULL) {
        return JNI_FALSE;
    }
    Parcel* reply = parcelForJavaObject(env, replyObj);
    if (reply == NULL && replyObj != NULL) {
        return JNI_FALSE;
    }

    IBinder* target = (IBinder*)
        env->GetLongField(obj, gBinderProxyOffsets.mObject);
    if (target == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
        return JNI_FALSE;
    }

    ALOGV("Java code calling transact on %p in Java object %p with code %" PRId32 "\n",
            target, obj, code);


    bool time_binder_calls;
    int64_t start_millis;
    if (kEnableBinderSample) {
        // Only log the binder call duration for things on the Java-level main thread.
        // But if we don't
        time_binder_calls = should_time_binder_calls();

        if (time_binder_calls) {
            start_millis = uptimeMillis();
        }
    }

    //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();

    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;
}
      该方法先对data数据进行判断,如果data为空,就直接抛出空指针异常。紧接着将我们从Java层传进来的对象转换为C++层的指针,如果转换出错,则中断执行,直接返回JNI_FALSE,下一步获取到C++层的Binder代理对象指针,实际是一个BpBinder对象,然后将封装好的C++层的四个对象作为参数,调用BpBinder对象的transact方法。

     BpBinder类的transact方法实现在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) {
        status_t status = IPCThreadState::self()->transact(
            mHandle, code, data, reply, flags);
        if (status == DEAD_OBJECT) mAlive = 0;
        return status;
    }

    return DEAD_OBJECT;
}
      首先检查当前的Binder代理对象是否还存活,只有在存活的状态下才能进行后续的逻辑。IPCThreadState和ProcessState两个类就是Binder通信的适配器,中转逻辑都是在它们两个类中完成的,它的self()方法获取到的就是一个IPCThreadState对象,我们继续分析它的transact方法的实现。

     IPCThreadState类的transact方法实现在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_LOG_TRANSACTIONS() {
        TextOutput::Bundle _b(alog);
        alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand "
            << handle << " / code " << TypeCode(code) << ": "
            << indent << data << dedent << endl;
    }

    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 (err != NO_ERROR) {
        if (reply) reply->setError(err);
        return (mLastError = err);
    }

    if ((flags & TF_ONE_WAY) == 0) {
        #if 0
        if (code == 4) { // relayout
            ALOGI(">>>>>> CALLING transaction 4");
        } else {
            ALOGI(">>>>>> CALLING transaction %d", code);
        }
        #endif
        if (reply) {
            err = waitForResponse(reply);
        } else {
            Parcel fakeReply;
            err = waitForResponse(&fakeReply);
        }
        #if 0
        if (code == 4) { // relayout
            ALOGI("<<<<<< RETURNING transaction 4");
        } else {
            ALOGI("<<<<<< RETURNING transaction %d", code);
        }
        #endif

        IF_LOG_TRANSACTIONS() {
            TextOutput::Bundle _b(alog);
            alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand "
                << handle << ": ";
            if (reply) alog << indent << *reply << dedent << endl;
            else alog << "(none requested)" << endl;
        }
    } else {
        err = waitForResponse(NULL, NULL);
    }

    return err;
}
      该方法首先仍然会进行数据检查,TF_ACCEPT_FDS表示是否可以携带文件描述符,接下来调用writeTransactionData将数据进一步封装成binder_transaction_data结构体,老罗的书中对所有Binder通信的结构体有非常详细的分析说明,大家可以去Android 8.0系统源码分析--开篇下载老罗的Android系统源代码情景分析【罗升阳著】PDF版本电子书。下一步继续调用waitForResponse来执行Binder通信。

     waitForResponse方法的实现源码如下:

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
    uint32_t cmd;
    int32_t err;

    while (1) {
        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;
        }

        switch (cmd) {
        case BR_TRANSACTION_COMPLETE:
            if (!reply && !acquireResult) goto finish;
            break;

        case BR_DEAD_REPLY:
            err = DEAD_OBJECT;
            goto finish;

        case BR_FAILED_REPLY:
            err = FAILED_TRANSACTION;
            goto finish;

        case BR_ACQUIRE_RESULT:
            {
                ALOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT");
                const int32_t result = mIn.readInt32();
                if (!acquireResult) continue;
                *acquireResult = result ? NO_ERROR : INVALID_OPERATION;
            }
            goto finish;

        case BR_REPLY:
            {
                binder_transaction_data tr;
                err = mIn.read(&tr, sizeof(tr));
                ALOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");
                if (err != NO_ERROR) goto finish;

                if (reply) {
                    if ((tr.flags & TF_STATUS_CODE) == 0) {
                        reply->ipcSetDataReference(
                            reinterpret_cast(tr.data.ptr.buffer),
                            tr.data_size,
                            reinterpret_cast(tr.data.ptr.offsets),
                            tr.offsets_size/sizeof(binder_size_t),
                            freeBuffer, this);
                    } else {
                        err = *reinterpret_cast(tr.data.ptr.buffer);
                        freeBuffer(NULL,
                            reinterpret_cast(tr.data.ptr.buffer),
                            tr.data_size,
                            reinterpret_cast(tr.data.ptr.offsets),
                            tr.offsets_size/sizeof(binder_size_t), this);
                    }
                } else {
                    freeBuffer(NULL,
                        reinterpret_cast(tr.data.ptr.buffer),
                        tr.data_size,
                        reinterpret_cast(tr.data.ptr.offsets),
                        tr.offsets_size/sizeof(binder_size_t), this);
                    continue;
                }
            }
            goto finish;

        default:
            err = executeCommand(cmd);
            if (err != NO_ERROR) goto finish;
            break;
        }
    }

finish:
    if (err != NO_ERROR) {
        if (acquireResult) *acquireResult = err;
        if (reply) reply->setError(err);
        mLastError = err;
    }

    return err;
}
      这里就是Binder通信比较核心的地方了,其中的BR_TRANSACTION_COMPLETE、BR_DEAD_REPLY、BR_ACQUIRE_RESULT、BR_REPLY都是Binder的通信协议,talkWithDriver方法就是最终和Binder驱动进行交互了,它是通过调用ioctl系统函数,将封装好的数据发送到Binder驱动中,然后由Binder驱动进行解析以实现和Server端的通信的。Binder通信协议定义在bionic\libc\kernel\uapi\linux\android\binder.h文件当中,包括了binder_transaction_data数据交互协议、binder_write_read数据结构体、binder_driver_return_protocol返回协议、binder_driver_command_protocol命令协议,该文件的整个源码如下:

/****************************************************************************
 ****************************************************************************
 ***
 ***   This header was automatically generated from a Linux kernel header
 ***   of the same name, to make information necessary for userspace to
 ***   call into the kernel available to libc.  It contains only constants,
 ***   structures, and macros generated from the original header, and thus,
 ***   contains no copyrightable information.
 ***
 ***   To edit the content of this header, modify the corresponding
 ***   source file (e.g. under external/kernel-headers/original/) then
 ***   run bionic/libc/kernel/tools/update_all.py
 ***
 ***   Any manual change here will be lost the next time this script will
 ***   be run. You've been warned!
 ***
 ****************************************************************************
 ****************************************************************************/
#ifndef _UAPI_LINUX_BINDER_H
#define _UAPI_LINUX_BINDER_H
#include 
#include 
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define B_PACK_CHARS(c1,c2,c3,c4) ((((c1) << 24)) | (((c2) << 16)) | (((c3) << 8)) | (c4))
#define B_TYPE_LARGE 0x85
enum {
  BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE),
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE),
  BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE),
  BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE),
  BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE),
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
};
enum {
  FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
  FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
};
#ifdef BINDER_IPC_32BIT
typedef __u32 binder_size_t;
typedef __u32 binder_uintptr_t;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#else
typedef __u64 binder_size_t;
typedef __u64 binder_uintptr_t;
#endif
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
struct flat_binder_object {
  __u32 type;
  __u32 flags;
  union {
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
    binder_uintptr_t binder;
    __u32 handle;
  };
  binder_uintptr_t cookie;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
};
struct binder_write_read {
  binder_size_t write_size;
  binder_size_t write_consumed;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  binder_uintptr_t write_buffer;
  binder_size_t read_size;
  binder_size_t read_consumed;
  binder_uintptr_t read_buffer;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
};
struct binder_version {
  __s32 protocol_version;
};
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#ifdef BINDER_IPC_32BIT
#define BINDER_CURRENT_PROTOCOL_VERSION 7
#else
#define BINDER_CURRENT_PROTOCOL_VERSION 8
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#endif
#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read)
#define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64)
#define BINDER_SET_MAX_THREADS _IOW('b', 5, __u32)
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, __s32)
#define BINDER_SET_CONTEXT_MGR _IOW('b', 7, __s32)
#define BINDER_THREAD_EXIT _IOW('b', 8, __s32)
#define BINDER_VERSION _IOWR('b', 9, struct binder_version)
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
enum transaction_flags {
  TF_ONE_WAY = 0x01,
  TF_ROOT_OBJECT = 0x04,
  TF_STATUS_CODE = 0x08,
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  TF_ACCEPT_FDS = 0x10,
};
struct binder_transaction_data {
  union {
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
    __u32 handle;
    binder_uintptr_t ptr;
  } target;
  binder_uintptr_t cookie;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  __u32 code;
  __u32 flags;
  pid_t sender_pid;
  uid_t sender_euid;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  binder_size_t data_size;
  binder_size_t offsets_size;
  union {
    struct {
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
      binder_uintptr_t buffer;
      binder_uintptr_t offsets;
    } ptr;
    __u8 buf[8];
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  } data;
};
struct binder_ptr_cookie {
  binder_uintptr_t ptr;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  binder_uintptr_t cookie;
};
struct binder_handle_cookie {
  __u32 handle;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  binder_uintptr_t cookie;
} __packed;
struct binder_pri_desc {
  __s32 priority;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  __u32 desc;
};
struct binder_pri_ptr_cookie {
  __s32 priority;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  binder_uintptr_t ptr;
  binder_uintptr_t cookie;
};
enum binder_driver_return_protocol {
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  BR_ERROR = _IOR('r', 0, __s32),
  BR_OK = _IO('r', 1),
  BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data),
  BR_REPLY = _IOR('r', 3, struct binder_transaction_data),
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  BR_ACQUIRE_RESULT = _IOR('r', 4, __s32),
  BR_DEAD_REPLY = _IO('r', 5),
  BR_TRANSACTION_COMPLETE = _IO('r', 6),
  BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie),
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie),
  BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie),
  BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie),
  BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie),
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  BR_NOOP = _IO('r', 12),
  BR_SPAWN_LOOPER = _IO('r', 13),
  BR_FINISHED = _IO('r', 14),
  BR_DEAD_BINDER = _IOR('r', 15, binder_uintptr_t),
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t),
  BR_FAILED_REPLY = _IO('r', 17),
};
enum binder_driver_command_protocol {
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data),
  BC_REPLY = _IOW('c', 1, struct binder_transaction_data),
  BC_ACQUIRE_RESULT = _IOW('c', 2, __s32),
  BC_FREE_BUFFER = _IOW('c', 3, binder_uintptr_t),
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  BC_INCREFS = _IOW('c', 4, __u32),
  BC_ACQUIRE = _IOW('c', 5, __u32),
  BC_RELEASE = _IOW('c', 6, __u32),
  BC_DECREFS = _IOW('c', 7, __u32),
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie),
  BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie),
  BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc),
  BC_REGISTER_LOOPER = _IO('c', 11),
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  BC_ENTER_LOOPER = _IO('c', 12),
  BC_EXIT_LOOPER = _IO('c', 13),
  BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_handle_cookie),
  BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_handle_cookie),
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  BC_DEAD_BINDER_DONE = _IOW('c', 16, binder_uintptr_t),
};
#endif
     剩下的就到了Binder进程间通信最核心的地方了,也就是waitForResponse之后的流程,我们下次继续分析。

     如果想详细了解Binder进程间通信内容,可以查看老罗的系列博客,讲的非常好,地址如下:

     Android进程间通信(IPC)机制Binder简要介绍和学习计划

     浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路

     浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路

     Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析

     Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析








你可能感兴趣的:(Android框架总结,Android源码解析,android,framework)