Skip to content

New code to perform managed <-> java lookups (typemap) #3992

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions Documentation/guides/messages/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ ms.date: 01/24/2020
+ [XA4305](xa4305.md): MultiDex is enabled, but '{nameof (MultiDexMainDexListFile)}' was not specified.
+ [XA4306](xa4306.md): R8 does not support \`@(MultiDexMainDexList)\` files when android:minSdkVersion >= 21
+ [XA4307](xa4307.md): Invalid ProGuard configuration file.
+ [XA4308](xa4308.md): Failed to generate type maps

## XA5xxx: GCC and toolchain

Expand Down
18 changes: 18 additions & 0 deletions Documentation/guides/messages/xa4308.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
title: Xamarin.Android error XA4308
description: XA4308 error code
ms.date: 02/07/2020
---
# Xamarin.Android error XA4308

## Issue

The `GenerateJavaStubs` task was unable to generate type maps. Detailed diagnostic will be found before this
error in the build log.

## Solution

Consider submitting a [bug][bug] if you are getting this warning under
normal circumstances.

[bug]: https://github.com/xamarin/xamarin-android/wiki/Submitting-Bugs,-Feature-Requests,-and-Pull-Requests
50 changes: 32 additions & 18 deletions build-tools/xaprepare/xaprepare/Steps/Step_DownloadMonoArchive.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,26 +60,39 @@ async Task<bool> DownloadMonoArchive (Context context)
localPath = Path.Combine (context.Properties.GetRequiredValue (KnownProperties.AndroidToolchainCacheDirectory), archiveFileName);
}

bool result = await DownloadAndUpackIfNeeded (
context,
"Mono",
context.MonoArchiveCustomUrl,
localPath,
archiveFileName,
Configurables.Paths.MonoSDKSOutputDir
);
bool result = false;
for (uint i = 0; i < 3; i++) {
result = await DownloadAndUpackIfNeeded (
context,
"Mono",
context.MonoArchiveCustomUrl,
localPath,
archiveFileName,
Configurables.Paths.MonoSDKSOutputDir
);

if (result)
break;
}

if (!result)
return false;

return await DownloadAndUpackIfNeeded (
context,
"Windows Mono",
customUrl: null,
localPath: Configurables.Paths.MonoArchiveWindowsLocalPath,
archiveFileName: Configurables.Paths.MonoArchiveWindowsFileName,
destinationDirectory: Configurables.Paths.BCLWindowsOutputDir
);
for (uint i = 0; i < 3; i++) {
result = await DownloadAndUpackIfNeeded (
context,
"Windows Mono",
customUrl: null,
localPath: Configurables.Paths.MonoArchiveWindowsLocalPath,
archiveFileName: Configurables.Paths.MonoArchiveWindowsFileName,
destinationDirectory: Configurables.Paths.BCLWindowsOutputDir
);

if (result)
break;
}

return result;
}

async Task<bool> DownloadAndUpackIfNeeded (Context context, string name, string customUrl, string localPath, string archiveFileName, string destinationDirectory)
Expand Down Expand Up @@ -109,7 +122,7 @@ async Task<bool> DownloadAndUpackIfNeeded (Context context, string name, string
await Download (context, url, localPath, $"{name} Archive", archiveFileName, downloadStatus);

if (!File.Exists (localPath)) {
Log.InfoLine ($"Download of {name} archive from {url} failed, Mono will be rebuilt");
Log.InfoLine ($"Download of {name} archive from {url} failed");
return false;
}
}
Expand All @@ -118,7 +131,8 @@ async Task<bool> DownloadAndUpackIfNeeded (Context context, string name, string
if (!await Utilities.Unpack (localPath, tempDir, cleanDestinatioBeforeUnpacking: true)) {
Utilities.DeleteFileSilent (localPath);
Utilities.DeleteDirectorySilent (destinationDirectory);
Log.WarningLine ($"Failed to unpack {name} archive {localPath}, Mono will be rebuilt");
Log.WarningLine ($"Failed to unpack {name} archive {localPath}");
Utilities.DeleteFileSilent (localPath);
return false;
}

Expand Down
12 changes: 6 additions & 6 deletions src/Mono.Android/Android.Runtime/AndroidRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,9 @@ protected override IEnumerable<Type> GetTypesForSimpleReference (string jniSimpl

protected override string GetSimpleReference (Type type)
{
var j = JNIEnv.monodroid_typemap_managed_to_java (type.FullName + ", " + type.Assembly.GetName ().Name);
if (j != IntPtr.Zero) {
return Marshal.PtrToStringAnsi (j);
string j = JNIEnv.TypemapManagedToJava (type);
if (j != null) {
return j;
}
if (JNIEnv.IsRunningOnDesktop) {
return JavaNativeTypeManager.ToJniName (type);
Expand All @@ -243,9 +243,9 @@ protected override string GetSimpleReference (Type type)

protected override IEnumerable<string> GetSimpleReferences (Type type)
{
var j = JNIEnv.monodroid_typemap_managed_to_java (type.FullName + ", " + type.Assembly.GetName ().Name);
if (j != IntPtr.Zero) {
yield return Marshal.PtrToStringAnsi (j);
string j = JNIEnv.TypemapManagedToJava (type);
if (j != null) {
yield return j;
}
if (JNIEnv.IsRunningOnDesktop) {
yield return JavaNativeTypeManager.ToJniName (type);
Expand Down
53 changes: 49 additions & 4 deletions src/Mono.Android/Android.Runtime/JNIEnv.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,14 @@ public static partial class JNIEnv {
static UncaughtExceptionHandler defaultUncaughtExceptionHandler;

internal static bool IsRunningOnDesktop;
internal static bool LogTypemapMissStackTrace;

static AndroidRuntime androidRuntime;
static BoundExceptionType BoundExceptionType;

[ThreadStatic]
static byte[] mvid_bytes;

internal static AndroidValueManager AndroidValueManager;

[DllImport ("__Internal", CallingConvention = CallingConvention.Cdecl)]
Expand Down Expand Up @@ -146,6 +150,8 @@ internal static unsafe void Initialize (JnienvInitializeArgs* args)
partial_timing_sequence = monodroid_timing_start (null);
}

LogTypemapMissStackTrace = (args->logCategories & (uint)LogCategories.Assembly) != 0;

gref_gc_threshold = args->grefGcThreshold;

java_vm = args->javaVm;
Expand Down Expand Up @@ -632,16 +638,55 @@ public static string GetClassNameFromInstance (IntPtr jobject)
}

[DllImport ("__Internal", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr monodroid_typemap_managed_to_java (string managed);
static extern IntPtr monodroid_typemap_managed_to_java (byte[] mvid, int token);

internal static void LogTypemapTrace (StackTrace st)
{
string trace = st.ToString ()?.Trim ();
if (String.IsNullOrEmpty (trace))
return;

monodroid_log (LogLevel.Warn, LogCategories.Assembly, "typemap: called from");
foreach (string line in trace.Split ('\n')) {
monodroid_log (LogLevel.Warn, LogCategories.Assembly, line);
}
}

internal static string TypemapManagedToJava (Type type)
{
if (mvid_bytes == null)
mvid_bytes = new byte[16];

Span<byte> mvid = new Span<byte>(mvid_bytes);
byte[] mvid_slow = null;
if (!type.Module.ModuleVersionId.TryWriteBytes (mvid)) {
monodroid_log (LogLevel.Warn, LogCategories.Default, $"Failed to obtain module MVID using the fast method, falling back to the slow one");
mvid_slow = type.Module.ModuleVersionId.ToByteArray ();
}

IntPtr ret = monodroid_typemap_managed_to_java (mvid_slow == null ? mvid_bytes : mvid_slow, type.MetadataToken);

if (ret == IntPtr.Zero) {
if (LogTypemapMissStackTrace) {
monodroid_log (LogLevel.Warn, LogCategories.Default, $"typemap: failed to map managed type to Java type: {type.AssemblyQualifiedName} (Module ID: {type.Module.ModuleVersionId}; Type token: {type.MetadataToken})");
LogTypemapTrace (new StackTrace (true));
}

return null;
}

return Marshal.PtrToStringAnsi (ret);
}

public static string GetJniName (Type type)
{
if (type == null)
throw new ArgumentNullException ("type");
var java = monodroid_typemap_managed_to_java (type.FullName + ", " + type.Assembly.GetName ().Name);
return java == IntPtr.Zero

string java = TypemapManagedToJava (type);
return java == null
? JavaNativeTypeManager.ToJniName (type)
: Marshal.PtrToStringAnsi (java);
: java;
}

public static IntPtr ToJniHandle (IJavaObject value)
Expand Down
16 changes: 10 additions & 6 deletions src/Mono.Android/Java.Interop/TypeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Java.Interop.Tools.TypeNameMappings;

Expand Down Expand Up @@ -203,22 +204,25 @@ static Exception CreateJavaLocationException ()
return new JavaLocationException (loc.ToString ());
}

[DllImport ("__Internal", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr monodroid_typemap_java_to_managed (string java);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
static extern Type monodroid_typemap_java_to_managed (string java_type_name);

internal static Type GetJavaToManagedType (string class_name)
{
var t = monodroid_typemap_java_to_managed (class_name);
if (t != IntPtr.Zero)
return Type.GetType (Marshal.PtrToStringAnsi (t));
Type type = monodroid_typemap_java_to_managed (class_name);
if (type != null)
return type;

if (!JNIEnv.IsRunningOnDesktop) {
// Miss message is logged in the native runtime
if (JNIEnv.LogTypemapMissStackTrace)
JNIEnv.LogTypemapTrace (new System.Diagnostics.StackTrace (true));
return null;
}

__TypeRegistrations.RegisterPackages ();

var type = (Type) null;
type = null;
int ls = class_name.LastIndexOf ('/');
var package = ls >= 0 ? class_name.Substring (0, ls) : "";
List<Converter<string, Type>> mappers;
Expand Down
4 changes: 4 additions & 0 deletions src/Mono.Android/Properties/AssemblyInfo.cs.in
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@ using System.Runtime.CompilerServices;
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Drawing.Size))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Drawing.SizeF))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Drawing.SystemColors))]
[assembly: InternalsVisibleTo("Mono.Android-Tests, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
[assembly: InternalsVisibleTo("Java.Interop-Tests, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
[assembly: InternalsVisibleTo("Mono.Android-TestsMultiDex, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
[assembly: InternalsVisibleTo("Mono.Android-TestsAppBundle, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<TargetFrameworkVersion>v10.0</TargetFrameworkVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\..\..\product.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<Import Project="..\..\..\..\Configuration.props" />
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
Expand Down Expand Up @@ -48,12 +50,11 @@
<Reference Include="Mono.Android" />
<Reference Include="Xamarin.Android.NUnitLite" />
<Reference Include="Mono.Linq.Expressions">
<HintPath>..\..\..\..\packages\mono.linq.expressions.2.0.0\lib\netstandard2.0\Mono.Linq.Expressions.dll</HintPath>
<HintPath>..\..\..\..\packages\Mono.Linq.Expressions.2.0.0\lib\netstandard2.0\Mono.Linq.Expressions.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Resources\Resource.designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Java.InteropTests\JavaInterop_Tests_Reference.cs" />
</ItemGroup>
<ItemGroup>
Expand Down

This file was deleted.

26 changes: 11 additions & 15 deletions src/Mono.Android/Test/Java.Interop/JnienvTest.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;

Expand Down Expand Up @@ -373,32 +374,27 @@ public void MoarThreadingTests ()
Assert.IsNull (ignore_t2, string.Format ("No exception should be thrown [t2]! Got: {0}", ignore_t2));
}

[DllImport ("__Internal", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr monodroid_typemap_java_to_managed (string java);

[Test]
public void JavaToManagedTypeMapping ()
{
var m = monodroid_typemap_java_to_managed ("android/content/res/Resources");
Assert.AreNotEqual (IntPtr.Zero, m);
m = monodroid_typemap_java_to_managed ("this/type/does/not/exist");
Assert.AreEqual (IntPtr.Zero, m);
Type m = Java.Interop.TypeManager.GetJavaToManagedType ("android/content/res/Resources");
Assert.AreNotEqual (null, m);
m = Java.Interop.TypeManager.GetJavaToManagedType ("this/type/does/not/exist");
Assert.AreEqual (null, m);
}

[DllImport ("__Internal", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr monodroid_typemap_managed_to_java (string java);

string GetTypeName (Type type)
{
return type.FullName + ", " + type.Assembly.GetName ().Name;
}
static extern IntPtr monodroid_typemap_managed_to_java (byte[] mvid, int token);

[Test]
public void ManagedToJavaTypeMapping ()
{
var m = monodroid_typemap_managed_to_java (GetTypeName (typeof (Activity)));
Type type = typeof(Activity);
var m = monodroid_typemap_managed_to_java (type.Module.ModuleVersionId.ToByteArray (), type.MetadataToken);
Assert.AreNotEqual (IntPtr.Zero, m, "`Activity` subclasses Java.Lang.Object, it should be in the typemap!");
m = monodroid_typemap_managed_to_java (GetTypeName (typeof (JnienvTest)));

type = typeof (JnienvTest);
m = monodroid_typemap_managed_to_java (type.Module.ModuleVersionId.ToByteArray (), type.MetadataToken);
Assert.AreEqual (IntPtr.Zero, m, "`JnienvTest` does *not* subclass Java.Lang.Object, it should *not* be in the typemap!");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Resources\Resource.designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="CustomTextView.cs" />
</ItemGroup>
<ItemGroup>
Expand Down
Loading