什么是Parcel.enforceInterface?

use*_*764 7 android parcel parcelable

谁能告诉我Android的Parcel类中的enforceInterface方法有什么用呢?开发者网站没有解释其目的,谷歌也没有返回任何有用的点击.

谢谢.

dre*_*ale 2

该方法在处理RPC调用时会检查客户端和服务器端的接口是否相同。

详细流程:

  1. 客户端调用服务器远程方法,在调用之前,会先调用mRemote.transact该方法。_data.writeInterfaceToken(DESCRIPTOR);
  2. 服务器端onTransact会被调用,然后调用检查data.enforceInterface(descriptor);接口是否相同,如果不匹配,就会抛出错误"Binder invocation to an incorrect interface"

包裹源代码:

static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name)
{
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if (parcel != NULL) {
        const jchar* str = env->GetStringCritical(name, 0);
        if (str) {
            IPCThreadState* threadState = IPCThreadState::self();
            const int32_t oldPolicy = threadState->getStrictModePolicy();
            const bool isValid = parcel->enforceInterface(
                String16(reinterpret_cast<const char16_t*>(str),
                        env->GetStringLength(name)),
                threadState);
            env->ReleaseStringCritical(name, str);
            if (isValid) {
                const int32_t newPolicy = threadState->getStrictModePolicy();
                if (oldPolicy != newPolicy) {
                    // Need to keep the Java-level thread-local strict
                    // mode policy in sync for the libcore
                    // enforcements, which involves an upcall back
                    // into Java.  (We can't modify the
                    // Parcel.enforceInterface signature, as it's
                    // pseudo-public, and used via AIDL
                    // auto-generation...)
                    set_dalvik_blockguard_policy(env, newPolicy);
                }
                return;     // everything was correct -> return silently
            }
        }
    }

    // all error conditions wind up here
    jniThrowException(env, "java/lang/SecurityException",
            "Binder invocation to an incorrect interface");
}


bool Parcel::enforceInterface(const String16& interface,
                            IPCThreadState* threadState) const
{
    int32_t strictPolicy = readInt32();
    if (threadState == NULL) {
        threadState = IPCThreadState::self();
    }
    if ((threadState->getLastTransactionBinderFlags() &
        IBinder::FLAG_ONEWAY) != 0) {
    // For one-way calls, the callee is running entirely
    // disconnected from the caller, so disable StrictMode entirely.
    // Not only does disk/network usage not impact the caller, but
    // there's no way to commuicate back any violations anyway.
    threadState->setStrictModePolicy(0);
    } else {
    threadState->setStrictModePolicy(strictPolicy);
    }
    const String16 str(readString16());
    if (str == interface) {
        return true;
    } else {
        ALOGW("**** enforceInterface() expected '%s' but read '%s'\n",
                String8(interface).string(), String8(str).string());
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)