Binder(2)--sayHello之BinderProxy的创建过程.md

参考资料

  1. Android Binder详解 https://mr-cao.gitbooks.io/android/content/android-binder.html
  2. msm-4.14 Code https://github.com/android-linux-stable/msm-4.14/blob/9c4b6ed1b229cfc35e5c3e5815e297b7f519cf93/drivers/android/binder.c

简介

接上文,首先回顾一下IBinder相关接口的类图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dCy5VSok-1605877447072)(res/1_1_DemoInterface类图.png)]

现在我们Client进程已经拿到Server端IDemoInterface中的IBinder对象,但是这个IBinder对象到底是哪个呢,Stub本身?还是Proxy亦或是Proxy中的mRemote?

还是看sayHello的调用过程先:

override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
    Log.d("Client", "DemoService connected")
    // 远程服务连接成功,打个招呼
    // 1.1 这个asInterface是做了什么操作呢?
    val mProxyBinder = IDemoInterface.Stub.asInterface(p1)
    try {
        // 2.1 sayHello!
        mProxyBinder.sayHello(5000, "Hello?")
    } catch (e:RemoteException) {

    }
}

一. asInterface方法

1.1 IDemoInterface.Stub.asInterface

public static com.oneplus.opbench.server.IDemoInterface asInterface(android.os.IBinder obj)
{
    if ((obj==null)) {
        return null;
    }
    // 1.2 生成IInterface
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (((iin!=null)&&(iin instanceof com.oneplus.opbench.server.IDemoInterface))) {
        return ((com.oneplus.opbench.server.IDemoInterface)iin);
    }
    // 1.3 转换成Proxy对象
    return new com.oneplus.opbench.server.IDemoInterface.Stub.Proxy(obj);
}

这个方法是自动生成的,看起来就是通过IBinder生成一个IInterface或者Proxy?

1.2 Binder.queryLocalInterface

public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
    if (mDescriptor != null && mDescriptor.equals(descriptor)) {
        return mOwner;
    }
    return null;
}

public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
    mOwner = owner;
    mDescriptor = descriptor;
}

看类图我们也知道,只有Binder实现了IBinder接口,而也只有IDemoInterface.Stub继承了Binder。这么说起来,SystemServer回传的IBinder对象实际上是服务端的IDemoInterface.Stub?然而mOwner此时还是null的,注意我们现在在Client进程中。这里我们直接debug client进程发现queryLocalInterface返回的null值,而且传入的IBinder的类型居然是BinderProxy的!这里什么时候返回非null,传入的IBinder是什么时候变成BinderProxy的呢,先留个疑问。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1PSFUJ3x-1605877447076)(res/2_1_IBinder类图.png)]

1.3 创建IDemoInterface.Stub.Proxy对象

      private android.os.IBinder mRemote;
      Proxy(android.os.IBinder remote)
      {
        mRemote = remote;
      }

明白了,现在这个mRemote对象实际上是指代的BinderProxy!

二. sayHello

2.1 Proxy.sayHello

      @Override public void sayHello(long aLong, java.lang.String aString) throws android.os.RemoteException
      {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        try {
          // 按顺序写入参数, 注意DESCRIPTOR
          _data.writeInterfaceToken(DESCRIPTOR);
          _data.writeLong(aLong);
          _data.writeString(aString);
          // 2.2 实质上是mRemote起作用的,在1.3中我们通过Debug知道这个其实是BinderProxy对象
          boolean _status = mRemote.transact(Stub.TRANSACTION_sayHello, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            getDefaultImpl().sayHello(aLong, aString);
            return;
          }
          _reply.readException();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
      }

2.2 BinderProxy.transact

    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        // ......
        // 2.3 忽略其他代码,这个是call了一个native方法,通过JNI调用
            return transactNative(code, data, reply, flags);
        // ......
    }

2.3 android_util_Binder.cpp#android_os_BinderProxy_transact

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
    // ......
    // 2.3.1 首先从名字中可以推出是获取远程通信的目标
    IBinder* target = getBPNativeData(env, obj)->mObject.get();
    // ......
    // 2.3.2 继续
    status_t err = target->transact(code, *data, reply, flags);
    // .....
}

2.3.1 android_util_Binder.cpp#getBPNativeData

