前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >binder是如何在java层和native层实现统一的

binder是如何在java层和native层实现统一的

原创
作者头像
好好学习吧
修改2023-06-04 12:39:23
4280
修改2023-06-04 12:39:23
举报
文章被收录于专栏:今天学习了吗

前言

众所周知,对于binder通信来说,native层通信的基础架构是BpBinder/BBinder,Java层的基础通信架构是BinderProxy/Binder,这两者是如何统一起来的呢?

正文

在binder的跨进程传递数据实现中,数据是包裹在Parcel中的。具体的传递方式,体现在Parcel类的两个方法writeStrongBinder()和readStrongBinder()中,前者的功能是写入Binder对象,后者的功能是读取Binder对象。同样,Parcel在java层和native层各有一套。不过,查看代码可知,java层的Parcel只是native层的封装,两者通过jni建立关联。

代码语言:java
复制
    public final void writeStrongBinder(IBinder val){

        nativeWriteStrongBinder(mNativePtr, val);

    }

    

    public final IBinder readStrongBinder(){

        return nativeReadStrongBinder(mNativePtr);

    }

    

    private static native String nativeReadStrongBinder(long nativePtr);

    private static native void nativeWriteStrongBinder(long natievPtr, IBinder);

jni层代码如下

代码语言:text
复制
  

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

         if (err != NO_ERROR){

             signalExceptionForError(env, clazz, err);

         }

     }

}



static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)

{

    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);

    if (parcel != NULL){

        return javaObjectForIBinder(env, parcel->readStrongBinder());

    }

    return NULL;

}

重点来了,在jni层代码中发现了两个名字起的有点意思的函数ibinderForJavaObject()和javaObjectForIBinder(),正是这两个函数,将java层和native层统一了,代码如下

代码语言:text
复制
    sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj){

        if (obj == NULL) return NULL;

        

        //Instance of Binder?

        if (env->IsInstanceOf(obj, gBinderOffsets.mClass)){

            JavaBBinderHolder* jbh = (JavaBBinderHolder*)env->GetLongField(obj, gBinderOffsets.mObject);

            return jbh->get(env, obj);

        }

        

        //Instance of BinderProxy?

        if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)){

            return getBPNativeData(env, obj)->mObject;

        }

        return NULL;

    }

    

    jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)

    {

        if (val == NULL) return NULL;

        if (val->checkSubclass(&gBinderOffsets)){

            //It's a JavaBBinder created by ibinderForJavaObject

            jobject object = static_cast<JavaBBinder*>(val.get())->object();

            return object;

        }

        

        BinderProxyNativeData* nativeData = new BinderProxyNativeData();

        nativeData->mOrgue = new DeathRecipientList;

        nativeData->mObject = val;

        

        jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mGetInstance, (jlong)nativeData, (jlong)val.get());

        ...

        BinderProxyNativeData* actualNativeData = getBPNativeData(env, object);

        if (actualNativeData == nativeData){

            //Created a new Proxy

            ...

        } else {

            delete nativeData;

        }

        return object;

    }

ibinderForJavaObject()将java binder对象转换成native层binder对象,javaObjectForIBinder()将native binder对象还原成java层binder对象。

总结

android在创建java层Binder对象和BinderProxy对象时,会同时在native层创建对应的JavaBBinderHolder和BinderProxyNativeData。前者包含一个JavaBBinder类型的成员,它继承自BBinder;后者包含BpBinder对象。这样就把java层和native层的连接建立起来了。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 正文
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档