欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-24 08:24:28
...

参考资料

  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相关接口的类图:

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

现在我们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的呢,先留个疑问。

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

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进程内的。

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

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有关系的类的类图:

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

果然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类图:

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

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

相关标签: Binder Android