struct BinderProxyNativeData {
    // Both fields are constant and not null once javaObjectForIBinder returns this as
    // part of a BinderProxy.

    // The native IBinder proxied by this BinderProxy.
    sp<IBinder> mObject;

    // Death recipients for mObject. Reference counted only because DeathRecipients
    // hold a weak reference that can be temporarily promoted.
    sp<DeathRecipientList> mOrgue;  // Death recipients for mObject.
};

static struct binderproxy_offsets_t
{
    // Class state.
    jclass mClass;
    jmethodID mGetInstance;
    jmethodID mSendDeathNotice;

    // Object state.
    jfieldID mNativeData;  // Field holds native pointer to BinderProxyNativeData.
} gBinderProxyOffsets;

BinderProxyNativeData* getBPNativeData(JNIEnv* env, jobject obj) {
    // 其实就是读取BinderProxy对象中保存的long类型的mNativeData数据
    // 然后强制转换成BinderProxyNativeData类型
    return (BinderProxyNativeData *) env->GetLongField(obj, gBinderProxyOffsets.mNativeData);
}

这里并不知道BinderProxy从哪儿来的,Native层也没有定义,应该就是指代java层的BinderProxy。

2.3.2 IBinder#transact

virtual status_t        transact(   uint32_t code,
                                        const Parcel& data,
                                        Parcel* reply,
                                        uint32_t flags = 0) = 0;

这里我们知道getBpNativeData中的mObject是IBinder类型的。但是是一个虚函数,没有具体实现,怎么往下查呢。

Native的Debug方式也有,但是总归不方便,那我们先梳理一下Native层关于IBinder的类图吧。注意现在我们还是在Client进程内的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BdW3W7HO-1605877447077)(res/2_2_NativeIBinder类图.png)]

IBinder相关类之间的关系大致理清楚了,从这个函数名称getBPNativeData可以猜出来应该是指代的BpBinder!

但是怎么确认呢,那我们回到Client App和Server App建立通信的过程中,溯源BinderProxy。

三. BinderProxy的创建过程

3.1 publishServiceLocked

  1. ServerApp: ActivityThread.handleBindService(BindServiceData data)
  2. SystemServer: ActivityManagerService.publishService(IBinder token, Intent intent, IBinder service)
  3. SystemServer: ActiveService.publishServiceLocked(ServiceRecord r, Intent intent, IBinder service)
private void handleBindService(BindServiceData data) {
    // 这个mService就是Service在被调用onCreate方法的时候存入的
    Service s = mServices.get(data.token);
    if (DEBUG_SERVICE)
        Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
    if (s != null) {
        try {
            data.intent.setExtrasClassLoader(s.getClassLoader());
            data.intent.prepareToEnterProcess();
            try {
                if (!data.rebind) {
                    // 3.1.1 所以这个onBind,就是Service中我们实现的onBind方法了
                    // 这里的binder就是对应我们实现的IDemoInterface.Stub
                    IBinder binder = s.onBind(data.intent);
                    // 告诉SystemServer该服务已准备就绪
                    ActivityManager.getService().publishService(
                            data.token, data.intent, binder);
                } else {
                    // 这里就是rebind
                    s.onRebind(data.intent);
                    ActivityManager.getService().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                }
            }
        // ......
    }
}

3.1.1 服务端的Stub初始化

    class DemoBinder:IDemoInterface.Stub() {
        override fun sayHello(aLong: Long, aString: String?) {
            Log.d("DemoService", "$aString:$aLong")
        }
    }

    // 看看这个Stub的初始化过程
    private val binder = DemoBinder()

    override fun onBind(intent: Intent?): IBinder? {
        // 所以Service中的onBind含义就是通知到AMS
        // 本服务已准备继续,随时可以工作
        return binder
    }

还要注意的是,初始化DemoBinder过程,会调用父类的构造函数哦:

    public Stub()
    {
      this.attachInterface(this, DESCRIPTOR);
    }

    public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
        // 噢噢,这个mOwner就是在这里保存的!
        // 它代表的就是IDemoInterface.Stub类的对象,其实就是DemoBinder
        mOwner = owner;
        mDescriptor = descriptor;
    }

但是这里还是没有找到BinderProxy对象的创建。不过我们知道,Binder通信是通过往Parcel中写入数据的;

