From 75a75d642b62f8e7df511256c7f3d86a12699878 Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Fri, 8 Sep 2017 17:44:05 -0700 Subject: [PATCH] Binder: Change reaction to Error Instead of aborting immediately with a native error, try to call Thread.dispatchUncaughtException to trigger a Java-side abort. Only fall back to the old strategy if this fails. (cherry picked from commit 1cd76f5c93bc1e2409c880cade19a323cd999aed) Bug: 64689630 Test: m Test: manual test Merged-In: If07a04d3769f3b9181c4736220333df9a2871a16 Change-Id: If07a04d3769f3b9181c4736220333df9a2871a16 --- core/jni/android_util_Binder.cpp | 36 ++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index 5b0f7768c165d..883d4db048905 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -133,6 +133,14 @@ static struct strict_mode_callback_offsets_t jmethodID mCallback; } gStrictModeCallbackOffsets; +static struct thread_dispatch_offsets_t +{ + // Class state. + jclass mClass; + jmethodID mDispatchUncaughtException; + jmethodID mCurrentThread; +} gThreadDispatchOffsets; + // **************************************************************************** // **************************************************************************** // **************************************************************************** @@ -166,6 +174,23 @@ static JNIEnv* javavm_to_jnienv(JavaVM* vm) return vm->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0 ? env : NULL; } +// Report a java.lang.Error (or subclass). This may terminate the runtime. +static void report_java_lang_error(JNIEnv* env, jthrowable error) +{ + // Try to run the uncaught exception machinery. + jobject thread = env->CallStaticObjectMethod(gThreadDispatchOffsets.mClass, + gThreadDispatchOffsets.mCurrentThread); + if (thread != nullptr) { + env->CallVoidMethod(thread, gThreadDispatchOffsets.mDispatchUncaughtException, + error); + // Should not return here, unless more errors occured. + } + // Some error occurred that meant that either dispatchUncaughtException could not be + // called or that it had an error itself (as this should be unreachable under normal + // conditions). Clear the exception. + env->ExceptionClear(); +} + static void report_exception(JNIEnv* env, jthrowable excep, const char* msg) { env->ExceptionClear(); @@ -192,6 +217,10 @@ static void report_exception(JNIEnv* env, jthrowable excep, const char* msg) } if (env->IsInstanceOf(excep, gErrorOffsets.mClass)) { + // Try to report the error. This should not return under normal circumstances. + report_java_lang_error(env, excep); + // The traditional handling: re-raise and abort. + /* * It's an Error: Reraise the exception and ask the runtime to abort. */ @@ -1337,5 +1366,12 @@ int register_android_os_Binder(JNIEnv* env) gStrictModeCallbackOffsets.mCallback = GetStaticMethodIDOrDie(env, clazz, "onBinderStrictModePolicyChange", "(I)V"); + clazz = FindClassOrDie(env, "java/lang/Thread"); + gThreadDispatchOffsets.mClass = MakeGlobalRefOrDie(env, clazz); + gThreadDispatchOffsets.mDispatchUncaughtException = GetMethodIDOrDie(env, clazz, + "dispatchUncaughtException", "(Ljava/lang/Throwable;)V"); + gThreadDispatchOffsets.mCurrentThread = GetStaticMethodIDOrDie(env, clazz, "currentThread", + "()Ljava/lang/Thread;"); + return 0; }