Skip to content

Commit 9121bea

Browse files
[Xamarin.Android.Build.Tasks] make "managed typemap" runtime agnostic (#9911)
Context: 684ede6 Context: b11471b For NativeAOT, we implemented a "managed" typemap that is trimmer-safe; see 684ede6 and b11471b. In order to test its performance characteristics, make this typemap useable for Mono and CoreCLR as well: * Move `NativeAotTypeManager`, `NativeAotValueManager`, and `TypeMapping` types to `Mono.Android.dll` * Rename `NativeAot*` types to `Managed*` * Add a new private `$(_AndroidTypeMapImplementation)` MSBuild property that can be set to `llvm-ir` or `managed`. * Add a new trimmer feature flag `Microsoft.Android.Runtime.RuntimeFeature.ManagedTypeMap`; when `true` uses the managed typemap on any runtime. I added a test that verifies `dotnet run` succeeds for all typemap implementations. Note that NativeAOT will *only* support the managed typemap. Update `JNIEnvInit.RegisterJniNatives()` to *not* require that `androidRuntime.TypeManager` be an `AndroidTypeManager`; this allows `ManagedTypeManager` to be used on MonoVM and CoreCLR.
1 parent 0d4f223 commit 9121bea

File tree

20 files changed

+92
-41
lines changed

20 files changed

+92
-41
lines changed

build-tools/create-packs/Microsoft.Android.Runtime.proj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ projects that use the Microsoft.Android framework in .NET 6+.
4646
/>
4747
<_AndroidRuntimePackAssemblies
4848
Include="$(_MonoAndroidNETOutputRoot)$(AndroidLatestStableApiLevel)\System.IO.Hashing.dll"
49-
Condition=" '$(AndroidRuntime)' == 'NativeAOT' "
5049
NoSymbols="true"
5150
/>
5251
<_AndroidRuntimePackAssemblies Include="$(_MonoAndroidNETOutputRoot)$(AndroidLatestStableApiLevel)\Mono.Android.Export.dll" />

src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/JavaInteropRuntime.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ static void init (IntPtr jnienv, IntPtr klass)
3737
var settings = new DiagnosticSettings ();
3838
settings.AddDebugDotnetLog ();
3939

40-
var typeManager = new NativeAotTypeManager ();
40+
var typeManager = new ManagedTypeManager ();
4141
var options = new NativeAotRuntimeOptions {
4242
EnvironmentPointer = jnienv,
4343
TypeManager = typeManager,

src/Microsoft.Android.Runtime.NativeAOT/Java.Interop/JreRuntime.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ static NativeAotRuntimeOptions CreateJreVM (NativeAotRuntimeOptions builder)
5858
throw new InvalidOperationException ($"Member `{nameof (NativeAotRuntimeOptions)}.{nameof (NativeAotRuntimeOptions.JvmLibraryPath)}` must be set.");
5959

6060
#if NET
61-
builder.TypeManager ??= new NativeAotTypeManager ();
61+
builder.TypeManager ??= new ManagedTypeManager ();
6262
#endif // NET
6363

6464
builder.ValueManager ??= new ManagedValueManager ();

src/Microsoft.Android.Runtime.NativeAOT/Microsoft.Android.Runtime.NativeAOT.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
<Target Name="_CopyToPackDirs">
3939
<ItemGroup>
4040
<_RuntimePackFiles Include="$(OutputPath)Microsoft.Android.Runtime.NativeAOT.dll" AndroidRID="%(AndroidAbiAndRuntimeFlavor.AndroidRID)" AndroidRuntime="%(AndroidAbiAndRuntimeFlavor.AndroidRuntime)" />
41-
<_RuntimePackFiles Include="$(OutputPath)System.IO.Hashing.dll" AndroidRID="%(AndroidAbiAndRuntimeFlavor.AndroidRID)" AndroidRuntime="%(AndroidAbiAndRuntimeFlavor.AndroidRuntime)" />
4241
</ItemGroup>
4342
<Message Importance="high" Text="$(TargetPath) %(AndroidAbiAndRuntimeFlavor.AndroidRID)" />
4443
<Copy

src/Microsoft.Android.Sdk.ILLink/TypeMappingStep.cs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ namespace Microsoft.Android.Sdk.ILLink;
1919
/// </summary>
2020
public class TypeMappingStep : BaseStep
2121
{
22-
const string AssemblyName = "Microsoft.Android.Runtime.NativeAOT";
23-
const string TypeName = "Microsoft.Android.Runtime.TypeMapping";
22+
const string AssemblyName = "Mono.Android";
23+
const string TypeName = "Microsoft.Android.Runtime.ManagedTypeMapping";
2424
const string SystemIOHashingAssemblyPathCustomData = "SystemIOHashingAssemblyPath";
2525
readonly IDictionary<string, List<TypeDefinition>> TypeMappings = new Dictionary<string, List<TypeDefinition>> (StringComparer.Ordinal);
26-
AssemblyDefinition? MicrosoftAndroidRuntimeNativeAot;
26+
AssemblyDefinition? MonoAndroidAssembly;
2727

2828
delegate ulong HashMethod (ReadOnlySpan<byte> data, long seed = 0);
2929
HashMethod? _hashMethod;
@@ -36,8 +36,7 @@ protected override void Process ()
3636
protected override void ProcessAssembly (AssemblyDefinition assembly)
3737
{
3838
if (assembly.Name.Name == AssemblyName) {
39-
MicrosoftAndroidRuntimeNativeAot = assembly;
40-
return;
39+
MonoAndroidAssembly = assembly;
4140
}
4241
if (Annotations?.GetAction (assembly) == AssemblyAction.Delete)
4342
return;
@@ -51,11 +50,11 @@ protected override void EndProcess ()
5150
{
5251
Context.LogMessage ($"Writing {TypeMappings.Count} typemap entries");
5352

54-
if (MicrosoftAndroidRuntimeNativeAot is null) {
53+
if (MonoAndroidAssembly is null) {
5554
throw new InvalidOperationException ($"Unable to find {AssemblyName} assembly");
5655
}
5756

58-
var module = MicrosoftAndroidRuntimeNativeAot.MainModule;
57+
var module = MonoAndroidAssembly.MainModule;
5958
var type = module.GetType (TypeName);
6059
if (type is null) {
6160
throw new InvalidOperationException ($"Unable to find {TypeName} type");

src/Mono.Android/Android.Runtime/AndroidRuntime.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ class AndroidRuntime : JniRuntime {
2323
internal AndroidRuntime (IntPtr jnienv,
2424
IntPtr vm,
2525
IntPtr classLoader,
26-
JniRuntime.JniTypeManager? typeManager,
27-
JniRuntime.JniValueManager? valueManager,
26+
JniRuntime.JniTypeManager typeManager,
27+
JniRuntime.JniValueManager valueManager,
2828
bool jniAddNativeMethodRegistrationAttributePresent)
2929
: base (new AndroidRuntimeOptions (jnienv,
3030
vm,
@@ -95,16 +95,16 @@ class AndroidRuntimeOptions : JniRuntime.CreationOptions {
9595
public AndroidRuntimeOptions (IntPtr jnienv,
9696
IntPtr vm,
9797
IntPtr classLoader,
98-
JniRuntime.JniTypeManager? typeManager,
99-
JniRuntime.JniValueManager? valueManager,
98+
JniRuntime.JniTypeManager typeManager,
99+
JniRuntime.JniValueManager valueManager,
100100
bool jniAddNativeMethodRegistrationAttributePresent)
101101
{
102102
EnvironmentPointer = jnienv;
103103
ClassLoader = new JniObjectReference (classLoader, JniObjectReferenceType.Global);
104104
InvocationPointer = vm;
105105
ObjectReferenceManager = new AndroidObjectReferenceManager ();
106-
TypeManager = typeManager ?? new AndroidTypeManager (jniAddNativeMethodRegistrationAttributePresent);
107-
ValueManager = valueManager ?? new AndroidValueManager ();
106+
TypeManager = typeManager;
107+
ValueManager = valueManager;
108108
UseMarshalMemberBuilder = false;
109109
JniAddNativeMethodRegistrationAttributePresent = jniAddNativeMethodRegistrationAttributePresent;
110110
}
@@ -512,7 +512,7 @@ public override void RegisterNativeMembers (
512512
[UnconditionalSuppressMessage ("Trimming", "IL2057", Justification = "Type.GetType() can never statically know the string value parsed from parameter 'methods'.")]
513513
[UnconditionalSuppressMessage ("Trimming", "IL2067", Justification = "Delegate.CreateDelegate() can never statically know the string value parsed from parameter 'methods'.")]
514514
[UnconditionalSuppressMessage ("Trimming", "IL2072", Justification = "Delegate.CreateDelegate() can never statically know the string value parsed from parameter 'methods'.")]
515-
public void RegisterNativeMembers (
515+
public override void RegisterNativeMembers (
516516
JniType nativeClass,
517517
[DynamicallyAccessedMembers (MethodsAndPrivateNested)] Type type,
518518
ReadOnlySpan<char> methods)

src/Mono.Android/Android.Runtime/JNIEnvInit.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Java.Interop.Tools.TypeNameMappings;
1010

1111
using Microsoft.Android.Runtime;
12+
using RuntimeFeature = Microsoft.Android.Runtime.RuntimeFeature;
1213

1314
namespace Android.Runtime
1415
{
@@ -79,7 +80,7 @@ static Type TypeGetType (string typeName) =>
7980
JniType.GetCachedJniType (ref jniType, className);
8081

8182
ReadOnlySpan<char> methods = new ReadOnlySpan<char> ((void*) methods_ptr, methods_len);
82-
((AndroidTypeManager)androidRuntime!.TypeManager).RegisterNativeMembers (jniType, type, methods);
83+
androidRuntime!.TypeManager.RegisterNativeMembers (jniType, type, methods);
8384
}
8485

8586
// NOTE: should have different name than `Initialize` to avoid:
@@ -110,12 +111,21 @@ internal static unsafe void Initialize (JnienvInitializeArgs* args)
110111
java_class_loader = args->grefLoader;
111112

112113
BoundExceptionType = (BoundExceptionType)args->ioExceptionType;
114+
JniRuntime.JniTypeManager typeManager;
115+
JniRuntime.JniValueManager valueManager;
116+
if (RuntimeFeature.ManagedTypeMap) {
117+
typeManager = new ManagedTypeManager ();
118+
valueManager = new ManagedValueManager ();
119+
} else {
120+
typeManager = new AndroidTypeManager (args->jniAddNativeMethodRegistrationAttributePresent != 0);
121+
valueManager = RuntimeType == DotNetRuntimeType.MonoVM ? new AndroidValueManager () : new ManagedValueManager ();
122+
}
113123
androidRuntime = new AndroidRuntime (
114124
args->env,
115125
args->javaVm,
116126
args->grefLoader,
117-
null,
118-
RuntimeType != DotNetRuntimeType.MonoVM ? new ManagedValueManager () : null,
127+
typeManager,
128+
valueManager,
119129
args->jniAddNativeMethodRegistrationAttributePresent != 0
120130
);
121131
ValueManager = androidRuntime.ValueManager;

src/Mono.Android/ILLink/ILLink.Substitutions.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,9 @@
44
<method signature="System.Boolean get_NegotiateAuthenticationIsEnabled()" body="stub" feature="Xamarin.Android.Net.UseNegotiateAuthentication" featurevalue="false" value="false" />
55
<method signature="System.Boolean get_NegotiateAuthenticationIsEnabled()" body="stub" feature="Xamarin.Android.Net.UseNegotiateAuthentication" featurevalue="true" value="true" />
66
</type>
7+
<type fullname="Microsoft.Android.Runtime.RuntimeFeature">
8+
<method signature="System.Boolean get_ManagedTypeMap()" body="stub" feature="Microsoft.Android.Runtime.RuntimeFeature.ManagedTypeMap" featurevalue="false" value="false" />
9+
<method signature="System.Boolean get_ManagedTypeMap()" body="stub" feature="Microsoft.Android.Runtime.RuntimeFeature.ManagedTypeMap" featurevalue="true" value="true" />
10+
</type>
711
</assembly>
812
</linker>
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1+
using System;
2+
using System.Collections.Generic;
13
using System.Diagnostics.CodeAnalysis;
24
using System.Reflection;
35
using Java.Interop;
46
using Java.Interop.Tools.TypeNameMappings;
57

68
namespace Microsoft.Android.Runtime;
79

8-
partial class NativeAotTypeManager : JniRuntime.JniTypeManager {
10+
class ManagedTypeManager : JniRuntime.JniTypeManager {
911

1012
const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
1113
internal const DynamicallyAccessedMemberTypes Methods = DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods;
1214
internal const DynamicallyAccessedMemberTypes MethodsAndPrivateNested = Methods | DynamicallyAccessedMemberTypes.NonPublicNestedTypes;
1315

14-
public NativeAotTypeManager ()
16+
public ManagedTypeManager ()
1517
{
1618
}
1719

@@ -127,7 +129,7 @@ public override void RegisterNativeMembers (
127129

128130
protected override IEnumerable<Type> GetTypesForSimpleReference (string jniSimpleReference)
129131
{
130-
if (TypeMapping.TryGetType (jniSimpleReference, out var target)) {
132+
if (ManagedTypeMapping.TryGetType (jniSimpleReference, out var target)) {
131133
yield return target;
132134
}
133135
foreach (var t in base.GetTypesForSimpleReference (jniSimpleReference)) {
@@ -141,7 +143,7 @@ protected override IEnumerable<string> GetSimpleReferences (Type type)
141143
yield return r;
142144
}
143145

144-
if (TypeMapping.TryGetJniName (type, out var jniName)) {
146+
if (ManagedTypeMapping.TryGetJniName (type, out var jniName)) {
145147
yield return jniName;
146148
}
147149
}

src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/TypeMapping.cs renamed to src/Mono.Android/Microsoft.Android.Runtime/ManagedTypeMapping.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Buffers.Binary;
23
using System.Diagnostics;
34
using System.Diagnostics.CodeAnalysis;
@@ -8,7 +9,7 @@
89

910
namespace Microsoft.Android.Runtime;
1011

11-
internal static class TypeMapping
12+
internal static class ManagedTypeMapping
1213
{
1314
internal static bool TryGetType (string jniName, [NotNullWhen (true)] out Type? type)
1415
{

0 commit comments

Comments
 (0)