而AMS.publishService函数中最后一个参数就是IBinder类型的。

3.2 publishService写入参数

通过查看IActivityManager.aidl文件编译后生成的IActivityManager.Stub.Proxy.class(想想为啥不是Stub而是Proxy)文件可以知道这个函数的具体内容:

  public void publishService(IBinder token, Intent intent, IBinder service) throws RemoteException {
    Parcel _data = Parcel.obtain();
    Parcel _reply = Parcel.obtain();
    try {
      _data.writeInterfaceToken("android.app.IActivityManager");
      _data.writeStrongBinder(token);
      if (intent != null) {
        _data.writeInt(1);
        intent.writeToParcel(_data, 0);
      } else {
        _data.writeInt(0);
      }
      // 3.1.3 IBinder对象是通过writeStrongBinder方法写入的
      // 注意这个IBinder就是Service实现的onBind方法中返回的, 就是IDemoInterface.Stub类型
      _data.writeStrongBinder(service);
      boolean _status = this.mRemote.transact(32, _data, _reply, 0);
      if (!_status && IActivityManager.Stub.getDefaultImpl() != null) {
        IActivityManager.Stub.getDefaultImpl().publishService(token, intent, service);
        return;
      } 
      _reply.readException();
    } finally {
      _reply.recycle();
      _data.recycle();
    } 
  }

3.2.1 Parcel.writeStrongBinder

public final void writeStrongBinder(IBinder val) {
    // 这里的mNativePtr就是此Parcel在Native的对应标识
    nativeWriteStrongBinder(mNativePtr, val);
}

看样子直接去了Native层干活去了。

3.2.2 android_os_Parcel#android_os_Parcel_writeStrongBinder

static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
    // 转成Native的Parcel
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if (parcel != NULL) {
        // 3.2.2.1 注意这个ibinderForJavaObject方法,将java层IBinder转成Native层的
        // 3.2.3 然后是保存这个Native的IBinder
        const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
        if (err != NO_ERROR) {
            signalExceptionForError(env, clazz, err);
        }
    }
}
3.2.2.1 android_util_Binder#ibinderForJavaObject
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);
        // 3.2.2.2 返回一个IBinder
        return jbh->get(env, obj);
    }

    // Instance of BinderProxy?
    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
        return getBPNativeData(env, obj)->mObject;
    }

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

这块首次出现了BinderProxy,不过当前我们还处于Service App进程对吧,而且上层传入的IBinder明显只是一个IDemoInterface.Stub类型。

所以这里还是将这个jobject转换成了JavaBBinderHolder!不过我们有理由猜测,BinderProxy是在AMS所处的SystemServer进程中转换的。

3.2.2.2 android_util_Binder#JavaBBinderHolder#get
sp<JavaBBinder> get(JNIEnv* env, jobject obj)
{
    AutoMutex _l(mLock);
    sp<JavaBBinder> b = mBinder.promote();
    if (b == NULL) {
        // 3.2.2.3 创建JavaBBinder
        b = new JavaBBinder(env, obj);
        if (mVintf) {
            ::android::internal::Stability::markVintf(b.get());
        }
        if (mExtension != nullptr) {
            b.get()->setExtension(mExtension);
        }
        mBinder = b;
        ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n",
                b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());
    }
    // 直接返回的JavaBBinder,说明JavaBBinder继承了IBinder
    return b;
}
3.2.2.3 创建Native层的IBinder对象-JavaBBinder
JavaBBinder(JNIEnv* env, jobject /* Java Binder */ object)
        : 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);
}

我们在看看现在Native层和IBinder有关系的类的类图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AAi3r1vT-1605877447080)(res/2_3_IBinder类图_JavaBBinder.png)]

果然JavaBBinder继承了IBinder。回到#3.2.2中,继续往下就是writeStrongBinder了。

3.2.3 Parcel#writeStrongBinder

status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
    return flattenBinder(val);
}

