Skip to content

Commit

Permalink
[Mono.Android] Make TypeManager a normal Java.Lang.Object (#1537)
Browse files Browse the repository at this point in the history
Context: https://github.com/xamarin/xamarin-android/projects/1

The idea: use `jnimarshalmethod-gen.exe` to generate
*JNI Marshal Methods* at packaging time, so that we can avoid using
as much reflection for method registration, and *entirely avoid*
using `System.Reflection.Emit` for marshal method registration.

The problem: The Java type `mono.android.TypeManager` is Just Like
every other `Java.Lang.Object` C# subclass, in that it's a Java
`native` method that is registered with a C# delegate via
`JNIEnv.RegisterJniNatives()`.

*Unlike* every other `Java.Lang.Object` subclass, it wasn't actually
a `Java.Lang.Object` subclass. It Just Happened To Work because it
`JNIEnv.RegisterJniNatives()` used Reflection to find the
registration methods/etc., but it was otherwise "unique".

Being unique was fine, but in our desired new
`jnimarshalmethod-gen.exe` World Order™, being unique *isn't* fine;
it means it won't participate in packaging-time marshal method
generation, thus requiring use of `System.Reflection.Emit`, which
is undesirable.

Add a new internal `Java.Interop.TypeManager.JavaTypeManager` type to
use as the C# peer for `mono.android.TypeManager`, make
`TypeManager.JavaTypeManager` a normal `Java.Lang.Object` subclass,
then update `mono.android.TypeManager` to register
`Java.Interop.TypeManager+JavaTypeManager`. This removes the
"uniqueness" of `mono.android.TypeManager`, allowing it to be
processed normally by `jnimarshalmethod-gen.exe`.
  • Loading branch information
radekdoulik authored and jonpryor committed Apr 11, 2018
1 parent 648aff9 commit 0140ab8
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 1 deletion.
15 changes: 15 additions & 0 deletions src/Mono.Android/Java.Interop/TypeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -358,5 +358,20 @@ public static void RegisterPackages (string[] packages, Converter<string, Type>[
}
}
}

[Register ("mono/android/TypeManager", DoNotGenerateAcw = true)]
internal class JavaTypeManager : Java.Lang.Object
{
[Register ("activate", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;[Ljava/lang/Object;)V", "")]
static void n_Activate (IntPtr jnienv, IntPtr jclass, IntPtr typename_ptr, IntPtr signature_ptr, IntPtr jobject, IntPtr parameters_ptr)
{
TypeManager.n_Activate (jnienv, jclass, typename_ptr, signature_ptr, jobject, parameters_ptr);
}

internal static Delegate GetActivateHandler ()
{
return TypeManager.GetActivateHandler ();
}
}
}
}
2 changes: 1 addition & 1 deletion src/Mono.Android/java/mono/android/TypeManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ public static void Activate (String typeName, String sig, Object instance, Objec
String methods =
"n_activate:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;[Ljava/lang/Object;)V:GetActivateHandler\n" +
"";
mono.android.Runtime.register ("Java.Interop.TypeManager, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", TypeManager.class, methods);
mono.android.Runtime.register ("Java.Interop.TypeManager+JavaTypeManager, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", TypeManager.class, methods);
}
}

0 comments on commit 0140ab8

Please sign in to comment.