Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions build-tools/create-packs/Microsoft.Android.Runtime.proj
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ projects that use the Microsoft.Android framework in .NET 6+.
Include="$(_MonoAndroidNETOutputRoot)$(AndroidLatestStableApiLevel)\Microsoft.Android.Runtime.NativeAOT.dll"
Condition=" '$(AndroidRuntime)' == 'NativeAOT' "
/>
<_AndroidRuntimePackAssemblies
Include="$(_MonoAndroidNETOutputRoot)$(AndroidLatestStableApiLevel)\System.IO.Hashing.dll"
Condition=" '$(AndroidRuntime)' == 'NativeAOT' "
/>
<_AndroidRuntimePackAssemblies Include="$(_MonoAndroidNETOutputRoot)$(AndroidLatestStableApiLevel)\Mono.Android.Export.dll" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,8 @@ partial class NativeAotTypeManager : JniRuntime.JniTypeManager {
internal const DynamicallyAccessedMemberTypes Methods = DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods;
internal const DynamicallyAccessedMemberTypes MethodsAndPrivateNested = Methods | DynamicallyAccessedMemberTypes.NonPublicNestedTypes;

readonly IDictionary<string, Type> TypeMappings = new Dictionary<string, Type> (StringComparer.Ordinal);

public NativeAotTypeManager ()
{
var startTicks = global::System.Environment.TickCount;
InitializeTypeMappings ();
var endTicks = global::System.Environment.TickCount;
AndroidLog.Print (AndroidLogLevel.Info, "NativeAotTypeManager", $"InitializeTypeMappings() took {endTicks - startTicks}ms");
}

void InitializeTypeMappings ()
{
// Should be replaced by src/Microsoft.Android.Sdk.ILLink/TypeMappingStep.cs
throw new InvalidOperationException ("TypeMappings should be replaced during trimming!");
}

[return: DynamicallyAccessedMembers (Constructors)]
Expand Down Expand Up @@ -139,7 +127,7 @@ public override void RegisterNativeMembers (

protected override IEnumerable<Type> GetTypesForSimpleReference (string jniSimpleReference)
{
if (TypeMappings.TryGetValue (jniSimpleReference, out var target)) {
if (TypeMapping.TryGetType (jniSimpleReference, out var target)) {
yield return target;
}
foreach (var t in base.GetTypesForSimpleReference (jniSimpleReference)) {
Expand All @@ -150,15 +138,7 @@ protected override IEnumerable<Type> GetTypesForSimpleReference (string jniSimpl
protected override IEnumerable<string> GetSimpleReferences (Type type)
{
return base.GetSimpleReferences (type)
.Concat (CreateSimpleReferencesEnumerator (type));
}

IEnumerable<string> CreateSimpleReferencesEnumerator (Type type)
{
foreach (var e in TypeMappings) {
if (e.Value == type)
yield return e.Key;
}
.Concat (TypeMapping.GetJavaClassNames (type));
}

static int CountMethods (ReadOnlySpan<char> methodsSpan)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO.Hashing;
using System.Runtime.InteropServices;
using System.Text;

using Android.Runtime;

namespace Microsoft.Android.Runtime;

internal static class TypeMapping
{
private static Dictionary<Type, string[]> s_javaClassNames = new ();

internal static bool TryGetType (string javaClassName, [NotNullWhen (true)] out Type? type)
{
ReadOnlySpan<byte> bytes = MemoryMarshal.AsBytes(javaClassName.AsSpan ());
ulong hash = XxHash3.HashToUInt64 (bytes);
type = GetType (hash);
return type is not null;
}

internal static IEnumerable<string> GetJavaClassNames (Type type)
{
if (!s_javaClassNames.TryGetValue (type, out var javaClassNames)) {
javaClassNames = GetJavaClassNamesSlow (type).ToArray ();
_ = s_javaClassNames.TryAdd (type, javaClassNames);
}

return javaClassNames;
}

private static IEnumerable<string> GetJavaClassNamesSlow (Type type)
{
for (int i = 0; i < Hashes.Length; i++) {
if (GetTypeByIndex (i) == type) {
var javaClassName = TypeMapping.GetJavaClassNameByIndex (i);
if (javaClassName is not null) {
yield return javaClassName;
}
}
}
}

private static Type? GetType (ulong hash)
{
int index = MemoryExtensions.BinarySearch (Hashes, hash);
if (index < 0) {
return null;
}

return GetTypeByIndex (index);
}

// Replaced by src/Microsoft.Android.Sdk.ILLink/TypeMappingStep.cs
private static ReadOnlySpan<ulong> Hashes => throw new NotImplementedException ();
private static Type? GetTypeByIndex (int index) => throw new NotImplementedException ();
private static string? GetJavaClassNameByIndex (int index) => throw new NotImplementedException ();
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
<ProjectReference Include="..\Mono.Android\Mono.Android.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="System.IO.Hashing" Version="$(SystemIOHashingPackageVersion)" />
</ItemGroup>

<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />

<!-- Copy runtime assemblies to bin/$(Configuration)/dotnet/packs folder -->
Expand All @@ -34,6 +38,7 @@
<Target Name="_CopyToPackDirs">
<ItemGroup>
<_RuntimePackFiles Include="$(OutputPath)Microsoft.Android.Runtime.NativeAOT.dll" AndroidRID="%(AndroidAbiAndRuntimeFlavor.AndroidRID)" AndroidRuntime="%(AndroidAbiAndRuntimeFlavor.AndroidRuntime)" />
<_RuntimePackFiles Include="$(OutputPath)System.IO.Hashing.dll" AndroidRID="%(AndroidAbiAndRuntimeFlavor.AndroidRID)" AndroidRuntime="%(AndroidAbiAndRuntimeFlavor.AndroidRuntime)" />
</ItemGroup>
<Message Importance="high" Text="$(TargetPath) %(AndroidAbiAndRuntimeFlavor.AndroidRID)" />
<Copy
Expand Down
Loading
Loading