status_t Parcel::flattenBinder(const sp<IBinder>& binder)
{
    flat_binder_object obj;
    // ......
    if (binder != nullptr) {
        // 3.2.3.1 是local还是remote?
        BBinder *local = binder->localBinder();
        if (!local) {
            BpBinder *proxy = binder->remoteBinder();
            if (proxy == nullptr) {
                ALOGE("null proxy");
            }
            const int32_t handle = proxy ? proxy->handle() : 0;
            obj.hdr.type = BINDER_TYPE_HANDLE;
            obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
            obj.handle = handle;
            obj.cookie = 0;
        } else {
            // 进入!
            if (local->isRequestingSid()) {
                obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
            }
            // 注意这里的type,是BINDER_TYPE_BINDER!
            obj.hdr.type = BINDER_TYPE_BINDER;
            // 保存BBinder的弱引用,这个是干啥用的?
            obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
            // 保存BBinder对象
            obj.cookie = reinterpret_cast<uintptr_t>(local);
        }
    } else {
        obj.hdr.type = BINDER_TYPE_BINDER;
        obj.binder = 0;
        obj.cookie = 0;
    }

    // 3.2.4 完成IBinder的写入
    return finishFlattenBinder(binder, obj);
}

这里对local和remote存在不同的处理方式,不过我们先仅仅关注其中一个分支。

3.2.3.1 IBinder#localBinder

我们这里的IBinder就是JavaBBinder类的对象,前面我们看过了JavaBBinder的初始化

BBinder* IBinder::localBinder()
{
    return nullptr;
}

// 注意IBinder调用的是这个
BBinder* BBinder::localBinder()
{
    return this;
}

因为这里的IBinder指针是指向其子类的子类JavaBBinder,然后其子类BBinder实现了虚函数localBinder,而JavaBBinder并没有。

所以这里是local的!

3.2.4 Parcel#finishFlattenBinder

flatten的意思是压平,其实可以理解为打包,将JavaBBinder打包然后发送出去。

status_t Parcel::finishFlattenBinder(
    const sp<IBinder>& binder, const flat_binder_object& flat)
{
    // 写入内存区域,这一块没有接触过,暂时先不管,后面研究
    // 理解为将IBinder保存到内存中的某个特定区域
    status_t status = writeObject(flat, false);
    if (status != OK) return status;

    internal::Stability::tryMarkCompilationUnit(binder.get());
    return writeInt32(internal::Stability::get(binder.get()));
}

到这里我们知道了Java层的IBinder对象是如何通过Parcel保存到Native中的。

3.3 SystemServer接收参数

这里我们先不去细究通信的过程,因为这本身就是一次Binder通信。先看AMS收到Server App发布Service的IBinder对象是什么。

还是通过看编译后生成的IActivityManager.Stub.Class文件中对应的publishService方法,注意我们现在切换到了SystemServer进程(忽略进程切换过程)。

    public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        // ......
        data.enforceInterface(descriptor);
        // 读取IBinder对象,不过这个是token, 不是我们想要的Service的IBinder
        // 用过Binder通信知道,是按顺序来读写的,所以我们看最后一个IBinder
        iBinder11 = data.readStrongBinder();
        if (0 != data.readInt()) {
          intent6 = (Intent)Intent.CREATOR.createFromParcel(data);
        } else {
          intent6 = null;
        } 
        // 3.3.1 这里就是我们想要的Service的IBinder了
        iBinder26 = data.readStrongBinder();
        publishService(iBinder11, intent6, iBinder26);
        reply.writeNoException();
        return true;
        // ......
    }

3.3.1 Parcel.readStrongBinder

public final IBinder readStrongBinder() {
    return nativeReadStrongBinder(mNativePtr);
}

还是直接切到Native.

3.3.2 android_os_Parcel#android_os_Parcel_readStrongBinder

static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if (parcel != NULL) {
        // 3.3.2.1 先看Parce->readStrongBinder
        // 3.3.3  将IBinder转换成jobject
        return javaObjectForIBinder(env, parcel->readStrongBinder());
    }
    return NULL;
}
3.3.2.1 Parcel#readStrongBinder
sp<IBinder> Parcel::readStrongBinder() const
{
    sp<IBinder> val;
    // 暂时不明确IBinder指代的是具体哪个子类吼
    readNullableStrongBinder(&val);
    return val;
}

status_t Parcel::readStrongBinder(sp<IBinder>* val) const
{
    status_t status = readNullableStrongBinder(val);
    if (status == OK && !val->get()) {
        status = UNEXPECTED_NULL;
    }
    return status;
}

