From 4332ea03833c3d99be2eb935221580ad1b22ae77 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 11 Jan 2024 02:05:06 +0000
Subject: [PATCH 1/9] Bump external/Java.Interop from `8b85462` to `def5bc0`

Bumps [external/Java.Interop](https://github.com/xamarin/java.interop) from `8b85462` to `def5bc0`.
- [Commits](https://github.com/xamarin/java.interop/compare/8b85462e5f304d9aa2d91c02966d7dc9751516c7...def5bc0df68a5908fac85e5dd4f02f1e27c75882)

---
updated-dependencies:
- dependency-name: external/Java.Interop
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 external/Java.Interop | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/external/Java.Interop b/external/Java.Interop
index 8b85462e5f3..def5bc0df68 160000
--- a/external/Java.Interop
+++ b/external/Java.Interop
@@ -1 +1 @@
-Subproject commit 8b85462e5f304d9aa2d91c02966d7dc9751516c7
+Subproject commit def5bc0df68a5908fac85e5dd4f02f1e27c75882

From e192af69c18208f02afbbf649368d91dfcdb17d2 Mon Sep 17 00:00:00 2001
From: Jonathan Peppers <jonathan.peppers@microsoft.com>
Date: Tue, 23 Jan 2024 16:39:27 -0600
Subject: [PATCH 2/9] JavaTypeScanner processes all IJavaPeerable implementors

Context: https://github.com/xamarin/xamarin-android/pull/8625#issuecomment-1907027253
---
 src/Xamarin.Android.Build.Tasks/Utilities/XAJavaTypeScanner.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/XAJavaTypeScanner.cs b/src/Xamarin.Android.Build.Tasks/Utilities/XAJavaTypeScanner.cs
index 5f965ab46ff..fb9881fc6a8 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/XAJavaTypeScanner.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/XAJavaTypeScanner.cs
@@ -77,7 +77,7 @@ public List<JavaType> GetJavaTypes (ICollection<ITaskItem> inputAssemblies, XAAs
 
 	void AddJavaType (TypeDefinition type, Dictionary<string, TypeData> types, AndroidTargetArch arch)
 	{
-		if (type.IsSubclassOf ("Java.Lang.Object", cache) || type.IsSubclassOf ("Java.Lang.Throwable", cache) || (type.IsInterface && type.ImplementsInterface ("Java.Interop.IJavaPeerable", cache))) {
+		if (type.ImplementsInterface ("Java.Interop.IJavaPeerable", cache)) {
 			// For subclasses of e.g. Android.App.Activity.
 			string typeName = type.GetPartialAssemblyQualifiedName (cache);
 			if (!types.TryGetValue (typeName, out TypeData typeData)) {

From 8fcc2ad7fe0099b93a3ca19812f82911ead9c537 Mon Sep 17 00:00:00 2001
From: Jonathan Pryor <jonpryor@vt.edu>
Date: Tue, 23 Jan 2024 22:15:50 -0500
Subject: [PATCH 3/9] Try xamarin/java.interop#1181
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Context: https://github.com/xamarin/java.interop/pull/1181

Does It Build™?
---
 .gitmodules           | 2 +-
 external/Java.Interop | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.gitmodules b/.gitmodules
index c9883e88b80..7900eb9c650 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -9,7 +9,7 @@
 [submodule "external/Java.Interop"]
     path = external/Java.Interop
     url = https://github.com/xamarin/java.interop.git
-    branch = main
+    branch = dev/jonp/ji-typemap-support
 [submodule "external/lz4"]
     path = external/lz4
     url = https://github.com/xamarin/lz4
diff --git a/external/Java.Interop b/external/Java.Interop
index def5bc0df68..b9aa5f7102e 160000
--- a/external/Java.Interop
+++ b/external/Java.Interop
@@ -1 +1 @@
-Subproject commit def5bc0df68a5908fac85e5dd4f02f1e27c75882
+Subproject commit b9aa5f7102e4e36a4487e3739b8b341a8abd8514

From 9a7aee75bd44f4f7e72d04d5cc72b6666e6c9dea Mon Sep 17 00:00:00 2001
From: Marek Habersack <grendel@twistedcode.net>
Date: Thu, 25 Jan 2024 13:09:07 +0100
Subject: [PATCH 4/9] Attempt to fix assembly image load for typemap

This is for situations when, for any reason, Java is calling us before
any of the managed types involved in the mapping had the chance to be
loaded - that is, before their containing assembly has been loaded.

For most apps the overhead of this solution will be negligible (a single
`nullptr` check).
---
 src/monodroid/jni/embedded-assemblies.cc | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/src/monodroid/jni/embedded-assemblies.cc b/src/monodroid/jni/embedded-assemblies.cc
index 82b7607f437..c7f3f966c6d 100644
--- a/src/monodroid/jni/embedded-assemblies.cc
+++ b/src/monodroid/jni/embedded-assemblies.cc
@@ -695,6 +695,20 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java
 
 	if (module->image == nullptr) {
 		module->image = mono_image_loaded (module->assembly_name);
+
+		if (module->image == nullptr) {
+			log_debug (LOG_ASSEMBLY, "typemap: assembly '%s' hasn't been loaded yet, attempting a full load", module->assembly_name);
+
+			// Trigger MonoVM's machinery to load an image. This will involve calling us back to find, uncompress (if
+            // necessary) and load the assembly from whatever storage the app uses.
+			MonoImageOpenStatus status{};
+			module->image = mono_image_open (module->assembly_name, &status);
+
+			if (status != MonoImageOpenStatus::MONO_IMAGE_OK) {
+				log_warn (LOG_ASSEMBLY, "typemap: failed to load managed assembly image '%s'. %s", module->assembly_name, mono_image_strerror (status));
+			}
+		}
+
 		if (module->image == nullptr) {
 			log_error (LOG_ASSEMBLY, "typemap: unable to load assembly '%s' when looking up managed type corresponding to Java type '%s'", module->assembly_name, to_utf8 (java_type_name).get ());
 			return nullptr;

From 7b46391ecaf2ce7511b0a7e56af36a4f4b945e6d Mon Sep 17 00:00:00 2001
From: Marek Habersack <grendel@twistedcode.net>
Date: Thu, 25 Jan 2024 21:55:29 +0100
Subject: [PATCH 5/9] Take 2 to fix assembly load for typemap lookup

Context: 9a7aee75bd44f4f7e72d04d5cc72b6666e6c9dea
---
 src/monodroid/jni/embedded-assemblies.cc | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/monodroid/jni/embedded-assemblies.cc b/src/monodroid/jni/embedded-assemblies.cc
index c7f3f966c6d..632b40a87f4 100644
--- a/src/monodroid/jni/embedded-assemblies.cc
+++ b/src/monodroid/jni/embedded-assemblies.cc
@@ -701,11 +701,17 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java
 
 			// Trigger MonoVM's machinery to load an image. This will involve calling us back to find, uncompress (if
             // necessary) and load the assembly from whatever storage the app uses.
+			dynamic_local_string<SENSIBLE_PATH_MAX> assembly_name;
+			assembly_name.assign_c (module->assembly_name);
+			assembly_name.append (SharedConstants::DLL_EXTENSION);
+
 			MonoImageOpenStatus status{};
-			module->image = mono_image_open (module->assembly_name, &status);
+			MonoAssembly *assm = mono_assembly_open (assembly_name.get (), &status);
 
 			if (status != MonoImageOpenStatus::MONO_IMAGE_OK) {
-				log_warn (LOG_ASSEMBLY, "typemap: failed to load managed assembly image '%s'. %s", module->assembly_name, mono_image_strerror (status));
+				log_warn (LOG_ASSEMBLY, "typemap: failed to load managed assembly '%s'. %s", assembly_name.get (), mono_image_strerror (status));
+			} else {
+				module->image = mono_assembly_get_image (assm);
 			}
 		}
 

From b4ca587dbd17bbd99b754f36e1be7dbd07f7e938 Mon Sep 17 00:00:00 2001
From: Jonathan Pryor <jonpryor@vt.edu>
Date: Fri, 26 Jan 2024 13:43:07 -0500
Subject: [PATCH 6/9] Audit JNIEnv::GetObjectClass() invocations
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Context: https://github.com/xamarin/java.interop/pull/1181/commits/6b3637dda089e455ebf0077ecebd0f57fe2875de

The story so far is that some of our unit tests are crashing, and
have been in one form or another since 4332ea03
(the bump to xamarin/java.interop@def5bc0).

The current crash, from the PR build for 7b46391e:

	D monodroid-assembly: typemap: assembly 'Java.Interop-Tests' hasn't been loaded yet, attempting a full load
	W monodroid-assembly: typemap: failed to load managed assembly 'Java.Interop-Tests.dll'. No such file or directory
	E monodroid-assembly: typemap: unable to load assembly 'Java.Interop-Tests' when looking up managed type corresponding to Java type 'java/lang/Object'
	I monodroid-timing: [1/5] Typemap.java_to_managed: end, total time; elapsed: 0:0::260000
	W monodroid-assembly: typemap: called from
	W monodroid-assembly: at Java.Interop.TypeManager.GetJavaToManagedType(String )
	W monodroid-assembly:    at Java.Interop.TypeManager.CreateInstance(IntPtr , JniHandleOwnership , Type )
	W monodroid-assembly:    at Java.Lang.Object.GetObject(IntPtr , JniHandleOwnership , Type )
	W monodroid-assembly:    at Java.Lang.Object._GetObject[IIterator](IntPtr , JniHandleOwnership )
	W monodroid-assembly:    at Java.Lang.Object.GetObject[IIterator](IntPtr handle, JniHandleOwnership transfer)
	W monodroid-assembly:    at Android.Runtime.JavaSet.Iterator()
	W monodroid-assembly:    at Android.Runtime.JavaSet`1[[System.String, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetEnumerator()
	W monodroid-assembly:    at Xamarin.Android.UnitTests.TestInstrumentation`1[[Xamarin.Android.UnitTests.NUnit.NUnitTestRunner, TestRunner.NUnit.NET, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].ProcessArguments()
	W monodroid-assembly:    at Xamarin.Android.UnitTests.TestInstrumentation`1[[Xamarin.Android.UnitTests.NUnit.NUnitTestRunner, TestRunner.NUnit.NET, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].OnCreate(Bundle arguments)
	W monodroid-assembly:    at Android.App.Instrumentation.n_OnCreate_Landroid_os_Bundle_(IntPtr jnienv, IntPtr native__this, IntPtr native_arguments)
	W monodroid-assembly:    at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPL_V(_JniMarshal_PPL_V callback, IntPtr jnienv, IntPtr klazz, IntPtr p0)
	E droid.NET_Test: JNI ERROR (app bug): accessed stale Local 0x75  (index 7 in a table of size 7)
	F droid.NET_Test: java_vm_ext.cc:570] JNI DETECTED ERROR IN APPLICATION: use of deleted local reference 0x75

There are *three* "concerning" items here:

 1. typemaps are trying to load `Java.Interop-Tests`, and failing:

        typemap: failed to load managed assembly 'Java.Interop-Tests.dll'. No such file or directory

    @grendello is looking into this.

 2. The binding for `java/lang/Object` is coming from
    Java.Interop-Tests, not Mono.Android (?!)

        typemap: unable to load assembly 'Java.Interop-Tests' when looking up managed type corresponding to Java type 'java/lang/Object'

    xamarin/java.interop#1181 has a fix for this, and we're not
    applying the fix yet because we believe that it will hide (1).

 3. The JNI error, which crashes the process:

        F droid.NET_Test: java_vm_ext.cc:570] JNI DETECTED ERROR IN APPLICATION: use of deleted local reference 0x75
        F droid.NET_Test: java_vm_ext.cc:570]     from void crc643df67da7b13bb6b1.TestInstrumentation_1.n_onCreate(android.os.Bundle)
        F droid.NET_Test: runtime.cc:630] Runtime aborting...
        F droid.NET_Test: runtime.cc:630] Dumping all threads without mutator lock held
        F droid.NET_Test: runtime.cc:630] All threads:
        F droid.NET_Test: runtime.cc:630] DALVIK THREADS (14):
        F droid.NET_Test: runtime.cc:630] "main" prio=5 tid=1 Runnable
        F droid.NET_Test: runtime.cc:630]   | group="" sCount=0 dsCount=0 flags=0 obj=0x729e9d98 self=0x7567e0f51000
        F droid.NET_Test: runtime.cc:630]   | sysTid=9143 nice=0 cgrp=default sched=0/0 handle=0x7567e14daed8
        F droid.NET_Test: runtime.cc:630]   | state=R schedstat=( 1270418000 334229000 139 ) utm=16 stm=110 core=0 HZ=100
        F droid.NET_Test: runtime.cc:630]   | stack=0x7ffcbb3e4000-0x7ffcbb3e6000 stackSize=8192KB
        F droid.NET_Test: runtime.cc:630]   | held mutexes= "abort lock" "mutator lock"(shared held)
        F droid.NET_Test: runtime.cc:630]   native: #00 pc 000000000048df4e  /apex/com.android.runtime/lib64/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, int, BacktraceMap*, char const*, art::ArtMethod*, void*, bool)+126)
        F droid.NET_Test: runtime.cc:630]   native: #01 pc 00000000005a77c3  /apex/com.android.runtime/lib64/libart.so (art::Thread::DumpStack(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, bool, BacktraceMap*, bool) const+675)
        F droid.NET_Test: runtime.cc:630]   native: #02 pc 00000000005c49cb  /apex/com.android.runtime/lib64/libart.so (art::DumpCheckpoint::Run(art::Thread*)+859)
        F droid.NET_Test: runtime.cc:630]   native: #03 pc 00000000005bcf28  /apex/com.android.runtime/lib64/libart.so (art::ThreadList::RunCheckpoint(art::Closure*, art::Closure*)+456)
        F droid.NET_Test: runtime.cc:630]   native: #04 pc 00000000005bc2e1  /apex/com.android.runtime/lib64/libart.so (art::ThreadList::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, bool)+1601)
        F droid.NET_Test: runtime.cc:630]   native: #05 pc 0000000000552eb9  /apex/com.android.runtime/lib64/libart.so (art::Runtime::Abort(char const*)+1529)
        F droid.NET_Test: runtime.cc:630]   native: #06 pc 000000000000c873  /system/lib64/libbase.so (android::base::LogMessage::~LogMessage()+611)
        F droid.NET_Test: runtime.cc:630]   native: #07 pc 00000000003ede84  /apex/com.android.runtime/lib64/libart.so (art::JavaVMExt::JniAbort(char const*, char const*)+1604)
        F droid.NET_Test: runtime.cc:630]   native: #08 pc 00000000003ee18a  /apex/com.android.runtime/lib64/libart.so (art::JavaVMExt::JniAbortF(char const*, char const*, ...)+234)
        F droid.NET_Test: runtime.cc:630]   native: #09 pc 00000000005adf31  /apex/com.android.runtime/lib64/libart.so (art::Thread::DecodeJObject(_jobject*) const+785)
        F droid.NET_Test: runtime.cc:630]   native: #10 pc 00000000003def9b  /apex/com.android.runtime/lib64/libart.so (art::(anonymous namespace)::ScopedCheck::CheckInstance(art::ScopedObjectAccess&, art::(anonymous namespace)::ScopedCheck::InstanceKind, _jobject*, bool)+91)
        F droid.NET_Test: runtime.cc:630]   native: #11 pc 00000000003de205  /apex/com.android.runtime/lib64/libart.so (art::(anonymous namespace)::ScopedCheck::CheckPossibleHeapValue(art::ScopedObjectAccess&, char, art::(anonymous namespace)::JniValueType)+485)
        F droid.NET_Test: runtime.cc:630]   native: #12 pc 00000000003dd732  /apex/com.android.runtime/lib64/libart.so (art::(anonymous namespace)::ScopedCheck::Check(art::ScopedObjectAccess&, bool, char const*, art::(anonymous namespace)::JniValueType*)+690)
        F droid.NET_Test: runtime.cc:630]   native: #13 pc 00000000003ce865  /apex/com.android.runtime/lib64/libart.so (art::(anonymous namespace)::CheckJNI::GetObjectClass(_JNIEnv*, _jobject*)+837)
        F droid.NET_Test: runtime.cc:630]   native: #14 pc 0000000000017196  /data/app/Mono.Android.NET_Tests-LUUW792fOvX745oAS4jeRQ==/split_config.x86_64.apk (offset 331000) (???)
        F droid.NET_Test: runtime.cc:630]   at crc643df67da7b13bb6b1.TestInstrumentation_1.n_onCreate(Native method)

As per `native #13`, we're (somehow) passing an invalid JNI reference
to `JNIEnv::GetObjectClass()`.

***HOW*** are we passing an invalid JNI reference to
`JNIEnv::GetObjectClass()`?

Attempt to investigate (3) further, by:

 1. Reviewing all calls to `JNIEnv::GetObjectClass()` within this
    repo to see if we could potentially be passing an invalid value.
    The "most obvious" candidate is `TypeManager.CreateInstance()`,
    which calls `JNIEnv::GetObjectClass()` in a loop.

    I'm still not sure if that could possibly be the cause, but
    Just In Case™…

    "Cleanup" some C++ code so that calls to
    `JNIEnv::DeleteLocalReference()` are closer to the
    `JNIEnv::GetObjectClass()` calls.

 2. Update
    `tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Mono.Android.NET-Tests.csproj`
    to add an `@(AndroidEnvironment)` item, which sets
    `debug.mono.log=gref+,lref+`.  This will enable LREF and GREF
    logging within `adb logcat`, which *may* allow us to track down
    where "local reference 0x75" came from.
---
 src/Mono.Android/Java.Interop/TypeManager.cs    | 17 ++++++++++++++---
 src/monodroid/jni/osbridge.cc                   |  9 +++------
 .../Environment.txt                             |  1 +
 .../Mono.Android.NET-Tests.csproj               |  4 ++++
 4 files changed, 22 insertions(+), 9 deletions(-)
 create mode 100644 tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Environment.txt

diff --git a/src/Mono.Android/Java.Interop/TypeManager.cs b/src/Mono.Android/Java.Interop/TypeManager.cs
index 3b900017db2..0425bfab304 100644
--- a/src/Mono.Android/Java.Interop/TypeManager.cs
+++ b/src/Mono.Android/Java.Interop/TypeManager.cs
@@ -265,9 +265,14 @@ internal static IJavaPeerable CreateInstance (IntPtr handle, JniHandleOwnership
 		[UnconditionalSuppressMessage ("Trimming", "IL2072", Justification = "TypeManager.CreateProxy() does not statically know the value of the 'type' local variable.")]
 		internal static IJavaPeerable CreateInstance (IntPtr handle, JniHandleOwnership transfer, Type? targetType)
 		{
+			if (handle == IntPtr.Zero) {
+				throw new NotSupportedException (
+						FormattableString.Invariant ($"Internal error: `handle` is NULL!"),
+						CreateJavaLocationException ());
+			}
 			Type? type = null;
 			IntPtr class_ptr = JNIEnv.GetObjectClass (handle);
-			string class_name = GetClassName (class_ptr);
+			string? class_name = GetClassName (class_ptr);
 			lock (TypeManagerMapDictionaries.AccessLock) {
 				while (class_ptr != IntPtr.Zero && !TypeManagerMapDictionaries.JniToManaged.TryGetValue (class_name, out type)) {
 
@@ -279,12 +284,18 @@ internal static IJavaPeerable CreateInstance (IntPtr handle, JniHandleOwnership
 
 					IntPtr super_class_ptr = JNIEnv.GetSuperclass (class_ptr);
 					JNIEnv.DeleteLocalRef (class_ptr);
+					class_name = null;
 					class_ptr = super_class_ptr;
-					class_name = GetClassName (class_ptr);
+					if (class_ptr != IntPtr.Zero) {
+						class_name = GetClassName (class_ptr);
+					}
 				}
 			}
 
-			JNIEnv.DeleteLocalRef (class_ptr);
+			if (class_ptr != IntPtr.Zero) {
+				JNIEnv.DeleteLocalRef (class_ptr);
+				class_ptr = IntPtr.Zero;
+			}
 
 			if (type == null) {
 				JNIEnv.DeleteRef (handle, transfer);
diff --git a/src/monodroid/jni/osbridge.cc b/src/monodroid/jni/osbridge.cc
index 067e9019da4..f7ca9467243 100644
--- a/src/monodroid/jni/osbridge.cc
+++ b/src/monodroid/jni/osbridge.cc
@@ -657,15 +657,13 @@ OSBridge::add_reference_jobject (JNIEnv *env, jobject handle, jobject reffed_han
 
 	java_class = env->GetObjectClass (handle);
 	add_method_id = env->GetMethodID (java_class, "monodroidAddReference", "(Ljava/lang/Object;)V");
+	env->DeleteLocalRef (java_class);
 	if (add_method_id) {
 		env->CallVoidMethod (handle, add_method_id, reffed_handle);
-		env->DeleteLocalRef (java_class);
-
 		return 1;
 	}
 
 	env->ExceptionClear ();
-	env->DeleteLocalRef (java_class);
 	return 0;
 }
 
@@ -910,7 +908,6 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri
 	MonoClass *klass;
 #endif
 	MonoObject *obj;
-	jclass java_class;
 	jobject jref;
 	jmethodID clear_method_id;
 	int i, j, total, alive, refs_added;
@@ -942,8 +939,9 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri
 				sccs [i]->is_alive = 1;
 				mono_field_get_value (obj, bridge_info->refs_added, &refs_added);
 				if (refs_added) {
-					java_class = env->GetObjectClass (jref);
+					jclass java_class = env->GetObjectClass (jref);
 					clear_method_id = env->GetMethodID (java_class, "monodroidClearReferences", "()V");
+					env->DeleteLocalRef (java_class);
 					if (clear_method_id) {
 						env->CallVoidMethod (jref, clear_method_id);
 					} else {
@@ -957,7 +955,6 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri
 						}
 #endif
 					}
-					env->DeleteLocalRef (java_class);
 				}
 			} else {
 				abort_unless (!sccs [i]->is_alive, "Bridge SCC at index %d must NOT be alive", i);
diff --git a/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Environment.txt b/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Environment.txt
new file mode 100644
index 00000000000..f545be1ea24
--- /dev/null
+++ b/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Environment.txt
@@ -0,0 +1 @@
+debug.mono.log=lref+,gref+
diff --git a/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Mono.Android.NET-Tests.csproj b/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Mono.Android.NET-Tests.csproj
index f21c94de80f..f9a77b78ad0 100644
--- a/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Mono.Android.NET-Tests.csproj
+++ b/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Mono.Android.NET-Tests.csproj
@@ -50,6 +50,10 @@
     <Compile Remove="..\Mono.Data.Sqlite\SqliteTests.cs" />
   </ItemGroup>
 
+  <ItemGroup>
+    <AndroidEnvironment Include="Environment.txt" />
+  </ItemGroup>
+
   <ItemGroup Condition=" '$(AndroidPackageFormat)' != 'aab' ">
     <TestApk Include="$(OutputPath)$(_MonoAndroidTestPackage)-Signed.apk">
       <Package>$(_MonoAndroidTestPackage)</Package>

From cde4e7186236d12d30d6cae2056a8a3a6da67818 Mon Sep 17 00:00:00 2001
From: Marek Habersack <grendel@twistedcode.net>
Date: Mon, 29 Jan 2024 12:20:21 +0100
Subject: [PATCH 7/9] Take 3 to fix assembly load for typemap lookup

Context: 9a7aee75bd44f4f7e72d04d5cc72b6666e6c9dea
Context: 7b46391ecaf2ce7511b0a7e56af36a4f4b945e6d

Fake a MonoVM hook to try to load the assembly.
---
 src/monodroid/jni/embedded-assemblies.cc | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/src/monodroid/jni/embedded-assemblies.cc b/src/monodroid/jni/embedded-assemblies.cc
index 632b40a87f4..ac6fddfd36b 100644
--- a/src/monodroid/jni/embedded-assemblies.cc
+++ b/src/monodroid/jni/embedded-assemblies.cc
@@ -699,17 +699,21 @@ EmbeddedAssemblies::typemap_java_to_managed (hash_t hash, const MonoString *java
 		if (module->image == nullptr) {
 			log_debug (LOG_ASSEMBLY, "typemap: assembly '%s' hasn't been loaded yet, attempting a full load", module->assembly_name);
 
-			// Trigger MonoVM's machinery to load an image. This will involve calling us back to find, uncompress (if
-            // necessary) and load the assembly from whatever storage the app uses.
-			dynamic_local_string<SENSIBLE_PATH_MAX> assembly_name;
-			assembly_name.assign_c (module->assembly_name);
-			assembly_name.append (SharedConstants::DLL_EXTENSION);
+			// Fake a request from MonoVM to load the assembly.
+			MonoAssemblyName *assembly_name = mono_assembly_name_new (module->assembly_name);
+			MonoAssembly *assm;
 
-			MonoImageOpenStatus status{};
-			MonoAssembly *assm = mono_assembly_open (assembly_name.get (), &status);
+			if (assembly_name == nullptr) {
+				log_error (LOG_ASSEMBLY, "typemap: failed to create Mono assembly name for '%s'", module->assembly_name);
+				assm = nullptr;
+			} else {
+				MonoAssemblyLoadContextGCHandle alc_gchandle = mono_alc_get_default_gchandle ();
+				MonoError mono_error;
+				assm = embeddedAssemblies.open_from_bundles (assembly_name, alc_gchandle, &mono_error, false /* ref_only */);
+			}
 
-			if (status != MonoImageOpenStatus::MONO_IMAGE_OK) {
-				log_warn (LOG_ASSEMBLY, "typemap: failed to load managed assembly '%s'. %s", assembly_name.get (), mono_image_strerror (status));
+			if (assm == nullptr) {
+				log_warn (LOG_ASSEMBLY, "typemap: failed to load managed assembly '%s'", module->assembly_name);
 			} else {
 				module->image = mono_assembly_get_image (assm);
 			}

From d500a1983db707dcbc5cc47e5448477dde4d98f7 Mon Sep 17 00:00:00 2001
From: Jonathan Pryor <jonpryor@vt.edu>
Date: Fri, 2 Feb 2024 13:01:09 -0500
Subject: [PATCH 8/9] =?UTF-8?q?Back=20to=20java.interop/main=E2=80=A6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

PR #8681 was merged, which fixed the Java.Interop bump issues.
---
 .gitmodules | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitmodules b/.gitmodules
index 7900eb9c650..c9883e88b80 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -9,7 +9,7 @@
 [submodule "external/Java.Interop"]
     path = external/Java.Interop
     url = https://github.com/xamarin/java.interop.git
-    branch = dev/jonp/ji-typemap-support
+    branch = main
 [submodule "external/lz4"]
     path = external/lz4
     url = https://github.com/xamarin/lz4

From a9dd3c5511b037ef4817bc35d272c8889505b168 Mon Sep 17 00:00:00 2001
From: Jonathan Pryor <jonpryor@vt.edu>
Date: Fri, 2 Feb 2024 13:15:04 -0500
Subject: [PATCH 9/9] Cleanup.

---
 src/Mono.Android/Java.Interop/TypeManager.cs                 | 5 -----
 .../Runtime-Microsoft.Android.Sdk/Environment.txt            | 1 -
 .../Mono.Android.NET-Tests.csproj                            | 4 ----
 3 files changed, 10 deletions(-)
 delete mode 100644 tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Environment.txt

diff --git a/src/Mono.Android/Java.Interop/TypeManager.cs b/src/Mono.Android/Java.Interop/TypeManager.cs
index 1b6e0562e4f..c0993e1a9d9 100644
--- a/src/Mono.Android/Java.Interop/TypeManager.cs
+++ b/src/Mono.Android/Java.Interop/TypeManager.cs
@@ -265,11 +265,6 @@ internal static IJavaPeerable CreateInstance (IntPtr handle, JniHandleOwnership
 		[UnconditionalSuppressMessage ("Trimming", "IL2072", Justification = "TypeManager.CreateProxy() does not statically know the value of the 'type' local variable.")]
 		internal static IJavaPeerable CreateInstance (IntPtr handle, JniHandleOwnership transfer, Type? targetType)
 		{
-			if (handle == IntPtr.Zero) {
-				throw new NotSupportedException (
-						FormattableString.Invariant ($"Internal error: `handle` is NULL!"),
-						CreateJavaLocationException ());
-			}
 			Type? type = null;
 			IntPtr class_ptr = JNIEnv.GetObjectClass (handle);
 			string? class_name = GetClassName (class_ptr);
diff --git a/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Environment.txt b/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Environment.txt
deleted file mode 100644
index f545be1ea24..00000000000
--- a/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Environment.txt
+++ /dev/null
@@ -1 +0,0 @@
-debug.mono.log=lref+,gref+
diff --git a/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Mono.Android.NET-Tests.csproj b/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Mono.Android.NET-Tests.csproj
index f9a77b78ad0..f21c94de80f 100644
--- a/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Mono.Android.NET-Tests.csproj
+++ b/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Mono.Android.NET-Tests.csproj
@@ -50,10 +50,6 @@
     <Compile Remove="..\Mono.Data.Sqlite\SqliteTests.cs" />
   </ItemGroup>
 
-  <ItemGroup>
-    <AndroidEnvironment Include="Environment.txt" />
-  </ItemGroup>
-
   <ItemGroup Condition=" '$(AndroidPackageFormat)' != 'aab' ">
     <TestApk Include="$(OutputPath)$(_MonoAndroidTestPackage)-Signed.apk">
       <Package>$(_MonoAndroidTestPackage)</Package>
