java层Binder——Binder类

java层Binder——Binder类

  Binder类是服务端Stub的父类,其主要作用也是为服务端提供Binder通信的支持。在Stub类中的onTransact方法,适用于Binder通信的,在客户端调用服务端IPC接口时,最终会调用到Stub的onTransact方法,该方法再去调用业务接口。但是由谁来调用onTransact方法的呢,答案就在Binder类里。

一、构造与初始化

public Binder(@Nullable String descriptor)  {
    mObject = getNativeBBinderHolder();
    NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mObject);

    if (FIND_POTENTIAL_LEAKS) {
        final Class<? extends Binder> klass = getClass();
        if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                (klass.getModifiers() & Modifier.STATIC) == 0) {
            Log.w(TAG, "The following Binder class should be static or leaks might occur: " +
                klass.getCanonicalName());
        }
    }
    mDescriptor = descriptor;
}

  构造时,会往里面传入一个descriptor用于表示该Binder的描述。getNativeBBinderHolder方法用于实例化native层中的一个C++类JavaBBinderHolder,返回该实例化对象的指针。

二、execTransact

  execTransact函数便是调用Stub的onTransact方法的地方。

private boolean execTransact(int code, long dataObj, long replyObj,
        int flags) {
    // At that point, the parcel request headers haven't been parsed so we do not know what
    // WorkSource the caller has set. Use calling uid as the default.
    final int callingUid = Binder.getCallingUid();
    final long origWorkSource = ThreadLocalWorkSource.setUid(callingUid);
    try {
        return execTransactInternal(code, dataObj, replyObj, flags, callingUid);
    } finally {
        ThreadLocalWorkSource.restore(origWorkSource);
    }
}

private boolean execTransactInternal(int code, long dataObj, long replyObj, int flags,
        int callingUid) {

        ……

        if ((flags & FLAG_COLLECT_NOTED_APP_OPS) != 0) {
            AppOpsManager.startNotedAppOpsCollection(callingUid);
            try {
                res = onTransact(code, data, reply, flags);
            } finally {
                AppOpsManager.finishNotedAppOpsCollection();
            }
        } else {
            res = onTransact(code, data, reply, flags);
        }
   
        ……
}

  execTransact会调用execTransactInternal,再由execTransactInternal调用onTransact。我们会发现无论是execTransact还是execTransactInternal,都是private函数,且没有任何地方调用execTransact,这是因为execTransact方法是在native层被调用的,它由native层中一个叫做JavaBBinder的C++对象调用。

status_t onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) override
{
    JNIEnv* env = javavm_to_jnienv(mVM);

    ALOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM);

    IPCThreadState* thread_state = IPCThreadState::self();
    const int32_t strict_policy_before = thread_state->getStrictModePolicy();

    //printf("Transact from %p to Java code sending: ", this);
    //data.print();
    //printf("\n");
    jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
        code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);

    if (env->ExceptionCheck()) {
        ScopedLocalRef<jthrowable> excep(env, env->ExceptionOccurred());
        report_exception(env, excep.get(),
            "*** Uncaught remote exception!  "
            "(Exceptions are not yet supported across processes.)");
        res = JNI_FALSE;
    }

    // Check if the strict mode state changed while processing the
    // call.  The Binder state will be restored by the underlying
    // Binder system in IPCThreadState, however we need to take care
    // of the parallel Java state as well.
    if (thread_state->getStrictModePolicy() != strict_policy_before) {
        set_dalvik_blockguard_policy(env, strict_policy_before);
    }

    if (env->ExceptionCheck()) {
        ScopedLocalRef<jthrowable> excep(env, env->ExceptionOccurred());
        report_exception(env, excep.get(),
            "*** Uncaught exception in onBinderStrictModePolicyChange");
    }

    // Need to always call through the native implementation of
    // SYSPROPS_TRANSACTION.
    if (code == SYSPROPS_TRANSACTION) {
        BBinder::onTransact(code, data, reply, flags);
    }

    //aout << "onTransact to Java code; result=" << res << endl
    //    << "Transact from " << this << " to Java code returning "
    //    << reply << ": " << *reply << endl;
    return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
}

  java层的execTransact会由native层的JavaBBinder对象的onTransact方法调用,该方法中调用java层方法的语句是:

jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
    code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);

  gBinderOffsets结构体是在jni注册方法时赋值的:

const char* const kBinderPathName = "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));
}

  那么JavaBBinder对象的onTransact方法又是由谁调用的呢?这就需要看JavaBBinder对象的父类了。JavaBBinder继承于BBinder,而一般C++层的Bn端Binder也继承于BBinder,没错,Bn端Binder的Binder通信相关功能就是由BBinder提供的,所以JavaBBinder本身就可以看作时C++层的一个服务端Binder,在功能上它等同于Bn端Binder。onTransact本身是在BBinder中被调用的,具体怎么调用,可以放在分析C++层Binder时去看。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值