status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const
{
    // 来了,解压的过程
    return unflattenBinder(val);
}
3.3.2.2 Parcel#unflattenBinder
status_t Parcel::unflattenBinder(sp<IBinder>* out) const
{
    // 从内存区域中读取当前位置的数据
    const flat_binder_object* flat = readObject(false);
    // 存在
    if (flat) {
        switch (flat->hdr.type) {
            // 我们在flatten中的Type就是这个!
            case BINDER_TYPE_BINDER: {
                // 转成IBinder,没有问题,我们存入的JavaBBinder,其父类的父类就是IBinder
                sp<IBinder> binder = reinterpret_cast<IBinder*>(flat->cookie);
                // 3.3.2.3 完成数据解压
                return finishUnflattenBinder(binder, out);
            }
            case BINDER_TYPE_HANDLE: {
                sp<IBinder> binder =
                    ProcessState::self()->getStrongProxyForHandle(flat->handle);
                return finishUnflattenBinder(binder, out);
            }
        }
    }
    return BAD_TYPE;
}

这个地方留个心眼哦,这里的flat->hdr.type真的还是原来的BINDER_TYPE_BINDER吗?

3.3.2.3 Parcel#finishUnflattenBinder
status_t Parcel::finishUnflattenBinder(
    const sp<IBinder>& binder, sp<IBinder>* out) const
{
    int32_t stability;
    status_t status = readInt32(&stability);
    if (status != OK) return status;

    status = internal::Stability::set(binder.get(), stability, true /*log*/);
    if (status != OK) return status;

    // out指向这个内存区域
    *out = binder;
    return OK;
}

所以这个IBinder到底是什么类型的呢?先回到#3.3.2中,继续readStrongBinder的过程

3.3.3 android_util_Binder#javaObjectForIBinder

jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
    // ......
    // 3.3.3.1 这里决定是不是直接返回JavaBBinder的类型
    if (val->checkSubclass(&gBinderOffsets)) {
        // It's a JavaBBinder created by ibinderForJavaObject. Already has Java object.
        jobject object = static_cast<JavaBBinder*>(val.get())->object();
        LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
        return object;
    }

    // 3.3.4 终于看到和BinderProxy相关的了, 至少名字上看都有关系
    BinderProxyNativeData* nativeData = new BinderProxyNativeData();
    nativeData->mOrgue = new DeathRecipientList;
    // 将从内存中读取的IBinder对象存起来
    nativeData->mObject = val;

    // 3.3.5 调用到java方法mGetInstance,生成BinderProxy!
    jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
            gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
    // ......
    // 所以这里最终返回是BinderProxy对象对应JNI的jobject.
    return object;
}
3.3.3.1 IBinder#checkSubclass
bool IBinder::checkSubclass(const void* /*subclassID*/) const
{
    return false;
}

// JavaBBinder:
bool    checkSubclass(const void* subclassID) const
{
    // 3.3.3.2 gBinderOffsets的初始化
    return subclassID == &gBinderOffsets;
}

这里思考一个问题,注意我们现在已经处于SystemServer进程了,这里的IBinder指向一块内存区域,是从Server App中拷贝而来的,与JavaBBinder数据保持一致。

那我们强制转换转成了IBinder,然后调用IBinder中的函数是调用IBinder中函数实现还是JavaBBinder中的函数实现呢?

3.3.3.2 android_util_Binder#int_register_android_os_Binder

首先gBinderOffsets是bindernative_offsets_t类型的结构体,其在int_register_android_os_Binder中被填充数据。

static int int_register_android_os_Binder(JNIEnv* env)
{
    jclass clazz = FindClassOrDie(env, kBinderPathName);

    gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");
    gBinderOffsets.mGetInterfaceDescriptor = GetMethodIDOrDie(env, clazz, "getInterfaceDescriptor",
        "()Ljava/lang/String;");
    gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");

    return RegisterMethodsOrDie(
        env, kBinderPathName,
        gBinderMethods, NELEM(gBinderMethods));
}

我们知道,在Java中,每个进程都有自己的虚拟机环境,所以对于不同进程来说,JNIEnv肯定也是不同的,这就导致gBinderOffsets也是不同的。

