java层Binder——BinderProxy类

java层Binder——BinderProxy类

  BinderProxy类实际上是java层Binder机制中客户端Proxy的mRemote成员变量。在Proxy中,客户端调用服务端IPC业务接口时,首先便会通过proxy中的业务接口去调用mRemote.transact,mRemote自然就是Proxy的成员变量,是一个IBinder类,这个IBinder只是一个Binder功能接口,它实际上就是由BinderProxy向上转型得来的。

一、实例化

  在java层代码中很难找到这个类实例化的地方,那是因为这个类一般都是被放到native层去进行实例化的。这里举一个简单的例子,当我在IMyAidlInterface中增加一个接口,该接口需要传递一个Binder。这样,在IMyAidlInterface服务端接收到客户端传过来的Bidner时,自然会自己实例化一个Proxy,我们由此可以看看它是怎样实例化的。

interface IMyAidlInterface {
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
    void BinderTest(IMyAidlInterface inetrface);
}

  经过编译后,可以看到Stub中关于BinderTest的接口实现如下:

@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
    ……
    case TRANSACTION_BinderTest:
    {
        data.enforceInterface(descriptor);
        com.example.bindertest.IMyAidlInterface _arg0;
        _arg0 = com.example.bindertest.IMyAidlInterface.Stub.asInterface(data.readStrongBinder());
        this.BinderTest(_arg0);
        reply.writeNoException();
        return true;
    }
    ……
}

  是的,在从客户端获取到一个Binder后,他会通过data.readStrongBinder()方法获取到一个Binder客户端。进入到Parcel后,会发现该接口实际只是一个native方法的封装。

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

  由此可以看出,java层中对Binder客户端的实例化,实际上是在native层实现的。在进入native层看代码。

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

  nativeReadStrongBinder方法对应到native层,便是android_os_Parcel_readStrongBinder方法。这个函数中,最终会嗲用javaObjectForIBinder方法来获取一个java层的Binder客户端。

jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
    // N.B. This function is called from a @FastNative JNI method, so don't take locks around
    // calls to Java code or block the calling thread for a long time for any reason.

    if (val == NULL) return NULL;

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

    BinderProxyNativeData* nativeData = new BinderProxyNativeData();
    nativeData->mOrgue = new DeathRecipientList;
    nativeData->mObject = val;

    jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
            gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
    if (env->ExceptionCheck()) {
        // In the exception case, getInstance still took ownership of nativeData.
        return NULL;
    }
    BinderProxyNativeData* actualNativeData = getBPNativeData(env, object);
    if (actualNativeData == nativeData) {
        // Created a new Proxy
        uint32_t numProxies = gNumProxies.fetch_add(1, std::memory_order_relaxed);
        uint32_t numLastWarned = gProxiesWarned.load(std::memory_order_relaxed);
        if (numProxies >= numLastWarned + PROXY_WARN_INTERVAL) {
            // Multiple threads can get here, make sure only one of them gets to
            // update the warn counter.
            if (gProxiesWarned.compare_exchange_strong(numLastWarned,
                        numLastWarned + PROXY_WARN_INTERVAL, std::memory_order_relaxed)) {
                ALOGW("Unexpectedly many live BinderProxies: %d\n", numProxies);
            }
        }
    } else {
        delete nativeData;
    }

    return object;
}

  在这个方法中,实例化java层Binder客户端的关键语句便是:

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

  而gBinderProxyOffsets结构体中,mClass和mGetInstance的赋值是在jni注册过程时完成的,代码如下:

const char* const kBinderProxyPathName = "android/os/BinderProxy";

