Skip to content

Commit

Permalink
[Java.Interop.Tools.TypeNameMappings] fix ToJniName() (dotnet#1198)
Browse files Browse the repository at this point in the history
Context: dotnet/android#8751
Context: 56b7eeb
Context: 67c079c

dotnet/android#8751 attempts to figure out how Java.Interop
broke xamarin-android.  That investigation eventually resulted in
67c079c, which allowed xamarin-android to *build* again, and
uncovered a unit test failure.

[`JnienvTest.NewObjectArrayWithNonJavaTypeAndEmptyArray()`][0]:

	[Test]
	public void NewObjectArrayWithNonJavaTypeAndEmptyArray ()
	{
	    //empty array gives the right type
	    var array = JNIEnv.NewObjectArray<Type> (new Type [0]);
	    …
	}

started failing:

	Java.Lang.ClassNotFoundException : crc64d04135c992393d83.Type
	----> Java.Lang.ClassNotFoundException : Didn't find class "crc64d04135c992393d83.Type" on path: DexPathList[[zip file "/data/app/Mono.Android.NET_Tests-VrfrXDHT2r32zDG95kFOiw==/base.apk", zip file "/data/app/Mono.Android.NET_Tests-VrfrXDHT2r32zDG95kFOiw==/split_config.x86_64.apk", zip file "/data/app/Mono.Android.NET_Tests-VrfrXDHT2r32zDG95kFOiw==/split_config.xxhdpi.apk"],nativeLibraryDirectories=[/data/app/Mono.Android.NET_Tests-VrfrXDHT2r32zDG95kFOiw==/lib/x86_64, /data/app/Mono.Android.NET_Tests-VrfrXDHT2r32zDG95kFOiw==/base.apk!/lib/x86_64, /data/app/Mono.Android.NET_Tests-VrfrXDHT2r32zDG95kFOiw==/split_config.x86_64.apk!/lib/x86_64, /data/app/Mono.Android.NET_Tests-VrfrXDHT2r32zDG95kFOiw==/split_config.xxhdpi.apk!/lib/x86_64, /system/lib64, /system/product/lib64]]

It turns out, this type is completely wrong?  It should be looking
for `java/lang/Object` instead?

In 56b7eeb, we lost an important detail from the expression:

	// 56b7eeb^
	if (!type.GetInterfaces ().Any (t => t.FullName == "Android.Runtime.IJavaObject")) …

	// 56b7eeb equivalent:
	if (type.GetInterfaces ().Any (t => t.FullName == "Java.Interop.IJavaPeerable")) …

We are missing the `!` !!!

I was able to reproduce this behavior in a test:

	[Test]
	[TestCase (typeof (System.Type), "java/lang/Object")]
	public void ToJniName (Type type, string expected)
	{
	    string actual = JavaNativeTypeManager.ToJniName (type);
	    Assert.AreEqual (expected, actual);
	}

Where `ToJniName()` was returning `crc64d04135c992393d83/Type` instead
of `java/lang/Object`!

After fixing the problem, the test passes.

[0]: https://github.com/xamarin/xamarin-android/blob/0665f449948c43675ec8706a5a2807b5d3f599f7/tests/Mono.Android-Tests/Java.Interop/JnienvTest.cs#L178-L186
  • Loading branch information
jonathanpeppers authored Feb 24, 2024
1 parent 67c079c commit bd793f1
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,9 @@ public static string ToJniName (Type type)
// Trimming warnings are not enabled for netstandard2.0 in this project.
static bool ShouldCheckSpecialExportJniType (Type type) =>
#if NETSTANDARD2_0
type.GetInterfaces ().Any (t => t.FullName == "Java.Interop.IJavaPeerable");
!type.GetInterfaces ().Any (t => t.FullName == "Java.Interop.IJavaPeerable");
#else
IJavaPeerableType.Value.IsAssignableFrom (type);
!IJavaPeerableType.Value.IsAssignableFrom (type);
#endif

public static string ToJniName (string jniType, int rank)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,14 @@ public void LowercaseWithAssemblyName ()
Assert.AreEqual ("assembly_mscorlib.system", JavaNativeTypeManager.GetPackageName (typeof (string)));
#endif // !NET
}

[Test]
[TestCase (typeof (string), "java/lang/String")]
[TestCase (typeof (Type), "java/lang/Object")]
public void ToJniName (Type type, string expected)
{
string actual = JavaNativeTypeManager.ToJniName (type);
Assert.AreEqual (expected, actual);
}
}
}

0 comments on commit bd793f1

Please sign in to comment.