1. 程式人生 > >Android 8.0系統原始碼分析--Binder程序間通訊(一)

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<N; i++) {
                final ActivityMonitor am = mActivityMonitors.get(i);
                ActivityResult result = null;
                if (am.ignoreMatchingSpecificIntents()) {
                    result = am.onStartActivity(intent);
                }
                if (result != null) {
                    am.mHits++;
                    return result;
                } else if (am.match(who, null, intent)) {
                    am.mHits++;
                    if (am.isBlocking()) {
                        return requestCode >= 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<IActivityManager> IActivityManagerSingleton =
        new Singleton<IActivityManager>() {
            @Override
            protected IActivityManager create() {
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                final IActivityManager am = IActivityManager.Stub.asInterface(b);
                return am;
            }
        };

     IActivityManagerSingleton是ActivityManager類中型別為Singleton<IActivityManager>的靜態成員變數,get()方法是單例模式Singleton來實現的,當呼叫get()方法時,就會執行範型 T 的create()方法,Singleton類的程式碼如下:

public abstract class Singleton<T> {
    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<POOL_SIZE; i++) {
                p = pool[i];
                if (p != null) {
                    pool[i] = null;
                    if (DEBUG_RECYCLE) {
                        p.mStack = new RuntimeException();
                    }
                    return p;
                }
            }
        }
        return new Parcel(0);
    }
     這裡就是用了池的概念,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<POOL_SIZE; i++) {
                if (pool[i] == null) {
                    pool[i] = this;
                    return;
                }
            }
        }
    }
     從註釋也可以看出來,是將一個即將要回收的物件放入物件池中,而釋放的只是它所佔用的記憶體空間而已,這裡最奇妙的就是第一個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<Parcel*>(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<const char16_t*>(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<char16_t*>(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<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);
                    } else {
                        err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
                        freeBuffer(NULL,
                            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), this);
                    }
                } else {
                    freeBuffer(NULL,
                        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), 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 <linux/types.h>
#include <linux/ioctl.h>
/* 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程序間通訊內容,可以檢視老羅的系列部落格,講的非常好,地址如下: