Android進階學習必會:Java Binder中的系統服務

前言

這個知識點是Android進階學習必須掌握的知識點之一,也是高階Android架構師經常問到的點。在這裏分想給大家,希望對大家的工作和學習有所幫助。喜歡本文的記得點贊關注哦~

在前面的Android Binder原理(三)系統服務的註冊過程這篇文章中,我介紹的是Native Binder中的系統服務的註冊過程,這一過程的核心是ServiceManager,而在Java Binder中,也有一個ServiceManager,只不過這個ServiceManager是Java文件。
既然要將系統服務註冊到ServiceManager,那麼需要選擇一個系統服務爲例,這裏以常見的AMS爲例。

1.將AMS註冊到ServiceManager

在AMS的setSystemProcess方法中,會調用ServiceManager的addService方法,如下所示。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    public void setSystemProcess() {
        try {
            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
                    DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);//1
           ....
        } catch (PackageManager.NameNotFoundException e) {
            throw new RuntimeException(
                    "Unable to find android system package", e);
        }
     ...
    }

註釋1處的Context.ACTIVITY_SERVICE的值爲"activity",作用就是將AMS註冊到ServiceManager中。接着來看
ServiceManager的addService方法。
frameworks/base/core/java/android/os/ServiceManager.java

    public static void addService(String name, IBinder service, boolean allowIsolated,
            int dumpPriority) {
        try {
            getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
    }

主要分析getIServiceManager方法返回的是什麼,代碼如下所示。
frameworks/base/core/java/android/os/ServiceManager.java

   private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }
        sServiceManager = ServiceManagerNative
                .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
        return sServiceManager;
    }

講到這裏,已經積累了幾個點需要分析,分別是:

  • BinderInternal.getContextObject()
  • ServiceManagerNative.asInterface()
  • getIServiceManager().addService()

現在我們來各個擊破它們。

1.1 BinderInternal.getContextObject()

Binder.allowBlocking的作用是將BinderProxy的sWarnOnBlocking值置爲false。主要來分析BinderInternal.getContextObject()做了什麼,這個方法是一個Native方法,找到它對應的函數:
frameworks/base/core/jni/android_util_Binder.cpp

static const JNINativeMethod gBinderInternalMethods[] = {
    { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
   ...
};

對應的函數爲android_os_BinderInternal_getContextObject:
frameworks/base/core/jni/android_util_Binder.cpp

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);//1
    return javaObjectForIBinder(env, b);
}

ProcessState::self()的作用是創建ProcessState,註釋1處最終返回的是BpBinder,不理解的可以查看Android Binder原理(二)ServiceManager中的Binder機制這篇文章。

BpBinder是Native Binder中的Client端,這說明Java層的ServiceManager需要Native層的BpBinder,但是這個BpBinder在Java層是無法直接使用,那麼就需要傳入javaObjectForIBinder函數來做處理,其內部會創建一個BinderProxy對象,這樣我們得知 BinderInternal.getContextObject()最終得到的是BinderProxy。
Android Binder原理(六)Java Binder的初始化這篇文章我們講過,BinderProxy是Java Binder的客戶端的代表。
需要注意的一點是,這個傳入的BpBinder會保存到BinderProxy的成員變量mObject中,後續會再次提到這個點。

1.2 ServiceManagerNative.asInterface()

說到asInterface方法,在Native Binder中也有一個asInterface函數。在Android Binder原理(二)ServiceManager中的Binder機制這篇文章中講過IServiceManager的asInterface函數,它的作用是用BpBinder做爲參數創建BpServiceManager。那麼在Java Binder中的asInterface方法的作用又是什麼?
frameworks/base/core/java/android/os/ServiceManagerNative.java

   static public IServiceManager asInterface(IBinder obj)
    {
        if (obj == null) {
            return null;
        }
        IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ServiceManagerProxy(obj);
    }

根據1.1小節,我們得知obj的值爲BinderProxy,那麼asInterface方法的作用就是用BinderProxy作爲參數創建ServiceManagerProxy。
BinderProxy和BpBinder分別在Jave Binder和Native Binder作爲客戶端的代表,BpServiceManager通過BpBinder來實現通信,同樣的,ServiceManagerProxy也會將業務的請求交給BinderProxy來處理。
分析到這裏,那麼:

        sServiceManager = ServiceManagerNative
                .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));

可以理解爲:

        sServiceManager = new ServiceManagerProxy(BinderProxy);
    }

1.3 getIServiceManager().addService()

根據1.2節的講解,getIServiceManager()返回的是ServiceManagerProxy,ServiceManagerProxy是ServiceManagerNative的內部類,它實現了IServiceManager接口。

來查看ServiceManagerProxy的addService方法,
frameworks/base/core/java/android/os/ServiceManagerNative.java::ServiceManagerProxy

    public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)
            throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        data.writeStrongBinder(service);//1
        data.writeInt(allowIsolated ? 1 : 0);
        data.writeInt(dumpPriority);
        mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);//2
        reply.recycle();
        data.recycle();
    }

註釋1處的data.writeStrongBinder很關鍵,後續會進行分析。這裏又看到了Parcel,它是一個數據包裝器,將請求數據寫入到Parcel類型的對象data中,通過註釋1處的mRemote.transact發送出去,mRemote實際上是BinderProxy,BinderProxy.transact是native函數,實現的函數如下所示。
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);//1
    if (data == NULL) {
        return JNI_FALSE;
    }
    Parcel* reply = parcelForJavaObject(env, replyObj);//2
    if (reply == NULL && replyObj != NULL) {
        return JNI_FALSE;
    }
    IBinder* target = getBPNativeData(env, obj)->mObject.get();//3
    if (target == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
        return JNI_FALSE;
    }
   ...
    status_t err = target->transact(code, *data, reply, flags);//4
    return JNI_FALSE;
}

註釋1和註釋2處,將Java層的Parcel對象轉化成爲Native層的Parcel對象。在1.1小節中,我們得知BpBinder會保存到BinderProxy的成員變量mObject中,因此在註釋3處,從BinderProxy的成員變量mObject中獲取BpBinder。最終會在註釋4處調用BpBinder的transact函數,向Binder驅動發送數據,可以看出Java Binder是需要Native Binder支持的,最終的目的就是向Binder驅動發送和接收數據。

2.引出JavaBBinder

接着回過頭來分析1.3小節遺留下來的data.writeStrongBinder(service),代碼如下所示。
frameworks/base/core/java/android/os/Parcel.java

  public final void writeStrongBinder(IBinder ll) {
        nativeWriteStrongBinder(mNativePtr, val);
    }

nativeWriteStrongBinder是Native方法,實現的函數爲android_os_Parcel_writeStrongBinder:
frameworks/base/core/jni/android_os_Parcel.cpp

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

接着查看註釋1處ibinderForJavaObject函數:
frameworks/base/core/jni/android_util_Binder.cpp

sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
    if (obj == NULL) return NULL;
    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {//1
        JavaBBinderHolder* jbh = (JavaBBinderHolder*)
            env->GetLongField(obj, gBinderOffsets.mObject);
        return jbh->get(env, obj);//2
    }
    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
        return getBPNativeData(env, obj)->mObject;
    }

    ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
    return NULL;
}

註釋2處,如果obj是Java層的BinderProxy類,則返回BpBinder。
註釋1處,如果obj是Java層的Binder類,那麼先獲取JavaBBinderHolder對象,然後在註釋2處調用JavaBBinderHolder的get函數,代碼如下所示。
frameworks/base/core/jni/android_util_Binder.cpp::JavaBBinderHolder

