diff --git a/src/Mono.Android/Android.App/Application.cs b/src/Mono.Android/Android.App/Application.cs index e7fca8d2190..ae4a144452d 100644 --- a/src/Mono.Android/Android.App/Application.cs +++ b/src/Mono.Android/Android.App/Application.cs @@ -14,14 +14,11 @@ public static Context Context { if (_context != null) return _context; - IntPtr klass = JNIEnv.FindClass ("mono/MonoPackageManager"); - try { - IntPtr field = JNIEnv.GetStaticFieldID (klass, "Context", "Landroid/content/Context;"); - IntPtr lref = JNIEnv.GetStaticObjectField (klass, field); - return _context = Java.Lang.Object.GetObject (lref, JniHandleOwnership.TransferLocalRef)!; - } finally { - JNIEnv.DeleteGlobalRef (klass); - } + var gref = JNIEnvInit.applicationContext; + if (gref == IntPtr.Zero) + throw new InvalidOperationException ("JNIEnvInit.applicationContext is not set!"); + + return _context = Java.Lang.Object.GetObject (gref, JniHandleOwnership.TransferGlobalRef)!; } } diff --git a/src/Mono.Android/Android.Runtime/JNIEnvInit.cs b/src/Mono.Android/Android.Runtime/JNIEnvInit.cs index 2499b693cf2..f70c9ecbbcc 100644 --- a/src/Mono.Android/Android.Runtime/JNIEnvInit.cs +++ b/src/Mono.Android/Android.Runtime/JNIEnvInit.cs @@ -32,6 +32,7 @@ internal struct JnienvInitializeArgs { public bool jniRemappingInUse; public bool marshalMethodsEnabled; public IntPtr grefGCUserPeerable; + public IntPtr applicationContext; } #pragma warning restore 0649 @@ -45,6 +46,7 @@ internal struct JnienvInitializeArgs { internal static IntPtr grefIGCUserPeer_class; internal static IntPtr grefGCUserPeerable_class; internal static IntPtr java_class_loader; + internal static IntPtr applicationContext; internal static JniRuntime? androidRuntime; @@ -117,6 +119,7 @@ internal static unsafe void Initialize (JnienvInitializeArgs* args) } } + applicationContext = JNIEnv.NewGlobalRef (args->applicationContext); SetSynchronizationContext (); } diff --git a/src/java-runtime/java/mono/android/MonoPackageManager.java b/src/java-runtime/java/mono/android/MonoPackageManager.java index 0955d55c8db..09f609a925a 100644 --- a/src/java-runtime/java/mono/android/MonoPackageManager.java +++ b/src/java-runtime/java/mono/android/MonoPackageManager.java @@ -24,8 +24,6 @@ public class MonoPackageManager { static Object lock = new Object (); static boolean initialized; - static android.content.Context Context; - public static void LoadApplication (Context context) { synchronized (lock) { @@ -40,9 +38,6 @@ public static void LoadApplication (Context context) apks = new String[] { runtimePackage.sourceDir }; } - if (context instanceof android.app.Application) { - Context = context; - } if (!initialized) { android.content.IntentFilter timezoneChangedFilter = new android.content.IntentFilter ( android.content.Intent.ACTION_TIMEZONE_CHANGED @@ -126,7 +121,8 @@ public static void LoadApplication (Context context) loader, MonoPackageManager_Resources.Assemblies, isEmulator (), - haveSplitApks + haveSplitApks, + context ); net.dot.android.ApplicationRegistration.registerApplications (); diff --git a/src/java-runtime/java/mono/android/Runtime.java b/src/java-runtime/java/mono/android/Runtime.java index 8ad03b1a2c5..1af1799146d 100644 --- a/src/java-runtime/java/mono/android/Runtime.java +++ b/src/java-runtime/java/mono/android/Runtime.java @@ -25,7 +25,8 @@ public static native void initInternal ( ClassLoader loader, String[] assemblies, boolean isEmulator, - boolean haveSplitApks + boolean haveSplitApks, + android.content.Context context ); public static native void register (String managedType, java.lang.Class nativeClass, String methods); public static native void notifyTimeZoneChanged (); diff --git a/src/native/mono/monodroid/mono_android_Runtime.h b/src/native/mono/monodroid/mono_android_Runtime.h index 663a02a9b4f..f3024db2847 100644 --- a/src/native/mono/monodroid/mono_android_Runtime.h +++ b/src/native/mono/monodroid/mono_android_Runtime.h @@ -21,7 +21,7 @@ JNIEXPORT void JNICALL Java_mono_android_Runtime_init * Signature: (Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;ILjava/lang/ClassLoader;[Ljava/lang/String;IZZ)V */ JNIEXPORT void JNICALL Java_mono_android_Runtime_initInternal - (JNIEnv *, jclass, jstring, jobjectArray, jstring, jobjectArray, jint, jobject, jobjectArray, jboolean, jboolean); + (JNIEnv *, jclass, jstring, jobjectArray, jstring, jobjectArray, jint, jobject, jobjectArray, jboolean, jboolean, jobject); /* * Class: mono_android_Runtime diff --git a/src/native/mono/monodroid/monodroid-glue-internal.hh b/src/native/mono/monodroid/monodroid-glue-internal.hh index 36c9206e36d..f2bac1335fc 100644 --- a/src/native/mono/monodroid/monodroid-glue-internal.hh +++ b/src/native/mono/monodroid/monodroid-glue-internal.hh @@ -101,6 +101,7 @@ namespace xamarin::android::internal bool jniRemappingInUse; bool marshalMethodsEnabled; jobject grefGCUserPeerable; + jobject applicationContext; }; using jnienv_initialize_fn = void (*) (JnienvInitializeArgs*); @@ -119,7 +120,7 @@ namespace xamarin::android::internal static void Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, jobjectArray runtimeApksJava, jstring runtimeNativeLibDir, jobjectArray appDirs, jint localDateTimeOffset, jobject loader, jobjectArray assembliesJava, jboolean isEmulator, - jboolean haveSplitApks) noexcept; + jboolean haveSplitApks, jobject context) noexcept; static jint Java_JNI_OnLoad (JavaVM *vm, void *reserved) noexcept; @@ -185,7 +186,7 @@ namespace xamarin::android::internal static void set_debug_options () noexcept; static void parse_gdb_options () noexcept; static void mono_runtime_init (JNIEnv *env, dynamic_local_string& runtime_args) noexcept; - static void init_android_runtime (JNIEnv *env, jclass runtimeClass, jobject loader) noexcept; + static void init_android_runtime (JNIEnv *env, jclass runtimeClass, jobject loader, jobject context) noexcept; static void set_environment_variable_for_directory (const char *name, jstring_wrapper &value, bool createDirectory, mode_t mode) noexcept; static void set_environment_variable_for_directory (const char *name, jstring_wrapper &value) noexcept @@ -205,7 +206,7 @@ namespace xamarin::android::internal static MonoDomain* create_and_initialize_domain (JNIEnv* env, jclass runtimeClass, jstring_array_wrapper &runtimeApks, jstring_array_wrapper &assemblies, jobjectArray assembliesBytes, jstring_array_wrapper &assembliesPaths, jobject loader, bool is_root_domain, bool force_preload_assemblies, - bool have_split_apks) noexcept; + bool have_split_apks, jobject context) noexcept; static void gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, size_t *out_user_assemblies_count, bool have_split_apks) noexcept; static bool should_register_file (const char *filename); diff --git a/src/native/mono/monodroid/monodroid-glue.cc b/src/native/mono/monodroid/monodroid-glue.cc index ebb72718c57..35ccb16e5d2 100644 --- a/src/native/mono/monodroid/monodroid-glue.cc +++ b/src/native/mono/monodroid/monodroid-glue.cc @@ -816,7 +816,7 @@ MonodroidRuntime::monodroid_debugger_unhandled_exception (MonoException *ex) } void -MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobject loader) noexcept +MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobject loader, jobject context) noexcept { constexpr std::string_view icall_typemap_java_to_managed { "Java.Interop.TypeManager::monodroid_typemap_java_to_managed" }; constexpr std::string_view icall_typemap_managed_to_java { "Android.Runtime.JNIEnv::monodroid_typemap_managed_to_java" }; @@ -849,6 +849,7 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec init.jniAddNativeMethodRegistrationAttributePresent = application_config.jni_add_native_method_registration_attribute_present ? 1 : 0; init.jniRemappingInUse = application_config.jni_remapping_replacement_type_count > 0 || application_config.jni_remapping_replacement_method_index_entry_count > 0; init.marshalMethodsEnabled = application_config.marshal_methods_enabled; + init.applicationContext = context; java_System = RuntimeUtil::get_class_from_runtime_field (env, runtimeClass, "java_lang_System", true); java_System_identityHashCode = env->GetStaticMethodID (java_System, "identityHashCode", "(Ljava/lang/Object;)I"); @@ -1253,7 +1254,7 @@ MonoDomain* MonodroidRuntime::create_and_initialize_domain (JNIEnv* env, jclass runtimeClass, jstring_array_wrapper &runtimeApks, jstring_array_wrapper &assemblies, [[maybe_unused]] jobjectArray assembliesBytes, [[maybe_unused]] jstring_array_wrapper &assembliesPaths, jobject loader, bool is_root_domain, - bool force_preload_assemblies, bool have_split_apks) noexcept + bool force_preload_assemblies, bool have_split_apks, jobject context) noexcept { MonoDomain* domain = create_domain (env, runtimeApks, is_root_domain, have_split_apks); // Asserting this on desktop apparently breaks a Designer test @@ -1275,7 +1276,7 @@ MonodroidRuntime::create_and_initialize_domain (JNIEnv* env, jclass runtimeClass bool preload = (AndroidSystem::is_assembly_preload_enabled () || (is_running_on_desktop && force_preload_assemblies)); load_assemblies (default_alc, preload, assemblies); - init_android_runtime (env, runtimeClass, loader); + init_android_runtime (env, runtimeClass, loader, context); osBridge.add_monodroid_domain (domain); return domain; @@ -1386,7 +1387,7 @@ inline void MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, jobjectArray runtimeApksJava, jstring runtimeNativeLibDir, jobjectArray appDirs, jint localDateTimeOffset, jobject loader, jobjectArray assembliesJava, jboolean isEmulator, - jboolean haveSplitApks) noexcept + jboolean haveSplitApks, jobject context) noexcept { char *mono_log_mask_raw = nullptr; char *mono_log_level_raw = nullptr; @@ -1522,7 +1523,7 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl jstring_array_wrapper assemblies (env, assembliesJava); jstring_array_wrapper assembliesPaths (env); /* the first assembly is used to initialize the AppDomain name */ - create_and_initialize_domain (env, klass, runtimeApks, assemblies, nullptr, assembliesPaths, loader, /*is_root_domain:*/ true, /*force_preload_assemblies:*/ false, haveSplitApks); + create_and_initialize_domain (env, klass, runtimeApks, assemblies, nullptr, assembliesPaths, loader, /*is_root_domain:*/ true, /*force_preload_assemblies:*/ false, haveSplitApks, context); // Install our dummy exception handler on Desktop if constexpr (is_running_on_desktop) { @@ -1581,7 +1582,8 @@ Java_mono_android_Runtime_init (JNIEnv *env, jclass klass, jstring lang, jobject loader, assembliesJava, /* isEmulator */ JNI_FALSE, - /* haveSplitApks */ JNI_FALSE + /* haveSplitApks */ JNI_FALSE, + /* context */ nullptr ); } @@ -1589,7 +1591,7 @@ JNIEXPORT void JNICALL Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, jobjectArray runtimeApksJava, jstring runtimeNativeLibDir, jobjectArray appDirs, jint localDateTimeOffset, jobject loader, jobjectArray assembliesJava, jboolean isEmulator, - jboolean haveSplitApks) + jboolean haveSplitApks, jobject context) { MonodroidRuntime::Java_mono_android_Runtime_initInternal ( env, @@ -1602,7 +1604,8 @@ Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, loader, assembliesJava, isEmulator, - application_config.ignore_split_configs ? false : haveSplitApks + application_config.ignore_split_configs ? false : haveSplitApks, + context ); }