From 581c7646fbd0f54595fbe441068edc8e999cb67e Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 21 Jan 2022 11:40:52 +0000 Subject: [PATCH] fix(ndk): don't attempt to share the `bsg_jni_cache` between threads --- CHANGELOG.md | 3 + .../src/main/jni/bugsnag.c | 39 ++- .../src/main/jni/bugsnag_ndk.c | 39 +-- .../src/main/jni/jni_cache.c | 280 ++++++++--------- .../src/main/jni/jni_cache.h | 6 +- .../src/main/jni/metadata.c | 295 +++++++++--------- .../src/main/jni/metadata.h | 7 +- 7 files changed, 329 insertions(+), 340 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c43400eaa3..f439325b3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ * Discarded unhandled exceptions are propagated to any previously registered handlers [#1584](https://github.com/bugsnag/bugsnag-android/pull/1584) + +* Fix SIGABRT crashes caused by race conditions in the NDK layer + []() ## 5.19.0 (2022-01-12) diff --git a/bugsnag-plugin-android-ndk/src/main/jni/bugsnag.c b/bugsnag-plugin-android-ndk/src/main/jni/bugsnag.c index a1e5393bdd..4fa9c904b1 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/bugsnag.c +++ b/bugsnag-plugin-android-ndk/src/main/jni/bugsnag.c @@ -118,7 +118,9 @@ void bugsnag_notify_env(JNIEnv *env, const char *name, const char *message, jbyteArray jname = NULL; jbyteArray jmessage = NULL; - if (!bsg_jni_cache_refresh(env)) { + bsg_jni_cache jni_cache; + + if (!bsg_jni_cache_refresh(env, &jni_cache)) { BUGSNAG_LOG("Could not refresh JNI cache."); goto exit; } @@ -130,25 +132,25 @@ void bugsnag_notify_env(JNIEnv *env, const char *name, const char *message, // create StackTraceElement array jtrace = bsg_safe_new_object_array(env, frame_count, - bsg_global_jni_cache->stack_trace_element); + jni_cache.stack_trace_element); if (jtrace == NULL) { goto exit; } // populate stacktrace object populate_notify_stacktrace(env, stacktrace, frame_count, - bsg_global_jni_cache->stack_trace_element, - bsg_global_jni_cache->ste_constructor, jtrace); + jni_cache.stack_trace_element, + jni_cache.ste_constructor, jtrace); // get the severity field jfieldID severity_field = - parse_jseverity(env, severity, bsg_global_jni_cache->severity); + parse_jseverity(env, severity, jni_cache.severity); if (severity_field == NULL) { goto exit; } // get the error severity object jseverity = bsg_safe_get_static_object_field( - env, bsg_global_jni_cache->severity, severity_field); + env, jni_cache.severity, severity_field); if (jseverity == NULL) { goto exit; } @@ -156,8 +158,8 @@ void bugsnag_notify_env(JNIEnv *env, const char *name, const char *message, jname = bsg_byte_ary_from_string(env, name); jmessage = bsg_byte_ary_from_string(env, message); - bsg_safe_call_static_void_method(env, bsg_global_jni_cache->native_interface, - bsg_global_jni_cache->ni_notify, jname, + bsg_safe_call_static_void_method(env, jni_cache.native_interface, + jni_cache.ni_notify, jname, jmessage, jseverity, jtrace); goto exit; @@ -173,7 +175,10 @@ void bugsnag_notify_env(JNIEnv *env, const char *name, const char *message, void bugsnag_set_user_env(JNIEnv *env, const char *id, const char *email, const char *name) { - if (!bsg_jni_cache_refresh(env)) { + + bsg_jni_cache jni_cache; + + if (!bsg_jni_cache_refresh(env, &jni_cache)) { BUGSNAG_LOG("Could not refresh JNI cache."); return; } @@ -182,8 +187,8 @@ void bugsnag_set_user_env(JNIEnv *env, const char *id, const char *email, jbyteArray jemail = bsg_byte_ary_from_string(env, email); jbyteArray jname = bsg_byte_ary_from_string(env, name); - bsg_safe_call_static_void_method(env, bsg_global_jni_cache->native_interface, - bsg_global_jni_cache->ni_set_user, jid, + bsg_safe_call_static_void_method(env, jni_cache.native_interface, + jni_cache.ni_set_user, jid, jemail, jname); bsg_safe_release_byte_array_elements(env, jid, (jbyte *)id); @@ -220,30 +225,32 @@ static jfieldID parse_jcrumb_type(JNIEnv *env, void bugsnag_leave_breadcrumb_env(JNIEnv *env, const char *message, const bugsnag_breadcrumb_type type) { + bsg_jni_cache jni_cache; + jbyteArray jmessage = NULL; jobject jtype = NULL; - if (!bsg_jni_cache_refresh(env)) { + if (!bsg_jni_cache_refresh(env, &jni_cache)) { BUGSNAG_LOG("Could not refresh JNI cache."); goto exit; } // get breadcrumb type fieldID jfieldID crumb_type = - parse_jcrumb_type(env, type, bsg_global_jni_cache->breadcrumb_type); + parse_jcrumb_type(env, type, jni_cache.breadcrumb_type); if (crumb_type == NULL) { goto exit; } // get the breadcrumb type jtype = bsg_safe_get_static_object_field( - env, bsg_global_jni_cache->breadcrumb_type, crumb_type); + env, jni_cache.breadcrumb_type, crumb_type); if (jtype == NULL) { goto exit; } jmessage = bsg_byte_ary_from_string(env, message); - bsg_safe_call_static_void_method(env, bsg_global_jni_cache->native_interface, - bsg_global_jni_cache->ni_leave_breadcrumb, + bsg_safe_call_static_void_method(env, jni_cache.native_interface, + jni_cache.ni_leave_breadcrumb, jmessage, jtype); goto exit; diff --git a/bugsnag-plugin-android-ndk/src/main/jni/bugsnag_ndk.c b/bugsnag-plugin-android-ndk/src/main/jni/bugsnag_ndk.c index e1e569560d..902aa84080 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/bugsnag_ndk.c +++ b/bugsnag-plugin-android-ndk/src/main/jni/bugsnag_ndk.c @@ -150,8 +150,10 @@ JNIEXPORT void JNICALL Java_com_bugsnag_android_ndk_NativeBridge_install( jboolean auto_detect_ndk_crashes, jint _api_level, jboolean is32bit, jint send_threads) { - if (!bsg_jni_cache_refresh(env)) { - BUGSNAG_LOG("Could not refresh JNI cache."); + bsg_jni_cache jni_cache; + + if (!bsg_jni_cache_refresh(env, &jni_cache)) { + BUGSNAG_LOG("Could not refresh JNI jni_cache."); } bsg_environment *bugsnag_env = calloc(1, sizeof(bsg_environment)); @@ -189,7 +191,7 @@ JNIEXPORT void JNICALL Java_com_bugsnag_android_ndk_NativeBridge_install( } // populate metadata from Java layer - bsg_populate_event(env, &bugsnag_env->next_event); + bsg_populate_event(env, &jni_cache, &bugsnag_env->next_event); time(&bugsnag_env->start_time); if (bugsnag_env->next_event.app.in_foreground) { bugsnag_env->foreground_start_time = bugsnag_env->start_time; @@ -224,6 +226,8 @@ Java_com_bugsnag_android_ndk_NativeBridge_deliverReportAtPath( static pthread_mutex_t bsg_native_delivery_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&bsg_native_delivery_mutex); + bsg_jni_cache jni_cache; + const char *event_path = NULL; bugsnag_event *event = NULL; jbyteArray jpayload = NULL; @@ -231,11 +235,7 @@ Java_com_bugsnag_android_ndk_NativeBridge_deliverReportAtPath( char *payload = NULL; jstring japi_key = NULL; - if (bsg_global_jni_cache == NULL) { - goto exit; - } - - if (!bsg_jni_cache_refresh(env)) { + if (!bsg_jni_cache_refresh(env, &jni_cache)) { BUGSNAG_LOG("Could not refresh JNI cache."); goto exit; } @@ -277,10 +277,9 @@ Java_com_bugsnag_android_ndk_NativeBridge_deliverReportAtPath( japi_key = bsg_safe_new_string_utf(env, event->api_key); if (japi_key != NULL) { bool is_launching = event->app.is_launching; - bsg_safe_call_static_void_method(env, - bsg_global_jni_cache->native_interface, - bsg_global_jni_cache->ni_deliver_report, - jstage, jpayload, japi_key, is_launching); + bsg_safe_call_static_void_method(env, jni_cache.native_interface, + jni_cache.ni_deliver_report, jstage, + jpayload, japi_key, is_launching); } exit: @@ -362,10 +361,10 @@ JNIEXPORT void JNICALL Java_com_bugsnag_android_ndk_NativeBridge_pausedSession( JNIEXPORT void JNICALL Java_com_bugsnag_android_ndk_NativeBridge_addBreadcrumb( JNIEnv *env, jobject _this, jstring name_, jstring crumb_type, jstring timestamp_, jobject metadata) { - if (bsg_global_env == NULL) { - return; - } - if (!bsg_jni_cache_refresh(env)) { + + bsg_jni_cache jni_cache; + + if (!bsg_jni_cache_refresh(env, &jni_cache)) { BUGSNAG_LOG("Could not refresh JNI cache."); return; } @@ -395,7 +394,7 @@ JNIEXPORT void JNICALL Java_com_bugsnag_android_ndk_NativeBridge_addBreadcrumb( crumb->type = BSG_CRUMB_MANUAL; } - bsg_populate_crumb_metadata(env, crumb, metadata); + bsg_populate_crumb_metadata(env, &jni_cache, crumb, metadata); request_env_write_lock(); bugsnag_event_add_breadcrumb(&bsg_global_env->next_event, crumb); release_env_write_lock(); @@ -717,12 +716,14 @@ JNIEXPORT void JNICALL Java_com_bugsnag_android_ndk_NativeBridge_updateMetadata( if (bsg_global_env == NULL) { return; } - if (!bsg_jni_cache_refresh(env)) { + + bsg_jni_cache jni_cache; + if (!bsg_jni_cache_refresh(env, &jni_cache)) { BUGSNAG_LOG("Could not refresh JNI cache."); return; } request_env_write_lock(); - bsg_populate_metadata(env, &bsg_global_env->next_event.metadata, metadata); + bsg_populate_metadata(env, &jni_cache, &bsg_global_env->next_event.metadata, metadata); release_env_write_lock(); } diff --git a/bugsnag-plugin-android-ndk/src/main/jni/jni_cache.c b/bugsnag-plugin-android-ndk/src/main/jni/jni_cache.c index 921643ef66..b82991f900 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/jni_cache.c +++ b/bugsnag-plugin-android-ndk/src/main/jni/jni_cache.c @@ -15,11 +15,8 @@ #define report_contents(VALUE, TYPECODE) \ BUGSNAG_LOG(#VALUE " == " TYPECODE, VALUE) -static bsg_jni_cache global_jni_cache; -bsg_jni_cache *bsg_global_jni_cache = &global_jni_cache; - -bool bsg_jni_cache_refresh(JNIEnv *env) { - if (bsg_global_jni_cache == NULL) { +bool bsg_jni_cache_refresh(JNIEnv *env, bsg_jni_cache *cache) { + if (cache == NULL) { return false; } @@ -28,264 +25,251 @@ bool bsg_jni_cache_refresh(JNIEnv *env) { // Classes - bsg_global_jni_cache->integer = bsg_safe_find_class(env, "java/lang/Integer"); - if (bsg_global_jni_cache->integer == NULL) { - report_contents(bsg_global_jni_cache->integer, "%p"); + cache->integer = bsg_safe_find_class(env, "java/lang/Integer"); + if (cache->integer == NULL) { + report_contents(cache->integer, "%p"); goto failed; } - bsg_global_jni_cache->boolean = bsg_safe_find_class(env, "java/lang/Boolean"); - if (bsg_global_jni_cache->boolean == NULL) { - report_contents(bsg_global_jni_cache->boolean, "%p"); + cache->boolean = bsg_safe_find_class(env, "java/lang/Boolean"); + if (cache->boolean == NULL) { + report_contents(cache->boolean, "%p"); goto failed; } - bsg_global_jni_cache->long_class = bsg_safe_find_class(env, "java/lang/Long"); - if (bsg_global_jni_cache->long_class == NULL) { - report_contents(bsg_global_jni_cache->long_class, "%p"); + cache->long_class = bsg_safe_find_class(env, "java/lang/Long"); + if (cache->long_class == NULL) { + report_contents(cache->long_class, "%p"); goto failed; } - bsg_global_jni_cache->float_class = - bsg_safe_find_class(env, "java/lang/Float"); - if (bsg_global_jni_cache->float_class == NULL) { - report_contents(bsg_global_jni_cache->float_class, "%p"); + cache->float_class = bsg_safe_find_class(env, "java/lang/Float"); + if (cache->float_class == NULL) { + report_contents(cache->float_class, "%p"); goto failed; } - bsg_global_jni_cache->number = bsg_safe_find_class(env, "java/lang/Number"); - if (bsg_global_jni_cache->number == NULL) { - report_contents(bsg_global_jni_cache->number, "%p"); + cache->number = bsg_safe_find_class(env, "java/lang/Number"); + if (cache->number == NULL) { + report_contents(cache->number, "%p"); goto failed; } - bsg_global_jni_cache->string = bsg_safe_find_class(env, "java/lang/String"); - if (bsg_global_jni_cache->string == NULL) { - report_contents(bsg_global_jni_cache->string, "%p"); + cache->string = bsg_safe_find_class(env, "java/lang/String"); + if (cache->string == NULL) { + report_contents(cache->string, "%p"); goto failed; } // Methods - bsg_global_jni_cache->arraylist = - bsg_safe_find_class(env, "java/util/ArrayList"); - if (bsg_global_jni_cache->arraylist == NULL) { - report_contents(bsg_global_jni_cache->arraylist, "%p"); + cache->arraylist = bsg_safe_find_class(env, "java/util/ArrayList"); + if (cache->arraylist == NULL) { + report_contents(cache->arraylist, "%p"); goto failed; } - bsg_global_jni_cache->hash_map = - bsg_safe_find_class(env, "java/util/HashMap"); - if (bsg_global_jni_cache->hash_map == NULL) { - report_contents(bsg_global_jni_cache->hash_map, "%p"); + cache->hash_map = bsg_safe_find_class(env, "java/util/HashMap"); + if (cache->hash_map == NULL) { + report_contents(cache->hash_map, "%p"); goto failed; } - bsg_global_jni_cache->map = bsg_safe_find_class(env, "java/util/Map"); - if (bsg_global_jni_cache->map == NULL) { - report_contents(bsg_global_jni_cache->map, "%p"); + cache->map = bsg_safe_find_class(env, "java/util/Map"); + if (cache->map == NULL) { + report_contents(cache->map, "%p"); goto failed; } - bsg_global_jni_cache->native_interface = + cache->native_interface = bsg_safe_find_class(env, "com/bugsnag/android/NativeInterface"); - if (bsg_global_jni_cache->native_interface == NULL) { - report_contents(bsg_global_jni_cache->native_interface, "%p"); + if (cache->native_interface == NULL) { + report_contents(cache->native_interface, "%p"); goto failed; } - bsg_global_jni_cache->stack_trace_element = + cache->stack_trace_element = bsg_safe_find_class(env, "java/lang/StackTraceElement"); - if (bsg_global_jni_cache->stack_trace_element == NULL) { - report_contents(bsg_global_jni_cache->stack_trace_element, "%p"); + if (cache->stack_trace_element == NULL) { + report_contents(cache->stack_trace_element, "%p"); goto failed; } - bsg_global_jni_cache->severity = - bsg_safe_find_class(env, "com/bugsnag/android/Severity"); - if (bsg_global_jni_cache->severity == NULL) { - report_contents(bsg_global_jni_cache->severity, "%p"); + cache->severity = bsg_safe_find_class(env, "com/bugsnag/android/Severity"); + if (cache->severity == NULL) { + report_contents(cache->severity, "%p"); goto failed; } - bsg_global_jni_cache->breadcrumb_type = + cache->breadcrumb_type = bsg_safe_find_class(env, "com/bugsnag/android/BreadcrumbType"); - if (bsg_global_jni_cache->breadcrumb_type == NULL) { - report_contents(bsg_global_jni_cache->breadcrumb_type, "%p"); + if (cache->breadcrumb_type == NULL) { + report_contents(cache->breadcrumb_type, "%p"); goto failed; } - bsg_global_jni_cache->integer_int_value = bsg_safe_get_method_id( - env, bsg_global_jni_cache->integer, "intValue", "()I"); - if (bsg_global_jni_cache->integer_int_value == NULL) { - report_contents(bsg_global_jni_cache->integer_int_value, "%p"); + cache->integer_int_value = + bsg_safe_get_method_id(env, cache->integer, "intValue", "()I"); + if (cache->integer_int_value == NULL) { + report_contents(cache->integer_int_value, "%p"); goto failed; } - bsg_global_jni_cache->float_float_value = bsg_safe_get_method_id( - env, bsg_global_jni_cache->float_class, "floatValue", "()F"); - if (bsg_global_jni_cache->float_float_value == NULL) { - report_contents(bsg_global_jni_cache->float_float_value, "%p"); + cache->float_float_value = + bsg_safe_get_method_id(env, cache->float_class, "floatValue", "()F"); + if (cache->float_float_value == NULL) { + report_contents(cache->float_float_value, "%p"); goto failed; } - bsg_global_jni_cache->number_double_value = bsg_safe_get_method_id( - env, bsg_global_jni_cache->number, "doubleValue", "()D"); - if (bsg_global_jni_cache->number_double_value == NULL) { - report_contents(bsg_global_jni_cache->number_double_value, "%p"); + cache->number_double_value = + bsg_safe_get_method_id(env, cache->number, "doubleValue", "()D"); + if (cache->number_double_value == NULL) { + report_contents(cache->number_double_value, "%p"); goto failed; } - bsg_global_jni_cache->long_long_value = bsg_safe_get_method_id( - env, bsg_global_jni_cache->integer, "longValue", "()J"); - if (bsg_global_jni_cache->long_long_value == NULL) { - report_contents(bsg_global_jni_cache->long_long_value, "%p"); + cache->long_long_value = + bsg_safe_get_method_id(env, cache->integer, "longValue", "()J"); + if (cache->long_long_value == NULL) { + report_contents(cache->long_long_value, "%p"); goto failed; } - bsg_global_jni_cache->boolean_bool_value = bsg_safe_get_method_id( - env, bsg_global_jni_cache->boolean, "booleanValue", "()Z"); - if (bsg_global_jni_cache->boolean_bool_value == NULL) { - report_contents(bsg_global_jni_cache->boolean_bool_value, "%p"); + cache->boolean_bool_value = + bsg_safe_get_method_id(env, cache->boolean, "booleanValue", "()Z"); + if (cache->boolean_bool_value == NULL) { + report_contents(cache->boolean_bool_value, "%p"); goto failed; } - bsg_global_jni_cache->arraylist_init_with_obj = - bsg_safe_get_method_id(env, bsg_global_jni_cache->arraylist, "", - "(Ljava/util/Collection;)V"); - if (bsg_global_jni_cache->arraylist_init_with_obj == NULL) { - report_contents(bsg_global_jni_cache->arraylist_init_with_obj, "%p"); + cache->arraylist_init_with_obj = bsg_safe_get_method_id( + env, cache->arraylist, "", "(Ljava/util/Collection;)V"); + if (cache->arraylist_init_with_obj == NULL) { + report_contents(cache->arraylist_init_with_obj, "%p"); goto failed; } - bsg_global_jni_cache->arraylist_get = bsg_safe_get_method_id( - env, bsg_global_jni_cache->arraylist, "get", "(I)Ljava/lang/Object;"); - if (bsg_global_jni_cache->arraylist_get == NULL) { - report_contents(bsg_global_jni_cache->arraylist_get, "%p"); + cache->arraylist_get = bsg_safe_get_method_id(env, cache->arraylist, "get", + "(I)Ljava/lang/Object;"); + if (cache->arraylist_get == NULL) { + report_contents(cache->arraylist_get, "%p"); goto failed; } - bsg_global_jni_cache->hash_map_key_set = bsg_safe_get_method_id( - env, bsg_global_jni_cache->hash_map, "keySet", "()Ljava/util/Set;"); - if (bsg_global_jni_cache->hash_map_key_set == NULL) { - report_contents(bsg_global_jni_cache->hash_map_key_set, "%p"); + cache->hash_map_key_set = bsg_safe_get_method_id( + env, cache->hash_map, "keySet", "()Ljava/util/Set;"); + if (cache->hash_map_key_set == NULL) { + report_contents(cache->hash_map_key_set, "%p"); goto failed; } - bsg_global_jni_cache->hash_map_size = bsg_safe_get_method_id( - env, bsg_global_jni_cache->hash_map, "size", "()I"); - if (bsg_global_jni_cache->hash_map_size == NULL) { - report_contents(bsg_global_jni_cache->hash_map_size, "%p"); + cache->hash_map_size = + bsg_safe_get_method_id(env, cache->hash_map, "size", "()I"); + if (cache->hash_map_size == NULL) { + report_contents(cache->hash_map_size, "%p"); goto failed; } - bsg_global_jni_cache->hash_map_get = - bsg_safe_get_method_id(env, bsg_global_jni_cache->hash_map, "get", - "(Ljava/lang/Object;)Ljava/lang/Object;"); - if (bsg_global_jni_cache->hash_map_get == NULL) { - report_contents(bsg_global_jni_cache->hash_map_get, "%p"); + cache->hash_map_get = bsg_safe_get_method_id( + env, cache->hash_map, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); + if (cache->hash_map_get == NULL) { + report_contents(cache->hash_map_get, "%p"); goto failed; } - bsg_global_jni_cache->map_key_set = bsg_safe_get_method_id( - env, bsg_global_jni_cache->map, "keySet", "()Ljava/util/Set;"); - if (bsg_global_jni_cache->map_key_set == NULL) { - report_contents(bsg_global_jni_cache->map_key_set, "%p"); + cache->map_key_set = + bsg_safe_get_method_id(env, cache->map, "keySet", "()Ljava/util/Set;"); + if (cache->map_key_set == NULL) { + report_contents(cache->map_key_set, "%p"); goto failed; } - bsg_global_jni_cache->map_size = - bsg_safe_get_method_id(env, bsg_global_jni_cache->map, "size", "()I"); - if (bsg_global_jni_cache->map_size == NULL) { - report_contents(bsg_global_jni_cache->map_size, "%p"); + cache->map_size = bsg_safe_get_method_id(env, cache->map, "size", "()I"); + if (cache->map_size == NULL) { + report_contents(cache->map_size, "%p"); goto failed; } - bsg_global_jni_cache->map_get = - bsg_safe_get_method_id(env, bsg_global_jni_cache->map, "get", - "(Ljava/lang/Object;)Ljava/lang/Object;"); - if (bsg_global_jni_cache->map_get == NULL) { - report_contents(bsg_global_jni_cache->map_get, "%p"); + cache->map_get = bsg_safe_get_method_id( + env, cache->map, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); + if (cache->map_get == NULL) { + report_contents(cache->map_get, "%p"); goto failed; } - bsg_global_jni_cache->ni_get_app = - bsg_safe_get_static_method_id(env, bsg_global_jni_cache->native_interface, - "getApp", "()Ljava/util/Map;"); - if (bsg_global_jni_cache->ni_get_app == NULL) { - report_contents(bsg_global_jni_cache->ni_get_app, "%p"); + cache->ni_get_app = bsg_safe_get_static_method_id( + env, cache->native_interface, "getApp", "()Ljava/util/Map;"); + if (cache->ni_get_app == NULL) { + report_contents(cache->ni_get_app, "%p"); goto failed; } - bsg_global_jni_cache->ni_get_device = - bsg_safe_get_static_method_id(env, bsg_global_jni_cache->native_interface, - "getDevice", "()Ljava/util/Map;"); - if (bsg_global_jni_cache->ni_get_device == NULL) { - report_contents(bsg_global_jni_cache->ni_get_device, "%p"); + cache->ni_get_device = bsg_safe_get_static_method_id( + env, cache->native_interface, "getDevice", "()Ljava/util/Map;"); + if (cache->ni_get_device == NULL) { + report_contents(cache->ni_get_device, "%p"); goto failed; } - bsg_global_jni_cache->ni_get_user = - bsg_safe_get_static_method_id(env, bsg_global_jni_cache->native_interface, - "getUser", "()Ljava/util/Map;"); - if (bsg_global_jni_cache->ni_get_user == NULL) { - report_contents(bsg_global_jni_cache->ni_get_user, "%p"); + cache->ni_get_user = bsg_safe_get_static_method_id( + env, cache->native_interface, "getUser", "()Ljava/util/Map;"); + if (cache->ni_get_user == NULL) { + report_contents(cache->ni_get_user, "%p"); goto failed; } - bsg_global_jni_cache->ni_set_user = bsg_safe_get_static_method_id( - env, bsg_global_jni_cache->native_interface, "setUser", "([B[B[B)V"); - if (bsg_global_jni_cache->ni_set_user == NULL) { - report_contents(bsg_global_jni_cache->ni_set_user, "%p"); + cache->ni_set_user = bsg_safe_get_static_method_id( + env, cache->native_interface, "setUser", "([B[B[B)V"); + if (cache->ni_set_user == NULL) { + report_contents(cache->ni_set_user, "%p"); goto failed; } - bsg_global_jni_cache->ni_get_metadata = - bsg_safe_get_static_method_id(env, bsg_global_jni_cache->native_interface, - "getMetadata", "()Ljava/util/Map;"); - if (bsg_global_jni_cache->ni_get_metadata == NULL) { - report_contents(bsg_global_jni_cache->ni_get_metadata, "%p"); + cache->ni_get_metadata = bsg_safe_get_static_method_id( + env, cache->native_interface, "getMetadata", "()Ljava/util/Map;"); + if (cache->ni_get_metadata == NULL) { + report_contents(cache->ni_get_metadata, "%p"); goto failed; } // lookup NativeInterface.getContext() - bsg_global_jni_cache->ni_get_context = - bsg_safe_get_static_method_id(env, bsg_global_jni_cache->native_interface, - "getContext", "()Ljava/lang/String;"); - if (bsg_global_jni_cache->ni_get_context == NULL) { - report_contents(bsg_global_jni_cache->ni_get_context, "%p"); + cache->ni_get_context = bsg_safe_get_static_method_id( + env, cache->native_interface, "getContext", "()Ljava/lang/String;"); + if (cache->ni_get_context == NULL) { + report_contents(cache->ni_get_context, "%p"); goto failed; } - bsg_global_jni_cache->ni_notify = bsg_safe_get_static_method_id( - env, bsg_global_jni_cache->native_interface, "notify", + cache->ni_notify = bsg_safe_get_static_method_id( + env, cache->native_interface, "notify", "([B[BLcom/bugsnag/android/Severity;[Ljava/lang/StackTraceElement;)V"); - if (bsg_global_jni_cache->ni_notify == NULL) { - report_contents(bsg_global_jni_cache->ni_notify, "%p"); + if (cache->ni_notify == NULL) { + report_contents(cache->ni_notify, "%p"); goto failed; } - bsg_global_jni_cache->ni_deliver_report = bsg_safe_get_static_method_id( - env, bsg_global_jni_cache->native_interface, "deliverReport", + cache->ni_deliver_report = bsg_safe_get_static_method_id( + env, cache->native_interface, "deliverReport", "([B[BLjava/lang/String;Z)V"); - if (bsg_global_jni_cache->ni_deliver_report == NULL) { - report_contents(bsg_global_jni_cache->ni_deliver_report, "%p"); + if (cache->ni_deliver_report == NULL) { + report_contents(cache->ni_deliver_report, "%p"); goto failed; } - bsg_global_jni_cache->ni_leave_breadcrumb = bsg_safe_get_static_method_id( - env, bsg_global_jni_cache->native_interface, "leaveBreadcrumb", + cache->ni_leave_breadcrumb = bsg_safe_get_static_method_id( + env, cache->native_interface, "leaveBreadcrumb", "([BLcom/bugsnag/android/BreadcrumbType;)V"); - if (bsg_global_jni_cache->ni_leave_breadcrumb == NULL) { - report_contents(bsg_global_jni_cache->ni_leave_breadcrumb, "%p"); + if (cache->ni_leave_breadcrumb == NULL) { + report_contents(cache->ni_leave_breadcrumb, "%p"); goto failed; } - bsg_global_jni_cache->ste_constructor = bsg_safe_get_method_id( - env, bsg_global_jni_cache->stack_trace_element, "", + cache->ste_constructor = bsg_safe_get_method_id( + env, cache->stack_trace_element, "", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V"); - if (bsg_global_jni_cache->ste_constructor == NULL) { - report_contents(bsg_global_jni_cache->ste_constructor, "%p"); + if (cache->ste_constructor == NULL) { + report_contents(cache->ste_constructor, "%p"); goto failed; } diff --git a/bugsnag-plugin-android-ndk/src/main/jni/jni_cache.h b/bugsnag-plugin-android-ndk/src/main/jni/jni_cache.h index 72747e1319..866b2ab299 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/jni_cache.h +++ b/bugsnag-plugin-android-ndk/src/main/jni/jni_cache.h @@ -52,17 +52,15 @@ typedef struct { jmethodID ste_constructor; } bsg_jni_cache; -// Always check for null before using this! -extern bsg_jni_cache *bsg_global_jni_cache; - /** * Refresh all references in the JNI cache. * This MUST be called on every Java-to-native call! * * @param env The JNI env + * @param cache The cache to refresh * @return false if an error occurs, in which case the cache is unusable. */ -bool bsg_jni_cache_refresh(JNIEnv *env); +bool bsg_jni_cache_refresh(JNIEnv *env, bsg_jni_cache *cache); #ifdef __cplusplus } diff --git a/bugsnag-plugin-android-ndk/src/main/jni/metadata.c b/bugsnag-plugin-android-ndk/src/main/jni/metadata.c index 2359dff4a6..008d0626b4 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/metadata.c +++ b/bugsnag-plugin-android-ndk/src/main/jni/metadata.c @@ -5,11 +5,12 @@ #include #include -static jobject get_map_value_obj(JNIEnv *env, jobject map, const char *_key) { +static jobject get_map_value_obj(JNIEnv *env, bsg_jni_cache *jni_cache, + jobject map, const char *_key) { jobject obj = NULL; jstring key = NULL; - if (bsg_global_jni_cache == NULL) { + if (jni_cache == NULL) { goto exit; } @@ -18,17 +19,17 @@ static jobject get_map_value_obj(JNIEnv *env, jobject map, const char *_key) { goto exit; } - obj = bsg_safe_call_object_method(env, map, - bsg_global_jni_cache->hash_map_get, key); + obj = bsg_safe_call_object_method(env, map, jni_cache->hash_map_get, key); exit: bsg_safe_delete_local_ref(env, key); return obj; } -static void copy_map_value_string(JNIEnv *env, jobject map, const char *_key, - char *dest, int len) { - jobject _value = get_map_value_obj(env, map, _key); +static void copy_map_value_string(JNIEnv *env, bsg_jni_cache *jni_cache, + jobject map, const char *_key, char *dest, + int len) { + jobject _value = get_map_value_obj(env, jni_cache, map, _key); if (_value == NULL) { return; @@ -44,76 +45,78 @@ static void copy_map_value_string(JNIEnv *env, jobject map, const char *_key, bsg_safe_delete_local_ref(env, _value); } -static long get_map_value_long(JNIEnv *env, jobject map, const char *_key) { +static long get_map_value_long(JNIEnv *env, bsg_jni_cache *jni_cache, + jobject map, const char *_key) { jobject _value = NULL; long value = 0; - if (bsg_global_jni_cache == NULL) { + if (jni_cache == NULL) { goto exit; } - _value = get_map_value_obj(env, map, _key); + _value = get_map_value_obj(env, jni_cache, map, _key); if (_value == NULL) { goto exit; } - value = bsg_safe_call_double_method( - env, _value, bsg_global_jni_cache->number_double_value); + value = + bsg_safe_call_double_method(env, _value, jni_cache->number_double_value); exit: bsg_safe_delete_local_ref(env, _value); return value; } -static float get_map_value_float(JNIEnv *env, jobject map, const char *_key) { +static float get_map_value_float(JNIEnv *env, bsg_jni_cache *jni_cache, + jobject map, const char *_key) { jobject _value = NULL; float value = 0; - if (bsg_global_jni_cache == NULL) { + if (jni_cache == NULL) { goto exit; } - _value = get_map_value_obj(env, map, _key); + _value = get_map_value_obj(env, jni_cache, map, _key); if (_value == NULL) { goto exit; } - value = bsg_safe_call_float_method(env, _value, - bsg_global_jni_cache->float_float_value); + value = bsg_safe_call_float_method(env, _value, jni_cache->float_float_value); exit: bsg_safe_delete_local_ref(env, _value); return value; } -static bool get_map_value_bool(JNIEnv *env, jobject map, const char *_key) { +static bool get_map_value_bool(JNIEnv *env, bsg_jni_cache *jni_cache, + jobject map, const char *_key) { jobject _value = NULL; bool value = 0; - if (bsg_global_jni_cache == NULL) { + if (jni_cache == NULL) { goto exit; } - _value = get_map_value_obj(env, map, _key); + _value = get_map_value_obj(env, jni_cache, map, _key); if (_value == NULL) { goto exit; } - value = bsg_safe_call_boolean_method( - env, _value, bsg_global_jni_cache->boolean_bool_value); + value = + bsg_safe_call_boolean_method(env, _value, jni_cache->boolean_bool_value); exit: bsg_safe_delete_local_ref(env, _value); return value; } -static int populate_cpu_abi_from_map(JNIEnv *env, jobject map, - bsg_device_info *device) { +static int populate_cpu_abi_from_map(JNIEnv *env, bsg_jni_cache *jni_cache, + jobject map, bsg_device_info *device) { jstring key = NULL; jobjectArray _value = NULL; int count = 0; - if (bsg_global_jni_cache == NULL) { + if (jni_cache == NULL) { goto exit; } @@ -122,8 +125,7 @@ static int populate_cpu_abi_from_map(JNIEnv *env, jobject map, goto exit; } - _value = bsg_safe_call_object_method(env, map, - bsg_global_jni_cache->hash_map_get, key); + _value = bsg_safe_call_object_method(env, map, jni_cache->hash_map_get, key); if (_value == NULL) { goto exit; } @@ -153,43 +155,43 @@ static int populate_cpu_abi_from_map(JNIEnv *env, jobject map, return count; } -static void populate_app_data(JNIEnv *env, bugsnag_event *event) { - if (bsg_global_jni_cache == NULL) { +static void populate_app_data(JNIEnv *env, bsg_jni_cache *jni_cache, + bugsnag_event *event) { + if (jni_cache == NULL) { return; } jobject data = bsg_safe_call_static_object_method( - env, bsg_global_jni_cache->native_interface, - bsg_global_jni_cache->ni_get_app); + env, jni_cache->native_interface, jni_cache->ni_get_app); if (data == NULL) { return; } - copy_map_value_string(env, data, "binaryArch", event->app.binary_arch, + copy_map_value_string(env, jni_cache, data, "binaryArch", event->app.binary_arch, sizeof(event->app.binary_arch)); - copy_map_value_string(env, data, "buildUUID", event->app.build_uuid, + copy_map_value_string(env, jni_cache, data, "buildUUID", event->app.build_uuid, sizeof(event->app.build_uuid)); - event->app.duration_ms_offset = get_map_value_long(env, data, "duration"); + event->app.duration_ms_offset = get_map_value_long(env, jni_cache, data, "duration"); event->app.duration_in_foreground_ms_offset = - get_map_value_long(env, data, "durationInForeground"); + get_map_value_long(env, jni_cache, data, "durationInForeground"); - copy_map_value_string(env, data, "id", event->app.id, sizeof(event->app.id)); - event->app.in_foreground = get_map_value_bool(env, data, "inForeground"); + copy_map_value_string(env, jni_cache, data, "id", event->app.id, sizeof(event->app.id)); + event->app.in_foreground = get_map_value_bool(env, jni_cache, data, "inForeground"); event->app.is_launching = true; char name[64]; - copy_map_value_string(env, data, "name", name, sizeof(name)); + copy_map_value_string(env, jni_cache, data, "name", name, sizeof(name)); bugsnag_event_add_metadata_string(event, "app", "name", name); - copy_map_value_string(env, data, "releaseStage", event->app.release_stage, + copy_map_value_string(env, jni_cache, data, "releaseStage", event->app.release_stage, sizeof(event->app.release_stage)); - copy_map_value_string(env, data, "type", event->app.type, + copy_map_value_string(env, jni_cache, data, "type", event->app.type, sizeof(event->app.type)); - copy_map_value_string(env, data, "version", event->app.version, + copy_map_value_string(env, jni_cache, data, "version", event->app.version, sizeof(event->app.version)); - event->app.version_code = get_map_value_long(env, data, "versionCode"); + event->app.version_code = get_map_value_long(env, jni_cache, data, "versionCode"); - bool restricted = get_map_value_bool(env, data, "backgroundWorkRestricted"); + bool restricted = get_map_value_bool(env, jni_cache, data, "backgroundWorkRestricted"); if (restricted) { bugsnag_event_add_metadata_bool(event, "app", "backgroundWorkRestricted", @@ -197,133 +199,133 @@ static void populate_app_data(JNIEnv *env, bugsnag_event *event) { } char process_name[64]; - copy_map_value_string(env, data, "processName", process_name, + copy_map_value_string(env, jni_cache, data, "processName", process_name, sizeof(process_name)); bugsnag_event_add_metadata_string(event, "app", "processName", process_name); - long total_memory = get_map_value_long(env, data, "memoryLimit"); + long total_memory = get_map_value_long(env, jni_cache, data, "memoryLimit"); bugsnag_event_add_metadata_double(event, "app", "memoryLimit", (double)total_memory); bsg_safe_delete_local_ref(env, data); } -static void populate_device_metadata(JNIEnv *env, bugsnag_event *event, - void *data) { +static void populate_device_metadata(JNIEnv *env, bsg_jni_cache *jni_cache, + bugsnag_event *event, void *data) { char brand[64]; - copy_map_value_string(env, data, "brand", brand, sizeof(brand)); + copy_map_value_string(env, jni_cache, data, "brand", brand, sizeof(brand)); bugsnag_event_add_metadata_string(event, "device", "brand", brand); bugsnag_event_add_metadata_double(event, "device", "dpi", - get_map_value_long(env, data, "dpi")); + get_map_value_long(env, jni_cache, data, "dpi")); bugsnag_event_add_metadata_bool(event, "device", "emulator", - get_map_value_bool(env, data, "emulator")); + get_map_value_bool(env, jni_cache, data, "emulator")); char location_status[32]; - copy_map_value_string(env, data, "locationStatus", location_status, + copy_map_value_string(env, jni_cache, data, "locationStatus", location_status, sizeof(location_status)); bugsnag_event_add_metadata_string(event, "device", "locationStatus", location_status); char network_access[64]; - copy_map_value_string(env, data, "networkAccess", network_access, + copy_map_value_string(env, jni_cache, data, "networkAccess", network_access, sizeof(network_access)); bugsnag_event_add_metadata_string(event, "device", "networkAccess", network_access); bugsnag_event_add_metadata_double( event, "device", "screenDensity", - get_map_value_float(env, data, "screenDensity")); + get_map_value_float(env, jni_cache, data, "screenDensity")); char screen_resolution[32]; - copy_map_value_string(env, data, "screenResolution", screen_resolution, + copy_map_value_string(env, jni_cache, data, "screenResolution", screen_resolution, sizeof(screen_resolution)); bugsnag_event_add_metadata_string(event, "device", "screenResolution", screen_resolution); } -static void populate_device_data(JNIEnv *env, bugsnag_event *event) { - if (bsg_global_jni_cache == NULL) { +static void populate_device_data(JNIEnv *env, bsg_jni_cache *jni_cache, + bugsnag_event *event) { + if (jni_cache == NULL) { return; } jobject data = bsg_safe_call_static_object_method( - env, bsg_global_jni_cache->native_interface, - bsg_global_jni_cache->ni_get_device); + env, jni_cache->native_interface, jni_cache->ni_get_device); if (data == NULL) { return; } - populate_cpu_abi_from_map(env, data, &event->device); + populate_cpu_abi_from_map(env, jni_cache, data, &event->device); - copy_map_value_string(env, data, "id", event->device.id, + copy_map_value_string(env, jni_cache, data, "id", event->device.id, sizeof(event->device.id)); - event->device.jailbroken = get_map_value_bool(env, data, "jailbroken"); + event->device.jailbroken = get_map_value_bool(env, jni_cache, data, "jailbroken"); - copy_map_value_string(env, data, "locale", event->device.locale, + copy_map_value_string(env, jni_cache, data, "locale", event->device.locale, sizeof(event->device.locale)); - copy_map_value_string(env, data, "manufacturer", event->device.manufacturer, + copy_map_value_string(env, jni_cache, data, "manufacturer", event->device.manufacturer, sizeof(event->device.manufacturer)); - copy_map_value_string(env, data, "model", event->device.model, + copy_map_value_string(env, jni_cache, data, "model", event->device.model, sizeof(event->device.model)); - copy_map_value_string(env, data, "orientation", event->device.orientation, + copy_map_value_string(env, jni_cache, data, "orientation", event->device.orientation, sizeof(event->device.orientation)); bsg_strncpy(event->device.os_name, bsg_os_name(), sizeof(event->device.os_name)); - copy_map_value_string(env, data, "osVersion", event->device.os_version, + copy_map_value_string(env, jni_cache, data, "osVersion", event->device.os_version, sizeof(event->device.os_version)); - jobject _runtime_versions = get_map_value_obj(env, data, "runtimeVersions"); + jobject _runtime_versions = get_map_value_obj(env, jni_cache, data, "runtimeVersions"); if (_runtime_versions != NULL) { - copy_map_value_string(env, _runtime_versions, "osBuild", + copy_map_value_string(env, jni_cache, _runtime_versions, "osBuild", event->device.os_build, sizeof(event->device.os_build)); char api_level[8]; - copy_map_value_string(env, _runtime_versions, "androidApiLevel", api_level, + copy_map_value_string(env, jni_cache, _runtime_versions, "androidApiLevel", api_level, sizeof(api_level)); event->device.api_level = strtol(api_level, NULL, 10); } - event->device.total_memory = get_map_value_long(env, data, "totalMemory"); + event->device.total_memory = get_map_value_long(env, jni_cache, data, "totalMemory"); // add fields to device metadata - populate_device_metadata(env, event, data); + populate_device_metadata(env, jni_cache, event, data); bsg_safe_delete_local_ref(env, data); bsg_safe_delete_local_ref(env, _runtime_versions); } -static void populate_user_data(JNIEnv *env, bugsnag_event *event) { - if (bsg_global_jni_cache == NULL) { +static void populate_user_data(JNIEnv *env, bsg_jni_cache *jni_cache, + bugsnag_event *event) { + if (jni_cache == NULL) { return; } jobject data = bsg_safe_call_static_object_method( - env, bsg_global_jni_cache->native_interface, - bsg_global_jni_cache->ni_get_user); + env, jni_cache->native_interface, jni_cache->ni_get_user); if (data == NULL) { return; } - copy_map_value_string(env, data, "id", event->user.id, + copy_map_value_string(env, jni_cache, data, "id", event->user.id, sizeof(event->user.id)); - copy_map_value_string(env, data, "name", event->user.name, + copy_map_value_string(env, jni_cache, data, "name", event->user.name, sizeof(event->user.name)); - copy_map_value_string(env, data, "email", event->user.email, + copy_map_value_string(env, jni_cache, data, "email", event->user.email, sizeof(event->user.email)); bsg_safe_delete_local_ref(env, data); } -static void populate_context(JNIEnv *env, bugsnag_event *event) { - if (bsg_global_jni_cache == NULL) { +static void populate_context(JNIEnv *env, bsg_jni_cache *jni_cache, + bugsnag_event *event) { + if (jni_cache == NULL) { return; } jstring _context = bsg_safe_call_static_object_method( - env, bsg_global_jni_cache->native_interface, - bsg_global_jni_cache->ni_get_context); + env, jni_cache->native_interface, jni_cache->ni_get_context); if (_context != NULL) { const char *value = bsg_safe_get_string_utf_chars(env, (jstring)_context); if (value != NULL) { @@ -337,26 +339,24 @@ static void populate_context(JNIEnv *env, bugsnag_event *event) { bsg_safe_delete_local_ref(env, _context); } -static void populate_metadata_value(JNIEnv *env, bugsnag_metadata *dst, - const char *section, const char *name, - jobject _value) { - if (bsg_global_jni_cache == NULL) { +static void populate_metadata_value(JNIEnv *env, bsg_jni_cache *jni_cache, + bugsnag_metadata *dst, const char *section, + const char *name, jobject _value) { + if (jni_cache == NULL) { return; } - if (bsg_safe_is_instance_of(env, _value, bsg_global_jni_cache->number)) { + if (bsg_safe_is_instance_of(env, _value, jni_cache->number)) { // add a double metadata value - double value = bsg_safe_call_double_method( - env, _value, bsg_global_jni_cache->number_double_value); + double value = bsg_safe_call_double_method(env, _value, + jni_cache->number_double_value); bsg_add_metadata_value_double(dst, section, name, value); - } else if (bsg_safe_is_instance_of(env, _value, - bsg_global_jni_cache->boolean)) { + } else if (bsg_safe_is_instance_of(env, _value, jni_cache->boolean)) { // add a boolean metadata value - bool value = bsg_safe_call_boolean_method( - env, _value, bsg_global_jni_cache->boolean_bool_value); + bool value = bsg_safe_call_boolean_method(env, _value, + jni_cache->boolean_bool_value); bsg_add_metadata_value_bool(dst, section, name, value); - } else if (bsg_safe_is_instance_of(env, _value, - bsg_global_jni_cache->string)) { + } else if (bsg_safe_is_instance_of(env, _value, jni_cache->string)) { const char *value = bsg_safe_get_string_utf_chars(env, _value); if (value != NULL) { bsg_add_metadata_value_str(dst, section, name, value); @@ -364,31 +364,31 @@ static void populate_metadata_value(JNIEnv *env, bugsnag_metadata *dst, } } -static void populate_metadata_obj(JNIEnv *env, bugsnag_metadata *dst, - jobject section, jobject section_keylist, - int index) { +static void populate_metadata_obj(JNIEnv *env, bsg_jni_cache *jni_cache, + bugsnag_metadata *dst, jobject section, + jobject section_keylist, int index) { jstring section_key = NULL; const char *name = NULL; jobject _value = NULL; - if (bsg_global_jni_cache == NULL) { + if (jni_cache == NULL) { goto exit; } section_key = bsg_safe_call_object_method( - env, section_keylist, bsg_global_jni_cache->arraylist_get, (jint)index); + env, section_keylist, jni_cache->arraylist_get, (jint)index); if (section_key == NULL) { goto exit; } - _value = bsg_safe_call_object_method( - env, section, bsg_global_jni_cache->map_get, section_key); + _value = bsg_safe_call_object_method(env, section, jni_cache->map_get, + section_key); name = bsg_safe_get_string_utf_chars(env, section_key); if (name == NULL) { goto exit; } - populate_metadata_value(env, dst, section, name, _value); + populate_metadata_value(env, jni_cache, dst, section, name, _value); exit: bsg_safe_release_string_utf_chars(env, section_key, name); @@ -396,17 +396,17 @@ static void populate_metadata_obj(JNIEnv *env, bugsnag_metadata *dst, bsg_safe_delete_local_ref(env, _value); } -static void populate_metadata_section(JNIEnv *env, bugsnag_metadata *dst, - jobject metadata, jobject keylist, - int i) { +static void populate_metadata_section(JNIEnv *env, bsg_jni_cache *jni_cache, + bugsnag_metadata *dst, jobject metadata, + jobject keylist, int i) { jstring _key = NULL; const char *section = NULL; jobject _section = NULL; jobject section_keyset = NULL; jobject section_keylist = NULL; - _key = bsg_safe_call_object_method( - env, keylist, bsg_global_jni_cache->arraylist_get, (jint)i); + _key = bsg_safe_call_object_method(env, keylist, jni_cache->arraylist_get, + (jint)i); if (_key == NULL) { goto exit; } @@ -414,30 +414,30 @@ static void populate_metadata_section(JNIEnv *env, bugsnag_metadata *dst, if (section == NULL) { goto exit; } - _section = bsg_safe_call_object_method(env, metadata, - bsg_global_jni_cache->map_get, _key); + _section = + bsg_safe_call_object_method(env, metadata, jni_cache->map_get, _key); if (_section == NULL) { goto exit; } jint section_size = - bsg_safe_call_int_method(env, _section, bsg_global_jni_cache->map_size); + bsg_safe_call_int_method(env, _section, jni_cache->map_size); if (section_size == -1) { goto exit; } - section_keyset = bsg_safe_call_object_method( - env, _section, bsg_global_jni_cache->map_key_set); + section_keyset = + bsg_safe_call_object_method(env, _section, jni_cache->map_key_set); if (section_keyset == NULL) { goto exit; } - section_keylist = bsg_safe_new_object( - env, bsg_global_jni_cache->arraylist, - bsg_global_jni_cache->arraylist_init_with_obj, section_keyset); + section_keylist = + bsg_safe_new_object(env, jni_cache->arraylist, + jni_cache->arraylist_init_with_obj, section_keyset); if (section_keylist == NULL) { goto exit; } for (int j = 0; j < section_size; j++) { - populate_metadata_obj(env, dst, _section, section_keylist, j); + populate_metadata_obj(env, jni_cache, dst, _section, section_keylist, j); } goto exit; @@ -451,19 +451,18 @@ static void populate_metadata_section(JNIEnv *env, bugsnag_metadata *dst, // Internal API -void bsg_populate_metadata(JNIEnv *env, bugsnag_metadata *dst, - jobject metadata) { +void bsg_populate_metadata(JNIEnv *env, bsg_jni_cache *jni_cache, + bugsnag_metadata *dst, jobject metadata) { jobject _metadata = NULL; jobject keyset = NULL; jobject keylist = NULL; - if (bsg_global_jni_cache == NULL) { + if (jni_cache == NULL) { goto exit; } if (metadata == NULL) { _metadata = bsg_safe_call_static_object_method( - env, bsg_global_jni_cache->native_interface, - bsg_global_jni_cache->ni_get_metadata); + env, jni_cache->native_interface, jni_cache->ni_get_metadata); metadata = _metadata; } @@ -472,27 +471,25 @@ void bsg_populate_metadata(JNIEnv *env, bugsnag_metadata *dst, goto exit; } - int size = - bsg_safe_call_int_method(env, metadata, bsg_global_jni_cache->map_size); + int size = bsg_safe_call_int_method(env, metadata, jni_cache->map_size); if (size == -1) { goto exit; } // create a list of metadata keys - keyset = bsg_safe_call_static_object_method( - env, metadata, bsg_global_jni_cache->map_key_set); + keyset = + bsg_safe_call_static_object_method(env, metadata, jni_cache->map_key_set); if (keyset == NULL) { goto exit; } - keylist = bsg_safe_new_object(env, bsg_global_jni_cache->arraylist, - bsg_global_jni_cache->arraylist_init_with_obj, - keyset); + keylist = bsg_safe_new_object(env, jni_cache->arraylist, + jni_cache->arraylist_init_with_obj, keyset); if (keylist == NULL) { goto exit; } for (int i = 0; i < size; i++) { - populate_metadata_section(env, dst, metadata, keylist, i); + populate_metadata_section(env, jni_cache, dst, metadata, keylist, i); } exit: @@ -501,48 +498,45 @@ void bsg_populate_metadata(JNIEnv *env, bugsnag_metadata *dst, bsg_safe_delete_local_ref(env, keylist); } -void bsg_populate_crumb_metadata(JNIEnv *env, bugsnag_breadcrumb *crumb, - jobject metadata) { +void bsg_populate_crumb_metadata(JNIEnv *env, bsg_jni_cache *jni_cache, + bugsnag_breadcrumb *crumb, jobject metadata) { jobject keyset = NULL; jobject keylist = NULL; if (metadata == NULL) { goto exit; } - if (bsg_global_jni_cache == NULL) { + if (jni_cache == NULL) { goto exit; } // get size of metadata map - jint map_size = - bsg_safe_call_int_method(env, metadata, bsg_global_jni_cache->map_size); + jint map_size = bsg_safe_call_int_method(env, metadata, jni_cache->map_size); if (map_size == -1) { goto exit; } // create a list of metadata keys - keyset = bsg_safe_call_object_method(env, metadata, - bsg_global_jni_cache->map_key_set); + keyset = bsg_safe_call_object_method(env, metadata, jni_cache->map_key_set); if (keyset == NULL) { goto exit; } - keylist = bsg_safe_new_object(env, bsg_global_jni_cache->arraylist, - bsg_global_jni_cache->arraylist_init_with_obj, - keyset); + keylist = bsg_safe_new_object(env, jni_cache->arraylist, + jni_cache->arraylist_init_with_obj, keyset); if (keylist == NULL) { goto exit; } for (int i = 0; i < map_size; i++) { jstring _key = bsg_safe_call_object_method( - env, keylist, bsg_global_jni_cache->arraylist_get, (jint)i); - jobject _value = bsg_safe_call_object_method( - env, metadata, bsg_global_jni_cache->map_get, _key); + env, keylist, jni_cache->arraylist_get, (jint)i); + jobject _value = + bsg_safe_call_object_method(env, metadata, jni_cache->map_get, _key); if (_key != NULL && _value != NULL) { const char *key = bsg_safe_get_string_utf_chars(env, _key); if (key != NULL) { - populate_metadata_value(env, &crumb->metadata, "metaData", key, _value); + populate_metadata_value(env, jni_cache, &crumb->metadata, "metaData", key, _value); bsg_safe_release_string_utf_chars(env, _key, key); } } @@ -555,14 +549,15 @@ void bsg_populate_crumb_metadata(JNIEnv *env, bugsnag_breadcrumb *crumb, bsg_safe_delete_local_ref(env, keylist); } -void bsg_populate_event(JNIEnv *env, bugsnag_event *event) { - if (bsg_global_jni_cache == NULL) { +void bsg_populate_event(JNIEnv *env, bsg_jni_cache *jni_cache, + bugsnag_event *event) { + if (jni_cache == NULL) { return; } - populate_context(env, event); - populate_app_data(env, event); - populate_device_data(env, event); - populate_user_data(env, event); + populate_context(env, jni_cache, event); + populate_app_data(env, jni_cache, event); + populate_device_data(env, jni_cache, event); + populate_user_data(env, jni_cache, event); } const char *bsg_os_name() { return "android"; } diff --git a/bugsnag-plugin-android-ndk/src/main/jni/metadata.h b/bugsnag-plugin-android-ndk/src/main/jni/metadata.h index de3e0e59d6..1625e165e8 100644 --- a/bugsnag-plugin-android-ndk/src/main/jni/metadata.h +++ b/bugsnag-plugin-android-ndk/src/main/jni/metadata.h @@ -2,25 +2,26 @@ #define BUGSNAG_METADATA_H #include "event.h" +#include "jni_cache.h" #include /** * Load all app, device, user, and custom metadata from NativeInterface into a * event */ -void bsg_populate_event(JNIEnv *env, bugsnag_event *event); +void bsg_populate_event(JNIEnv *env, bsg_jni_cache *jni_cache, bugsnag_event *event); /** * Load custom metadata from NativeInterface into a native metadata struct, * optionally from an object. If metadata is not provided, load from * NativeInterface */ -void bsg_populate_metadata(JNIEnv *env, bugsnag_metadata *dst, +void bsg_populate_metadata(JNIEnv *env, bsg_jni_cache *jni_cache, bugsnag_metadata *dst, jobject metadata); /** * Parse as java.util.Map to populate crumb metadata */ -void bsg_populate_crumb_metadata(JNIEnv *env, bugsnag_breadcrumb *crumb, +void bsg_populate_crumb_metadata(JNIEnv *env, bsg_jni_cache *jni_cache, bugsnag_breadcrumb *crumb, jobject metadata); const char *bsg_os_name();