淺析Binder(五)——ServiceManager代理對象的獲取

大家都知道Binder機制主要由ServiceManager,Binder實體對象,Binder代理對象三個組件,顧我們想要在Java世界實現Binder機制也需要事項這個三個組件

Service Manager的Java代理對象的類型為ServiceManagerProxy類型,想要獲取這個對象需要先在C++層創建一個句柄值為0的Binder代理對象,然后在Java層創建一個對應的Java服務代理對象。

ServiceManager的java代理對象類圖.jpeg

最終是ServiceManager類獲取到ServiceManagerProxy對象,并保存在了sServiceManager成員變量中,通過這個變量我們又可以得到getService(),listService(),checkService(),addService()等操作Java服務的方法。

//framworks/base/core/java/android/os/ServiceManager.java
 private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }
//framworks/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);
    }

然后大家會問?Java服務代理對象是從哪里獲取的呢?
看到那個黃色的小框了沒有,Java服務對象就是通過JNI方法獲取的
getContextObject()方法是JNI方法,JNI教程參考,它由android_os_BinderInternal_getContextObject來實現

//framworks/base/core/jni/android_util_Binder.cpp
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    return javaObjectForIBinder(env, b);
}

然后我們需要具體解析的javaObjectForIBinder(),看名字就知道他就是將Java對象轉換為IBinder對象的關鍵方法

jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
    if (val == NULL) return NULL;

    if (val->checkSubclass(&gBinderOffsets)) {
        // One of our own!
        jobject object = static_cast<JavaBBinder*>(val.get())->object();
        LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
        return object;
    }

    // For the rest of the function we will hold this lock, to serialize
    // looking/creation of Java proxies for native Binder proxies.
    AutoMutex _l(mProxyLock);

    // Someone else's...  do we know about it?
    jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
    if (object != NULL) {
        jobject res = jniGetReferent(env, object);
        if (res != NULL) {
            ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res);
            return res;
        }
        LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());
        android_atomic_dec(&gNumProxyRefs);
        val->detachObject(&gBinderProxyOffsets);
        env->DeleteGlobalRef(object);
    }

    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
    if (object != NULL) {
        LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object);
        // The proxy holds a reference to the native object.
        env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
        val->incStrong((void*)javaObjectForIBinder);

        // The native object needs to hold a weak reference back to the
        // proxy, so we can retrieve the same proxy if it is still active.
        jobject refObject = env->NewGlobalRef(
                env->GetObjectField(object, gBinderProxyOffsets.mSelf));
        val->attachObject(&gBinderProxyOffsets, refObject,
                jnienv_to_javavm(env), proxy_cleanup);

        // Also remember the death recipients registered on this proxy
        sp<DeathRecipientList> drl = new DeathRecipientList;
        drl->incStrong((void*)javaObjectForIBinder);
        env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));

        // Note that a new object reference has been created.
        android_atomic_inc(&gNumProxyRefs);
        incRefsCreated(env);
    }

    return object;
}

參數val要么指向一個Binder代理對象,要么指向一個Binder本地對象。當它指向一個Binder本地對象時,他的類型為JavaBBinder,后者繼承BBinder類。

frameworks/base/libs/binder/Binder.cpp
bool IBinder::checkSubclass(const void* /*subclassID*/) const
{
    return false;
}

大家看到checkSubclass是用來檢測val指向Binder代理對象,還是JavaBBinder對象,默認值返回false。但是JavaBBinder類重寫了其父類BBinder的父類IBinder的成員函數checkSubclass(),所以只要subclassID指向全局變量gBinderOffsets就返回true

  1. val指向的是一個JavaBBinder對象的時候就返回true,并通過成員方法object()獲取Java對象,mobject指向Java層中的一個Binder對象。
//framworks/base/core/jni/android_util_Binder.cpp
class JavaBBinder : public BBinder
{
public:
    JavaBBinder(JNIEnv* env, jobject object)
        : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
    {
        ALOGV("Creating JavaBBinder %p\n", this);
        android_atomic_inc(&gNumLocalRefs);
        incRefsCreated(env);
    }

    bool    checkSubclass(const void* subclassID) const
    {
        return subclassID == &gBinderOffsets;
    }

    jobject object() const
    {
        return mObject;
    }
    ......
    private:
      jobject const mObject;
}
  1. 當val指向的是一個句柄值等于0的Binder代理對象的時候,它最終返回的是一個java層的服務代理對象,即BinderProxy對象
jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
    if (object != NULL) {
        jobject res = jniGetReferent(env, object);
        if (res != NULL) {
            ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res);
            return res;
        }
        LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());
        android_atomic_dec(&gNumProxyRefs);
        val->detachObject(&gBinderProxyOffsets);
        env->DeleteGlobalRef(object);
    }

這段代碼的功能主要是檢查當前進程是否已經創建BinderProxy對象。如果是,則返回指向該BinderProxy對象的WeakRefenrence對象object。但是object指向的BinderProxy可能已經失效,因此需要繼續檢查,并將其升級為強引用對象。若object升級成功則返回BinderProxy對象,如果升級失敗則解除它與無效的BinderProxy對象的對應關系。

如何將Binder代理對象外部對象關聯?
例:函數javaObjectForBinder在為一個Binder代理對象(BpBinder)創建一個Java服務對象(BinderProxy)時,就會將創建出來的Java服務代理對象(BinderProxy)保存在Binder代理對象(BpBinder)的成員變量mObjects中。但是一個Binder代理對象(BpBinder)不僅僅是關聯一個外部對象,所以需要為每一個外部對象設置一個參數,而Java服務代理對象(BinderPorxy)所使用的參數就是gBinderProxyOffsets的地址。

ObjectManager 是定義在BpBinder內部的一個類。定義了外部對象操作函數attach(增),find(查),detach(刪)kill函數用來清理與Binder代理對象管理的外部對象。

  class ObjectManager
    {
    public:
                    ObjectManager();
                    ~ObjectManager();

        void        attach( const void* objectID,
                            void* object,
                            void* cleanupCookie,
                            IBinder::object_cleanup_func func);
        void*       find(const void* objectID) const;
        void        detach(const void* objectID);

        void        kill();

    private:
                    ObjectManager(const ObjectManager&);
        ObjectManager& operator=(const ObjectManager&);

        struct entry_t
        {
            void* object; // 指向外部對象的一個弱引用對象
            void* cleanupCookie; //fun所指向的清理函數的一個調用參數
            IBinder::object_cleanup_func func; // 函數指針,用來清理Object指向的外部對象
        };

        //維護與一個Binder代理對象所關聯的外部對象,這些外部對象都使用entry_t結構體來描述
        KeyedVector<const void*, entry_t> mObjects; 
    

相應的Binder代理對象也提供了三個成員函數,attchObject,findObject,detachObject用來增查刪與它關聯的外部對象,具體實現是調用內部類的成員變量mObjects的成員函數attach,find,detach實現。

void BpBinder::attachObject(
    const void* objectID, void* object, void* cleanupCookie,
    object_cleanup_func func)
{
    AutoMutex _l(mLock);
    ALOGV("Attaching object %p to binder %p (manager=%p)", object, this, &mObjects);
    mObjects.attach(objectID, object, cleanupCookie, func);
}

void* BpBinder::findObject(const void* objectID) const
{
    AutoMutex _l(mLock);
    return mObjects.find(objectID);
}

void BpBinder::detachObject(const void* objectID)
{
    AutoMutex _l(mLock);
    mObjects.detach(objectID);
}

參考:
《Android系統源代碼情景分析》

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容