static int int_register_android_os_BinderProxy(JNIEnv* env)
{
    gErrorOffsets.mError = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/Error"));
    gErrorOffsets.mOutOfMemory =
        MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/OutOfMemoryError"));
    gErrorOffsets.mStackOverflow =
        MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/StackOverflowError"));

    jclass clazz = FindClassOrDie(env, kBinderProxyPathName);
    gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    gBinderProxyOffsets.mGetInstance = GetStaticMethodIDOrDie(env, clazz, "getInstance",
            "(JJ)Landroid/os/BinderProxy;");
    gBinderProxyOffsets.mSendDeathNotice =
            GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
                                   "(Landroid/os/IBinder$DeathRecipient;Landroid/os/IBinder;)V");
    gBinderProxyOffsets.mNativeData = GetFieldIDOrDie(env, clazz, "mNativeData", "J");

    clazz = FindClassOrDie(env, "java/lang/Class");
    gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");

    return RegisterMethodsOrDie(
        env, kBinderProxyPathName,
        gBinderProxyMethods, NELEM(gBinderProxyMethods));
}

  现在已经很明显了,java层的Binder客户端实际上就是BinderProxy。

二、构造和初始化

private static BinderProxy getInstance(long nativeData, long iBinder) {
    BinderProxy result;
    synchronized (sProxyMap) {
        try {
            result = sProxyMap.get(iBinder);
            if (result != null) {
                return result;
            }
            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) {
    mNativeData = nativeData;
}

  BinderProxy的构造函数很简单,首先它时private函数,需要通过getInstance方法来完成实例化,但getInstance也是一个private方法,且在自身类中没有调用该方法的地方。这当然是因为它本身只提供给native层调用,调用过程上面有分析。此外在BinderProxy的构造函数中,还传入了一个nativeData,它是native层的一个BinderProxyNativeData对象指针,在native层需要用到该指针。

三、transact

  BinderProxy的关键函数自然就是transact,java层的Binder客户端就是通过该函数进行Binder通信的。而该函数本质上也是调用的native层接口。函数中的关键语句如下:

public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    ……
    try {
        return transactNative(code, data, reply, flags);
    } finally {
        AppOpsManager.resumeNotedAppOpsCollection(prevCollection);

        if (transactListener != null) {
            transactListener.onTransactEnded(session);
        }

        if (tracingEnabled) {
            Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
        }
    }
    ……

}

  BinderProxy通过调用native层的transactNative方法来进行Binder通信。该方法对应到native的方法名是android_os_BinderProxy_transact。

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
    if (dataObj == NULL) {
        jniThrowNullPointerException(env, NULL);
        return JNI_FALSE;
    }

    Parcel* data = parcelForJavaObject(env, dataObj);
    if (data == NULL) {
        return JNI_FALSE;
    }
    Parcel* reply = parcelForJavaObject(env, replyObj);
    if (reply == NULL && replyObj != NULL) {
        return JNI_FALSE;
    }

    IBinder* target = getBPNativeData(env, obj)->mObject.get(); //获取C++层Bp端Binder(就是C++层的客户端Binder)
    if (target == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
        return JNI_FALSE;
    }

    ALOGV("Java code calling transact on %p in Java object %p with code %" PRId32 "\n",
            target, obj, code);


    bool time_binder_calls;
    int64_t start_millis;
    if (kEnableBinderSample) {
        // Only log the binder call duration for things on the Java-level main thread.
        // But if we don't
        time_binder_calls = should_time_binder_calls();

        if (time_binder_calls) {
            start_millis = uptimeMillis();
        }
    }

    //printf("Transact from Java code to %p sending: ", target); data->print();
    status_t err = target->transact(code, *data, reply, flags);     //通过Bp端Binder进行Binder通信
    //if (reply) printf("Transact from Java code to %p received: ", target); reply->print();

    if (kEnableBinderSample) {
        if (time_binder_calls) {
            conditionally_log_binder_call(start_millis, target, code);
        }
    }

    if (err == NO_ERROR) {
        return JNI_TRUE;
    } else if (err == UNKNOWN_TRANSACTION) {
        return JNI_FALSE;
    }

    signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/, data->dataSize());
    return JNI_FALSE;
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值