所以对于3.3.3.1中checkSubclass来说,返回的就是false了。

3.3.4 创建BinderProxyNativeData

struct BinderProxyNativeData {
    // Both fields are constant and not null once javaObjectForIBinder returns this as
    // part of a BinderProxy.

    // The native IBinder proxied by this BinderProxy.
    sp<IBinder> mObject;

    // Death recipients for mObject. Reference counted only because DeathRecipients
    // hold a weak reference that can be temporarily promoted.
    sp<DeathRecipientList> mOrgue;  // Death recipients for mObject.
};

哦噢,空欢喜?这里只是一个结构体,将IBinder和DeathRecipientList组合起来。

3.3.5 gBinderProxyOffsets.mGetInstance => BinderProxy.getInstance

private static BinderProxy getInstance(long nativeData, long iBinder) {
    BinderProxy result;
    synchronized (sProxyMap) {
        try {
            result = sProxyMap.get(iBinder);
            if (result != null) {
                return result;
            }
            // 创建BinderProxy对象!
            result = new BinderProxy(nativeData);
        } catch (Throwable e) {
            // We're throwing an exception (probably OOME); don't drop nativeData.
            NativeAllocationRegistry.applyFreeFunction(NoImagePreloadHolder.sNativeFinalizer,
                    nativeData);
            throw e;
        }
        NoImagePreloadHolder.sRegistry.registerNativeAllocation(result, nativeData);
        // The registry now owns nativeData, even if registration threw an exception.
        sProxyMap.set(iBinder, result);
    }
    return result;
}

private BinderProxy(long nativeData) {
    // 所以这个nativeData原来是代表的BinderProxyNativeData
    mNativeData = nativeData;
}

通过JNI调用到Java方法,最终生成BinderProxy对象。

四. 总结

到这里我们就理清了BinderProxy这个是怎么来的了。总结一下:

  1. Server App实现Service的onBind方法,返回一个IBinder对象,这个IBinder对象是继承了某个aidl接口的Stub类,记为StubIBinder
  2. Server App调用publishService,将StubIBinder通过一系列方法,在Native层转成JavaBBinder,保存在Parce的内存区域中
  3. Binder驱动拷贝Parcel并将其传给SystemServer进程(这个过程我们稍后分析)
  4. SystemServer接收到Parcel内存数据,将其中JavaBBinder所在的内存区域强制转成IBinder类型,并将其保存为Java层的BinderProxy对象

同理我们知道Client App通过调用bindService获取了一个IBinder对象,那这个IBinder对象也是BinderProxy类型的, 只不过这里有点点小差异:

SystemServer通过IServiceConnection向Client App发送Server App注册的BinderProxy对象时,在Parcel.writeStrongBinder过程中,存入cookie的是BinderProxy:

sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
    if (obj == NULL) return NULL;

    // 是否为Binder对象
    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
        JavaBBinderHolder* jbh = (JavaBBinderHolder*)
            env->GetLongField(obj, gBinderOffsets.mObject);
        return jbh->get(env, obj);
    }

    // 是否为BinderProxy对象
    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
        // SystemServer向Client App发送Server App的BinderProxy对象,走这里
        return getBPNativeData(env, obj)->mObject;
    }

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

那么在接下来打包flattenBinder的过程中, type 的类型其实是 BINDER_TYPE_HANDLE

status_t Parcel::flattenBinder(const sp<IBinder>& binder)
    // ......
        // 注意此时我们身处SystemServer进程,传入的IBinder实际上是对应BinderProxy
        BBinder *local = binder->localBinder();
        if (!local) {
            BpBinder *proxy = binder->remoteBinder();
            if (proxy == nullptr) {
                ALOGE("null proxy");
            }
            const int32_t handle = proxy ? proxy->handle() : 0;
            obj.hdr.type = BINDER_TYPE_HANDLE;
            obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
            obj.handle = handle;
            obj.cookie = 0;
        } else {
            if (local->isRequestingSid()) {
                obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
            }
            obj.hdr.type = BINDER_TYPE_BINDER;
            obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
            obj.cookie = reinterpret_cast<uintptr_t>(local);
        }
    // ......
}

4.1 新的疑问

哦吼,新的问题来了,这个binder->localBinder()调用的到底是那个方法呢?IBinder, BBinder中都有实现。

