Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is Parcel.enforceInterface?

Can anyone tell me what the method enforceInterface in Android's Parcel class does? The developer website does not explain its purpose, and Google doesn't return any helpful hits either.

Thanks.

like image 434
user1118764 Avatar asked Apr 19 '16 03:04

user1118764


1 Answers

This method will check whether the interface is the same between the client and the server side when processing RPC call.

Detail process:

  1. client side call server remote method, before call mRemote.transact, this method _data.writeInterfaceToken(DESCRIPTOR); will call first.
  2. server side onTransact will be called, and then call data.enforceInterface(descriptor); to check whether the interface is the same, if they did't match, an error will throw "Binder invocation to an incorrect interface".

Parcel source code:

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;
    }
}
like image 198
dreamtale Avatar answered Oct 15 '22 08:10

dreamtale