(3) Android中Binder调用流程 --- 相关类介绍

6 篇文章 0 订阅
6 篇文章 0 订阅

       在具体讲解Binder调用流程之前,有必要先把调用流程中和数据相关的类介绍下,通过前面两节介绍,我们知道Binder对象分为本地和远程,在远程调用进行数据系列化时对这两种对象处理也是有区别的,下面是Binder调用流程中和数据直接相关的类。

       JAVA端

       BinderProxy:远程服务在本地的代理;

       Binder:实现IBinder接口,实体Service具体实现一般继承这个类,表示具体业务逻辑实现;

       Parcel:android的数据系列化类,直接在内存中操作,在JAVA端其只是个容器,真正实现在本地端;

       对应本地端

       BpBinder:远程服务代理对象,每个服务都会经过Binder驱动生成对应的handle一一对应;

       BBinder:据图服务的实现,其功能之一返回本地IBinder对象,这个对象相关信息会直接传给Binder驱动;

       Parcel:android数据系列化和反系列化本地管理类;

       在分析这些类之前,我们先看下本地IBinder对本地对象和远程对象的接口支持的定义。

       frameworks/native/include/binder/IBinder.h

50class IBinder : public virtual RefBase
......
161    virtual BBinder*        localBinder();   // (1)
162    virtual BpBinder*       remoteBinder(); // (2)
163
164protected:
165    virtual          ~IBinder();
166
167private:
168};

       (1)返回的是一个本地IBinder对象,什么叫本地对象?就是调用的进程就是实现这个IBinder的宿主进程,IBinder实体类就存储在此进程中。

       (2)返回的是一个远程代理对象,就是调用进程和IBinder实体不在同一个进程,其和远程IBinder实体对象是通过对象的handle进行关联的。

       下面一一分析这些类的具体实现细节,这里我们只会讲和Binder调用流程相关,其它读者自行查看源码。

BinderProxy

文件:frameworks/base/core/java/android/os/Binder.java

       查看BinderProxy的源码:

733final class BinderProxy implements IBinder {
......
744    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
.....
763        try {
764            return transactNative(code, data, reply, flags);
765        } finally {
766            if (tracingEnabled) {
767                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
768            }
769        }
770    }

       上面我们只留下关键代码,首先BinderProxy是从IBinder继承过来,所有其具有Binder通行的基础,在其具体实现方法transact里,我们发现其实际调用的是transactNative方法,这是一个本地方法,定义如下:

public native boolean transactNative(int code, Parcel data, Parcel reply,int flags) throws RemoteException;

       这是一个JNI方法,其实现在如下文件中:

      frameworks/base/core/jni/android_util_Binder.cpp

       在这个文件我们发现定义了BinderProxy的本地方法映射:

