浅析Binder(五)——ServiceManager代理对象的获取

大家都知道Binder机制主要由ServiceManager,Binder实体对象,Binder代理对象三个组件,顾我们想要在Java世界实现Binder机制也需要事项这个三个组件

Service Manager的Java代理对象的类型为ServiceManagerProxy类型,想要获取这个对象需要先在C++层创建一个句柄值为0的Binder代理对象,然后在Java层创建一个对应的Java服务代理对象。

浅析Binder(五)——ServiceManager代理对象的获取_第1张图片
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 b = ProcessState::self()->getContextObject(NULL);
    return javaObjectForIBinder(env, b);
}

然后我们需要具体解析的javaObjectForIBinder(),看名字就知道他就是将Java对象转换为IBinder对象的关键方法

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

    if (val->checkSubclass(&gBinderOffsets)) {
        // One of our own!
        jobject object = static_cast(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 drl = new DeathRecipientList;
        drl->incStrong((void*)javaObjectForIBinder);
        env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast(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 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系统源代码情景分析》

你可能感兴趣的:(浅析Binder(五)——ServiceManager代理对象的获取)