Binder机制中Jni

在Service绑定成功后,会调用ServiceConnection的onServiceConnected方法,其中会传入一个IBinder参数。Java层拥有了Proxy便可以与其他进程通讯。这是很奇怪的地方。因为我们知道,Binder是一个misc的驱动,驱动的操作方法都是系统调用。这里很自然的想到,一定会用到Jni。
Client调用Proxy中所有的方法,均通过BinderProxy的transact发起:

public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");

    if (mWarnOnBlocking && ((flags & FLAG_ONEWAY) == 0)) {
        // For now, avoid spamming the log by disabling after we've logged
        // about this interface at least once
        mWarnOnBlocking = false;
        Log.w(Binder.TAG, "Outgoing transactions from this process must be FLAG_ONEWAY",
                new Throwable());
    }

    final boolean tracingEnabled = Binder.isTracingEnabled();
    if (tracingEnabled) {
        final Throwable tr = new Throwable();
        Binder.getTransactionTracker().addTrace(tr);
        StackTraceElement stackTraceElement = tr.getStackTrace()[1];
        Trace.traceBegin(Trace.TRACE_TAG_ALWAYS,
                stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName());
    }
    try {
    //注意这个方法
        return transactNative(code, data, reply, flags);
    } finally {
        if (tracingEnabled) {
            Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
        }
    }
}

真正的trancsat是在android_util_Binder.cpp实现的,java层只是定义了一个接口。

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

我们来看看其实现:

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 = (IBinder*)
        env->GetLongField(obj, gBinderProxyOffsets.mObject);
    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);
    //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;
}

在transact调用完后,系统会在某个时机调用server的onTransact。JavaBBinder继承自本地框架的BBinder,代表Binder Service服务端的实体,而JavaBBinderHolder保存了JavaBBinder指针,Java层的Binder的mObject保存的JavaBBinderHolder指针的值。调用的顺序为,Binder->JavaBBinderHolder->JavaBBinder(例子中的RemoteService)

virtual status_t onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
{
    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()) {
        jthrowable excep = env->ExceptionOccurred();
        report_exception(env, excep,
            "*** Uncaught remote exception!  "
            "(Exceptions are not yet supported across processes.)");
        res = JNI_FALSE;

        /* clean up JNI local ref -- we don't return to Java code */
        env->DeleteLocalRef(excep);
    }

    // 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()) {
        jthrowable excep = env->ExceptionOccurred();
        report_exception(env, excep,
            "*** Uncaught exception in onBinderStrictModePolicyChange");
        /* clean up JNI local ref -- we don't return to Java code */
        env->DeleteLocalRef(excep);
    }

    // Need to always call through the native implementation of
    // SYSPROPS_TRANSACTION.
    if (code == SYSPROPS_TRANSACTION) {
    //调用server中的onTransact方法
        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;
}

以RemotService为例,完成加法之后,要将数据传到client去

@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_add:
{
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
int _result = this.add(_arg0, _arg1);
reply.writeNoException();
//此处回写数据
reply.writeInt(_result);
return true;
}

从上面分析可知其大致流程,client调用c层传输数据后,server处理数据,然后回写数据(当然这其中数据传输依赖于parcel),除去parcel的jni调用,client与server其只有client发生了jni调用,这也就是为什么transact方法是native而onTransact不是natvie的原因。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值