static const JNINativeMethod gBinderProxyMethods[] = {
1305     /* name, signature, funcPtr */
1306    {"pingBinder",          "()Z", (void*)android_os_BinderProxy_pingBinder},
1307    {"isBinderAlive",       "()Z", (void*)android_os_BinderProxy_isBinderAlive},
1308    {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor},
1309    {"transactNative",      "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
1310    {"linkToDeath",         "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
1311    {"unlinkToDeath",       "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
1312    {"destroy",             "()V", (void*)android_os_BinderProxy_destroy},
1313};

       transactNative方法在本地对应的实现是android_os_BinderProxy_transact,下面看看这个方法具体做了些什么:

1141static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
1142        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
1143{
......
1149    Parcel* data = parcelForJavaObject(env, dataObj);  // (1)
......
1153    Parcel* reply = parcelForJavaObject(env, replyObj); // (2)
......
1158    IBinder* target = (IBinder*)
1159        env->GetLongField(obj, gBinderProxyOffsets.mObject); // (3)
......
1182    status_t err = target->transact(code, *data, reply, flags);
1183    ......
1198    return JNI_FALSE;
1199}

       其中(1)和(2)后面讲Parcel会说,我们来看看(3),这里从BinderProxy直接取出其成员变量mObject的值,它就是一个本地IBinder类型的对象,那么这个本地对象是怎么设置给JAVA层的BinderProxy的呢?从这里我们可以大致推断这个JAVA层的BinderProxy对象有可能是在native层创建的。

       从上面代码发现这里有个结构gBinderProxyOffsets,其定义如下:

96static struct binderproxy_offsets_t
97{
98    // Class state.
99    jclass mClass;
100    jmethodID mConstructor;
101    jmethodID mSendDeathNotice;
102
103    // Object state.
104    jfieldID mObject;
105    jfieldID mSelf;
106    jfieldID mOrgue;
107
108} gBinderProxyOffsets;

       这个结构其实就是保持了JAVA层BinderProxy类成员变量和成员方法的相关信息,其中的mObject保存了本地对象,我们看看这个mObject在那里设置进来的,搜索SetLongField(为什么要搜索这个方法?)方法,发现和mObject相关代码如下:

5jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
596{
......
624    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
625    if (object != NULL) {
......
628        env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
629        val->incStrong((void*)javaObjectForIBinder);
630

       在方法中javaObjectForIBinder创建了BinderProxy对象,并把参数val设置给了BinderProxy的mObject成员变量,继续找javaObjectForIBinder在那里调用:

950static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
951{
952    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
953    return javaObjectForIBinder(env, b);
954}

       这里有一处调用,原来这个IBinder是ProcessState::self()->getContextObject(NULL);创建的,看下这个方法就知道了:

238sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
239{
......
244    handle_entry* e = lookupHandleLocked(handle);
245
246    if (e != NULL) {
......
279            b = new BpBinder(handle);
280            e->binder = b;
......
292    return result;
293}

       经过层层调用发现,最终会调getStrongProxyForHandle这个方法,原来返回的IBinder是由b = new BpBinder(handle);这句代码创建的,到这里我们知道了设置给BinderProxy的mObject成员变量的native对象就是BpBinder,这就对应上了。细心的读者可能发现,这里是对本地的BpBinder做了缓存处理的,通过handle来保存。另外,大家也要注意此方法也在Parcel被调用,可见它是获取远程服务的本地代理的方法入口。

       接着我们看看本地实际的远程代理对象的实现。

       frameworks/native/libs/binder/BpBinder.cpp

307BpBinder* BpBinder::remoteBinder()
308{
309    return this;
310}

   看到了吧,其远程接口 remoteBinder()直接返回BpBinder对象本身,而其本地接口返回的是NULL(IBinder中实现)。

   讲完了BinderProxy,接下来看下Binder和本地的BBinder又是怎么回事?

Binder

文件:frameworks/base/core/java/android/os/Binder.java

       Binder定义如下:

70public class Binder implements IBinder {

       其构造方法如下:

363    public Binder() {
364        init();
......
374    }

       其构造方法里调用了init,init方法是个本地方法,其定义如下:

678    private native final void init();

       和上面一样,在native找到其对应的实现,其定义在如下文件中:

       frameworks/base/core/jni/android_util_Binder.cpp

856static void android_os_Binder_init(JNIEnv* env, jobject obj)
857{
858    JavaBBinderHolder* jbh = new JavaBBinderHolder();
......
865    env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
866}

       和BinderProxy一样的套路,我们发现在native其实就是new一个JavaBBinderHolder对象,并把它设置到Binder的mObject成员变量中,这里就不多说,下面我们看看JavaBBinderHolder实现。

362class JavaBBinderHolder : public RefBase
363{
364public:
365    sp<JavaBBinder> get(JNIEnv* env, jobject obj)
366    {
367        AutoMutex _l(mLock);
368        sp<JavaBBinder> b = mBinder.promote();
369        if (b == NULL) {
370            b = new JavaBBinder(env, obj);  // (1)
371            mBinder = b;
......
384
385private:
386    Mutex           mLock;
387    wp<JavaBBinder> mBinder; // (2)
388};

       最终JavaBBinderHolder 通过其get方法返回JavaBBinder对象,这里先不管JavaBBinderHolder.get在哪儿被调用,先看看JavaBBinder的定义。

265class JavaBBinder : public BBinder
266{
267public:
268    JavaBBinder(JNIEnv* env, jobject object)
269        : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
270    {
271        ALOGV("Creating JavaBBinder %p\n", this);
272        android_atomic_inc(&gNumLocalRefs);
273        incRefsCreated(env);
274    }

       关键来了,原来JavaBBinder就是一个BBinder对象,所以和我们一开始说的一样,从Binder继承的Service在本地其实是一个BBinder,而且这个JavaBBinder还持有实体IBinder的引用(mObject(env->NewGlobalRef(object))),其把实体IBinder对象保存在mObject中,而这个对象就是JAVA层实现的Service。在Binder驱动把业务逻辑转到Service宿主进程的时候最终会执行到JavaBBinder的onTransact方法。

295    virtual status_t onTransact(
296        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
297    {
298        JNIEnv* env = javavm_to_jnienv(mVM);
......
308        jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
309            code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);

       从上面代码我们知道最终会把调用转到JAVA层实现的Service的execTransact方法,这个execTransact就是JAVA层的Binder对象的一个方法,Service重载这个方法从而完成把逻辑转到业务层的调度。

       接下来我们看下BBinder的定义。

       在文件frameworks/native/libs/binder/Binder.cpp中找到localBinder的定义。

199BBinder* BBinder::localBinder()
200{
201    return this;
202}

       这里我们看到了BBinder对本地接口返回是自身对象,远程接口返回的是NULL(在IBinder中实现),到这里就明白了为什么实现Binder的服务就是一个本地对象。

       最后看下Parcel的实现,这里JAVA层的Parcel就不讲了,因为都是一个套路,JAVA层的Parcel只是一个容器,实际实现在本地的Parcel类中。

Parcel

frameworks/native/libs/binder/include/binder/Parcel.h

       这里JAVA层的Parcel接口对应实现在下面文件中。

       frameworks/base/core/jni/android_os_Parcel.cpp

       这里重点看下nativeReadStrongBinder的实现。

451static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
452{
453    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
454    if (parcel != NULL) {
455        return javaObjectForIBinder(env, parcel->readStrongBinder());  // (1)
456    }
457    return NULL;
458}

       这里调用javaObjectForIBinder生成JAVA对象,其实就是BinderProxy,在看javaObjectForIBinder方法之前,先看下parcel->readStrongBinder()这个怎么返回IBinder对象的,经过层层调用最终会进入如下方法:

323status_t unflatten_binder(const sp<ProcessState>& proc,
324    const Parcel& in, wp<IBinder>* out)
325{
326    const flat_binder_object* flat = in.readObject(false);
327
328    if (flat) {
329        switch (flat->type) {
......
342            case BINDER_TYPE_HANDLE:
343            case BINDER_TYPE_WEAK_HANDLE:
344                *out = proc->getWeakProxyForHandle(flat->handle);  // (1)
345                return finish_unflatten_binder(
346                    static_cast<BpBinder*>(out->unsafe_get()), *flat, in);
347        }
348    }
349    return BAD_TYPE;
350}

       这里有个flat_binder_object结构,我们简单说下,这个结构其实就是IBinder对象在Binder驱动层的二进制描述,存储了IBinder的相关信息。我们重点看下代码(1)出的逻辑,这里最终调用还是ProcessSate的getWeakProxyForHandle方法,这个方法上面介绍过,其实就是返回BpBinder对象,而且根据handle做了缓存处理。

       这样我们知道javaObjectForIBinder的第二个参数其实就是BpBinder类型的IBinder对象,这个方法上面也介绍过了,就是生成BinderProxy对象,然后把BpBinder类型的IBinder设置给BinderProxy的成员变量mObject。

       到这里我们把和Binder调用流程相关的几个关键类介绍完了,有了这个基础,后面讲解Binder的调用流程就会轻松多了。

       本系列文章均为原创,主要总结作者多年在软件行业的一些经验,和大家共同学习、进步,转载请注明出处,谢谢!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值