Loading core/jni/android_util_Binder.cpp +97 −65 Original line number Diff line number Diff line Loading @@ -20,8 +20,6 @@ #include "android_os_Parcel.h" #include "android_util_Binder.h" #include <nativehelper/JNIHelp.h> #include <fcntl.h> #include <inttypes.h> #include <stdio.h> Loading @@ -44,8 +42,9 @@ #include <utils/SystemClock.h> #include <utils/threads.h> #include <nativehelper/ScopedUtfChars.h> #include <nativehelper/JNIHelp.h> #include <nativehelper/ScopedLocalRef.h> #include <nativehelper/ScopedUtfChars.h> #include "core_jni_helpers.h" Loading Loading @@ -133,6 +132,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; // **************************************************************************** // **************************************************************************** // **************************************************************************** Loading Loading @@ -166,56 +173,36 @@ static JNIEnv* javavm_to_jnienv(JavaVM* vm) return vm->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0 ? env : NULL; } static void report_exception(JNIEnv* env, jthrowable excep, const char* msg) // Report a java.lang.Error (or subclass). This will terminate the runtime by // calling FatalError with a message derived from the given error. static void report_java_lang_error_fatal_error(JNIEnv* env, jthrowable error, const char* msg) { env->ExceptionClear(); jstring tagstr = env->NewStringUTF(LOG_TAG); jstring msgstr = NULL; if (tagstr != NULL) { msgstr = env->NewStringUTF(msg); } if ((tagstr == NULL) || (msgstr == NULL)) { env->ExceptionClear(); /* assume exception (OOM?) was thrown */ ALOGE("Unable to call Log.e()\n"); ALOGE("%s", msg); goto bail; } env->CallStaticIntMethod( gLogOffsets.mClass, gLogOffsets.mLogE, tagstr, msgstr, excep); if (env->ExceptionCheck()) { /* attempting to log the failure has failed */ ALOGW("Failed trying to log exception, msg='%s'\n", msg); env->ExceptionClear(); } if (env->IsInstanceOf(excep, gErrorOffsets.mClass)) { /* * It's an Error: Reraise the exception and ask the runtime to abort. */ // Report an error: reraise the exception and ask the runtime to abort. // Try to get the exception string. Sometimes logcat isn't available, // so try to add it to the abort message. std::string exc_msg = "(Unknown exception message)"; { ScopedLocalRef<jclass> exc_class(env, env->GetObjectClass(excep)); jmethodID method_id = env->GetMethodID(exc_class.get(), "toString", ScopedLocalRef<jclass> exc_class(env, env->GetObjectClass(error)); jmethodID method_id = env->GetMethodID(exc_class.get(), "toString", "()Ljava/lang/String;"); ScopedLocalRef<jstring> jstr( env, reinterpret_cast<jstring>( env->CallObjectMethod(excep, method_id))); env->CallObjectMethod(error, method_id))); env->ExceptionClear(); // Just for good measure. if (jstr.get() != nullptr) { ScopedUtfChars jstr_utf(env, jstr.get()); if (jstr_utf.c_str() != nullptr) { exc_msg = jstr_utf.c_str(); } else { env->ExceptionClear(); } } } env->Throw(excep); env->Throw(error); ALOGE("java.lang.Error thrown during binder transaction (stack trace follows) : "); env->ExceptionDescribe(); Loading @@ -225,10 +212,54 @@ static void report_exception(JNIEnv* env, jthrowable excep, const char* msg) env->FatalError(error_msg.c_str()); } bail: /* discard local refs created for us by VM */ env->DeleteLocalRef(tagstr); env->DeleteLocalRef(msgstr); // Report a java.lang.Error (or subclass). This will terminate the runtime, either by // the uncaught exception handler, or explicitly by calling // report_java_lang_error_fatal_error. static void report_java_lang_error(JNIEnv* env, jthrowable error, const char* msg) { // 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). As the binder code cannot handle Errors, attempt to log the error and // abort. env->ExceptionClear(); report_java_lang_error_fatal_error(env, error, msg); } static void report_exception(JNIEnv* env, jthrowable excep, const char* msg) { env->ExceptionClear(); ScopedLocalRef<jstring> tagstr(env, env->NewStringUTF(LOG_TAG)); ScopedLocalRef<jstring> msgstr(env); if (tagstr != nullptr) { msgstr.reset(env->NewStringUTF(msg)); } if ((tagstr != nullptr) && (msgstr != nullptr)) { env->CallStaticIntMethod(gLogOffsets.mClass, gLogOffsets.mLogE, tagstr.get(), msgstr.get(), excep); if (env->ExceptionCheck()) { // Attempting to log the failure has failed. ALOGW("Failed trying to log exception, msg='%s'\n", msg); env->ExceptionClear(); } } else { env->ExceptionClear(); /* assume exception (OOM?) was thrown */ ALOGE("Unable to call Log.e()\n"); ALOGE("%s", msg); } if (env->IsInstanceOf(excep, gErrorOffsets.mClass)) { report_java_lang_error(env, excep, msg); } } class JavaBBinderHolder; Loading Loading @@ -280,14 +311,11 @@ protected: code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags); if (env->ExceptionCheck()) { jthrowable excep = env->ExceptionOccurred(); report_exception(env, excep, ScopedLocalRef<jthrowable> excep(env, env->ExceptionOccurred()); report_exception(env, excep.get(), "*** 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 Loading @@ -299,11 +327,9 @@ protected: } if (env->ExceptionCheck()) { jthrowable excep = env->ExceptionOccurred(); report_exception(env, excep, ScopedLocalRef<jthrowable> excep(env, env->ExceptionOccurred()); report_exception(env, excep.get(), "*** 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 Loading Loading @@ -446,9 +472,8 @@ public: if (mObject != NULL) { result = env->IsSameObject(obj, mObject); } else { jobject me = env->NewLocalRef(mObjectWeak); result = env->IsSameObject(obj, me); env->DeleteLocalRef(me); ScopedLocalRef<jobject> me(env, env->NewLocalRef(mObjectWeak)); result = env->IsSameObject(obj, me.get()); } return result; } Loading Loading @@ -1337,5 +1362,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; } Loading
core/jni/android_util_Binder.cpp +97 −65 Original line number Diff line number Diff line Loading @@ -20,8 +20,6 @@ #include "android_os_Parcel.h" #include "android_util_Binder.h" #include <nativehelper/JNIHelp.h> #include <fcntl.h> #include <inttypes.h> #include <stdio.h> Loading @@ -44,8 +42,9 @@ #include <utils/SystemClock.h> #include <utils/threads.h> #include <nativehelper/ScopedUtfChars.h> #include <nativehelper/JNIHelp.h> #include <nativehelper/ScopedLocalRef.h> #include <nativehelper/ScopedUtfChars.h> #include "core_jni_helpers.h" Loading Loading @@ -133,6 +132,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; // **************************************************************************** // **************************************************************************** // **************************************************************************** Loading Loading @@ -166,56 +173,36 @@ static JNIEnv* javavm_to_jnienv(JavaVM* vm) return vm->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0 ? env : NULL; } static void report_exception(JNIEnv* env, jthrowable excep, const char* msg) // Report a java.lang.Error (or subclass). This will terminate the runtime by // calling FatalError with a message derived from the given error. static void report_java_lang_error_fatal_error(JNIEnv* env, jthrowable error, const char* msg) { env->ExceptionClear(); jstring tagstr = env->NewStringUTF(LOG_TAG); jstring msgstr = NULL; if (tagstr != NULL) { msgstr = env->NewStringUTF(msg); } if ((tagstr == NULL) || (msgstr == NULL)) { env->ExceptionClear(); /* assume exception (OOM?) was thrown */ ALOGE("Unable to call Log.e()\n"); ALOGE("%s", msg); goto bail; } env->CallStaticIntMethod( gLogOffsets.mClass, gLogOffsets.mLogE, tagstr, msgstr, excep); if (env->ExceptionCheck()) { /* attempting to log the failure has failed */ ALOGW("Failed trying to log exception, msg='%s'\n", msg); env->ExceptionClear(); } if (env->IsInstanceOf(excep, gErrorOffsets.mClass)) { /* * It's an Error: Reraise the exception and ask the runtime to abort. */ // Report an error: reraise the exception and ask the runtime to abort. // Try to get the exception string. Sometimes logcat isn't available, // so try to add it to the abort message. std::string exc_msg = "(Unknown exception message)"; { ScopedLocalRef<jclass> exc_class(env, env->GetObjectClass(excep)); jmethodID method_id = env->GetMethodID(exc_class.get(), "toString", ScopedLocalRef<jclass> exc_class(env, env->GetObjectClass(error)); jmethodID method_id = env->GetMethodID(exc_class.get(), "toString", "()Ljava/lang/String;"); ScopedLocalRef<jstring> jstr( env, reinterpret_cast<jstring>( env->CallObjectMethod(excep, method_id))); env->CallObjectMethod(error, method_id))); env->ExceptionClear(); // Just for good measure. if (jstr.get() != nullptr) { ScopedUtfChars jstr_utf(env, jstr.get()); if (jstr_utf.c_str() != nullptr) { exc_msg = jstr_utf.c_str(); } else { env->ExceptionClear(); } } } env->Throw(excep); env->Throw(error); ALOGE("java.lang.Error thrown during binder transaction (stack trace follows) : "); env->ExceptionDescribe(); Loading @@ -225,10 +212,54 @@ static void report_exception(JNIEnv* env, jthrowable excep, const char* msg) env->FatalError(error_msg.c_str()); } bail: /* discard local refs created for us by VM */ env->DeleteLocalRef(tagstr); env->DeleteLocalRef(msgstr); // Report a java.lang.Error (or subclass). This will terminate the runtime, either by // the uncaught exception handler, or explicitly by calling // report_java_lang_error_fatal_error. static void report_java_lang_error(JNIEnv* env, jthrowable error, const char* msg) { // 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). As the binder code cannot handle Errors, attempt to log the error and // abort. env->ExceptionClear(); report_java_lang_error_fatal_error(env, error, msg); } static void report_exception(JNIEnv* env, jthrowable excep, const char* msg) { env->ExceptionClear(); ScopedLocalRef<jstring> tagstr(env, env->NewStringUTF(LOG_TAG)); ScopedLocalRef<jstring> msgstr(env); if (tagstr != nullptr) { msgstr.reset(env->NewStringUTF(msg)); } if ((tagstr != nullptr) && (msgstr != nullptr)) { env->CallStaticIntMethod(gLogOffsets.mClass, gLogOffsets.mLogE, tagstr.get(), msgstr.get(), excep); if (env->ExceptionCheck()) { // Attempting to log the failure has failed. ALOGW("Failed trying to log exception, msg='%s'\n", msg); env->ExceptionClear(); } } else { env->ExceptionClear(); /* assume exception (OOM?) was thrown */ ALOGE("Unable to call Log.e()\n"); ALOGE("%s", msg); } if (env->IsInstanceOf(excep, gErrorOffsets.mClass)) { report_java_lang_error(env, excep, msg); } } class JavaBBinderHolder; Loading Loading @@ -280,14 +311,11 @@ protected: code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags); if (env->ExceptionCheck()) { jthrowable excep = env->ExceptionOccurred(); report_exception(env, excep, ScopedLocalRef<jthrowable> excep(env, env->ExceptionOccurred()); report_exception(env, excep.get(), "*** 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 Loading @@ -299,11 +327,9 @@ protected: } if (env->ExceptionCheck()) { jthrowable excep = env->ExceptionOccurred(); report_exception(env, excep, ScopedLocalRef<jthrowable> excep(env, env->ExceptionOccurred()); report_exception(env, excep.get(), "*** 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 Loading Loading @@ -446,9 +472,8 @@ public: if (mObject != NULL) { result = env->IsSameObject(obj, mObject); } else { jobject me = env->NewLocalRef(mObjectWeak); result = env->IsSameObject(obj, me); env->DeleteLocalRef(me); ScopedLocalRef<jobject> me(env, env->NewLocalRef(mObjectWeak)); result = env->IsSameObject(obj, me.get()); } return result; } Loading Loading @@ -1337,5 +1362,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; }