class JavaBBinderHolder
{
public:
    sp<JavaBBinder> get(JNIEnv* env, jobject obj)
    {
        AutoMutex _l(mLock);
        sp<JavaBBinder> b = mBinder.promote();//1
        if (b == NULL) {
            //obj是一個Java層Binder對象
            b = new JavaBBinder(env, obj);//2
            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;
};

成員變量mBinder是wp<JavaBBinder>類型的弱引用,在註釋1處得到sp<JavaBBinder>類型的強引用b,在註釋2處創建JavaBBinder並賦值給b。那麼,JavaBBinderHolder的get函數返回的是JavaBBinder。

data.writeStrongBinder(service)在本文中等價於:

data.writeStrongBinder(new JavaBBinder(env,Binder))。

講到這裏可以得知ServiceManager.addService()傳入的並不是AMS本身,而是JavaBBinder。

3.解析JavaBBinder

接着來分析JavaBBinder,查看它的構造函數:
frameworks/base/core/jni/android_util_Binder.cpp::JavaBBinderHolder::JavaBBinder

class JavaBBinder : public BBinder
{
public:
    JavaBBinder(JNIEnv* env, jobject /* Java Binder */ c)
        : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
    {
        ALOGV("Creating JavaBBinder %p\n", this);
        gNumLocalRefsCreated.fetch_add(1, std::memory_order_relaxed);
        gcIfManyNewRefs(env);
    }
...

可以發現JavaBBinder繼承了BBinder,那麼JavaBBinder的作用是什麼呢?當Binder驅動得到客戶端的請求,緊接着會將響應發送給JavaBBinder,這時會調用JavaBBinder的onTransact函數,代碼如下所示。
frameworks/base/core/jni/android_util_Binder.cpp::JavaBBinderHolder::JavaBBinder

 virtual status_t onTransact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
    {                            
        JNIEnv* env = javavm_to_jnienv(mVM);
        ALOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM);
        IPCThreadState* thread_state = IPCThreadState::self();
        const int32_t strict_policy_before = thread_state->getStrictModePolicy();
        jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
            code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);//1

        ...
        return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
    }

在註釋1處會調用Java層Binder的execTransact函數:
frameworks/base/core/java/android/os/Binder.java

    private boolean execTransact(int code, long dataObj, long replyObj,
            int flags) {
...
        try {
            if (tracingEnabled) {
                Trace.traceBegin(Trace.TRACE_TAG_ALWAYS, getClass().getName() + ":" + code);
            }
            res = onTransact(code, data, reply, flags);//1
        } catch (RemoteException|RuntimeException e) {
           ...
        }
       ...
        return res;
    }

關鍵點是註釋1處的onTransact函數,AMS實現了onTransact函數,從而完成業務實現。
從這裏可有看出,JavaBBinder並沒有實現什麼業務,當它接收到請求時,會調用Binder類的execTransact函數,execTransact函數內部又調用了onTransact函數,系統服務會重寫onTransact函數來實現自身的業務功能。

4.Java Binder架構

Binder架構如下圖所示。

Native Binder的部分在此前的文章已經講過,這裏主要來說說Java Binder部分,從圖中可以看到:
1.Binder是服務端的代表,JavaBBinder繼承BBinder,JavaBBinder通過mObject變量指向Binder。
2.BinderProxy是客戶端的代表,ServiceManager的addService等方法會交由ServiceManagerProxy處理。
3.ServiceManagerProxy的成員變量mRemote指向BinderProxy對象,所以ServiceManagerProxy的addService等方法會交由BinderProxy來處理。
4.BinderProxy的成員變量mObject指向BpBinder對象,因此BinderProxy可以通過BpBinder和Binder驅動發送數據。

感謝
《深入理解Android卷二》
《深入理解Android卷三》
http://gityuan.com/2015/11/21/binder-framework/

最後

千里之行始於足下

Android學習是一條漫長的道路,我們要學習的東西不僅僅只有表面的 技術,還要深入底層,弄明白下面的 原理,只有這樣,我們才能夠提高自己的競爭力,在當今這個競爭激烈的世界裏立足。

我把自己這段時間整理的Android最重要最熱門的學習方向資料放在了我的GitHub:https://github.com/xieyuliang/Android-P7-(點擊藍色字體可以獲取),裏面還有不同方向的自學編程路線、面試題集合/面經、及系列技術文章等。

資源持續更新中,歡迎大家一起學習和探討。

部分資料截圖展示:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章