如果是直接拷贝的话,那么按理说也是会调用到BBinder的localBinder,这样这里还是个local!

如果拷贝后在新进程中调用的是IBinder的localBinder,那么接下来的remoteBinder也是IBinder的,还是返回null!

这样也说不通,因为如果remoteBinder返回的也是空,那么打包后传入的信息就不能识别Server App的IDemoInterface了。

这里曾困扰我一段时间,这个IBinder到底是什么是我们理解Binder通信的基础。

按照网上一大堆的文章来说,从Binder通信到了另一个进程,那么BBinder就会转成了BpBinder。

然而我们梳理了上层代码,并没有发现这个转变过程。在Parcel整个压缩和解包的过程中都没有发现将IBinder强制转成BpBinder。

4.2 binder驱动

其实这里是在驱动层做的处理:android/kernel/msm-4.19/drivers/android/binder.c

static void binder_transaction(struct binder_proc *proc,
			       struct binder_thread *thread,
			       struct binder_transaction_data *tr, int reply,
			       binder_size_t extra_buffers_size)
{
    // ......
    for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
            buffer_offset += sizeof(binder_size_t)) {
        // ......
        switch (hdr->type) {
            case BINDER_TYPE_BINDER:
            case BINDER_TYPE_WEAK_BINDER: {
                struct flat_binder_object *fp;

                fp = to_flat_binder_object(hdr);
                ret = binder_translate_binder(fp, t, thread);
                // ......
        }
    // ......
}

static int binder_translate_binder(struct flat_binder_object *fp,
				   struct binder_transaction *t,
				   struct binder_thread *thread)
{
    // ......
    if (fp->hdr.type == BINDER_TYPE_BINDER)
        // 这里,如果读取的hdr.type是BINDER_TYPE_BINDER
        // 将会被改成BINDER_TYPE_HANDLE!!!
        fp->hdr.type = BINDER_TYPE_HANDLE;
    else
        fp->hdr.type = BINDER_TYPE_WEAK_HANDLE;
    // ......
}

在驱动层传输数据的时候会加工一次!怪不得上层找不到任何信息,这个可真的是太容易误导了。

4.3 SystemServer => Parcel#unflattenBinder

所以在 #3.3.2.2 中 Parcel#unflattenBinder 解包数据时,对IBinder对象的处理是另外一条路径了:

status_t Parcel::unflattenBinder(sp<IBinder>* out) const
{
    // 从内存区域中读取当前位置的数据
    const flat_binder_object* flat = readObject(false);
    // 存在
    if (flat) {
        switch (flat->hdr.type) {
            case BINDER_TYPE_BINDER: {
                sp<IBinder> binder = reinterpret_cast<IBinder*>(flat->cookie);
                return finishUnflattenBinder(binder, out);
            }
            case BINDER_TYPE_HANDLE: {
                // 注意此时收到的数据是经过Binder驱动加工过的,我们现在是在SystemServer进程
                // 所以这个hdr.type从BINDER_TYPE_BINDER转成了BINDER_TYPE_HANDLE!
                // 这里解包,注意flat_binder_object这个结构体,他里面的binder和handle是被组合成union结构的!
                // 所以封包的时候写存入的binder就是此时读取的handle,这也代表了Server App中对应的BBinder
                sp<IBinder> binder =
                    ProcessState::self()->getStrongProxyForHandle(flat->handle);
                // 这里我们在回到#3.3.2中android_os_Parcel#android_os_Parcel_readStrongBinder
                // 就可以知道,其实SystemServer自始至终都是保存了来自Server App的BBinder相同数据但是转成了BpBinder的IBinder对象
                return finishUnflattenBinder(binder, out);
            }
        }
    }
    return BAD_TYPE;
}

这里有个疑问吼,我们看这个flat_binder_object结构的内容:

typedef __u32 binder_size_t;

struct flat_binder_object {
	struct binder_object_header	hdr;
	__u32				flags;

	/* 8 bytes of data. */
	union {
		binder_uintptr_t	binder;	/* local object */
		__u32			handle;	/* remote object */
	};

	/* extra data associated with local object */
	binder_uintptr_t	cookie;
};

这个handle是一个__u32类型的数据,说明该变量占4字节。

4.3.1 ProcessState#getStrongProxyForHandle(int32_t handle)

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;
    AutoMutex _l(mLock);
    // 4.3.2 从mHandleToObject中获取handle对应的handle_entry
    handle_entry* e = lookupHandleLocked(handle);
    if (e != nullptr) {
        IBinder* b = e->binder;
        // 第一次当然是null的
        if (b == nullptr || !e->refs->attemptIncWeak(this)) {
            if (handle == 0) {
                Parcel data;
                status_t status = IPCThreadState::self()->transact(
                        0, IBinder::PING_TRANSACTION, data, nullptr, 0);
                if (status == DEAD_OBJECT)
                   return nullptr;
            }
            // 4.3.3 创建BpBinder!!!
            b = BpBinder::create(handle);
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    // 这个result就是新创建的BpBinder,或者之前创建缓存的BpBinder
    return result;
}

4.3.2 ProcessState#lookupHandleLocked

ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
{
    // mHandleToObject 是Vector类型的数据集合
    const size_t N=mHandleToObject.size();
    if (N <= (size_t)handle) {
        handle_entry e;
        e.binder = nullptr;
        e.refs = nullptr;
        status_t err = mHandleToObject.insertAt(e, N, handle+1-N);
        if (err < NO_ERROR) return nullptr;
    }
    return &mHandleToObject.editItemAt(handle);
}

这里传入的handle其实是Server App在打包数据时,获取的:obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs()), 然后经过驱动加工,可以视为BBinder的映射BpBinder的Token. 这里的细节我们后面分析。

一般来说每个BBinder都不一样(为什么呢,涉及到binder驱动以及Android的智能指针),所以,这里的mHandleToObject是缓存IBinder对象,防止频繁创建销毁消耗资源。

4.3.3 创建BpBinder

BpBinder* BpBinder::create(int32_t handle) {
    int32_t trackedUid = -1;
    // sCountByUidEnabled默认是false的,SystemServer进程是再开机过程中打开的
    if (sCountByUidEnabled) {
        // 获取Server App的UID
        trackedUid = IPCThreadState::self()->getCallingUid();
        // 接下来是判断Server App是否存在过多的binder proxy对象
        // 默认2500个, 对于SystemServer进程是6000个(也是开机过程中设置的nSetBinderProxyCountWatermarks)
        AutoMutex _l(sTrackingLock);
        uint32_t trackedValue = sTrackingMap[trackedUid];
        if (CC_UNLIKELY(trackedValue & LIMIT_REACHED_MASK)) {
            if (sBinderProxyThrottleCreate) {
                return nullptr;
            }
        } else {
            if ((trackedValue & COUNTING_VALUE_MASK) >= sBinderProxyCountHighWatermark) {
                ALOGE("Too many binder proxy objects sent to uid %d from uid %d (%d proxies held)",
                      getuid(), trackedUid, trackedValue);
                sTrackingMap[trackedUid] |= LIMIT_REACHED_MASK;
                if (sLimitCallback) sLimitCallback(trackedUid);
                if (sBinderProxyThrottleCreate) {
                    ALOGI("Throttling binder proxy creates from uid %d in uid %d until binder proxy"
                          " count drops below %d",
                          trackedUid, getuid(), sBinderProxyCountLowWatermark);
                    return nullptr;
                }
            }
        }
        // 该UID创建了新的BpBinder
        sTrackingMap[trackedUid]++;
    }
    return new BpBinder(handle, trackedUid);
}

BpBinder::BpBinder(int32_t handle, int32_t trackedUid)
    : mHandle(handle)
    , mStability(0)
    , mAlive(1)
    , mObitsSent(0)
    , mObituaries(nullptr)
    , mTrackedUid(trackedUid)
{
    ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);

    extendObjectLifetime(OBJECT_LIFETIME_WEAK);
    // 给此BpBinder新增一个弱引用
    IPCThreadState::self()->incWeakHandle(handle, this);
}

最后补上一张IBinder类图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vPiBr7AF-1605877447082)(res/2_4_IBinder全类图.png)]

了解了IBinder转换过程的原理,BinderProxy的生成过程,也知道了BBinder和BpBinder的映射关系,接下来就是在Client App和Server App之间的通信了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值