From 2b6a0bf4598ed812baa8878c5cfb4abd6f02b979 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 23 Feb 2024 15:07:04 -0600 Subject: [PATCH 1/6] [Mono.Android] fix trimming warnings, part 2 This fixes the next set of trimmer warnings found via: true true ~~ JavaObjectExtensions ~~ `JavaCast()` now requires `PublicConstructors` and `NonPublicConstructors` because of `Activator.CreateInstance()`. This change bubbles up to various other types that have a `Find*ById()` method: * `Activity` * `Dialog` * `FragmentManager` * `View` * `Window` `GetInvokerType()` also has suppressions around `Assembly.GetType()` and `Type.MakeGenericType()`. We track this for the future at: https://github.com/xamarin/xamarin-android/issues/8724 ~~ AndroidRuntime ~~ Update `[DynamicallyAccessedMembers]` based on changes to `RegisterNativeMembers` in: https://github.com/xamarin/java.interop/commit/b8f6f8884ac11775107cbb55a9f57a38cbd53240 ~~ JNINativeWrapper ~~ `$(EnableAotAnalyzer)` found usage of `DynamicMethod`. Suppress for now, as we track this for the future at: https://github.com/xamarin/xamarin-android/issues/8724 ~~ ResourceIdManager ~~ Usage of `Type.GetMethod ("UpdateIdValues")` leads to decoration of `[ResourceDesignerAttribute]` with: [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] public string FullName { get; set; } I also had to suppress warnings around `Assembly.GetType()`. This *should* be OK, as `Resource.designer.cs` is always in the "root assembly" of Android application projects. ~~ JavaProxyThrowable ~~ Suppress warning around `StackFrame.GetMethod()`, we already handle null return values and exceptions. The existing code appears to be "best effort" to provide additional stack trace information. ~~ TypeManager ~~ Suppress warning around a call to `Type.GetType()` with a string passed in from Java. Not really much we can do yet, except rely on `MarkJavaObjects` trimmer step. Likely also a problem for the future: https://github.com/xamarin/xamarin-android/issues/8724 --- src/Mono.Android/Android.App/Activity.cs | 14 ++++-- src/Mono.Android/Android.App/Dialog.cs | 6 ++- .../Android.App/FragmentManager.cs | 20 ++++++-- .../Android.Runtime/AndroidRuntime.cs | 13 +++-- .../Android.Runtime/Extensions.cs | 5 +- .../Android.Runtime/JNINativeWrapper.cs | 8 +++- .../Android.Runtime/JavaProxyThrowable.cs | 7 ++- .../ResourceDesignerAttribute.cs | 6 ++- .../Android.Runtime/ResourceIdManager.cs | 11 ++++- src/Mono.Android/Android.Views/View.cs | 12 ++++- src/Mono.Android/Android.Views/Window.cs | 5 +- .../Java.Interop/JavaObjectExtensions.cs | 48 +++++++++++++++---- src/Mono.Android/Java.Interop/TypeManager.cs | 6 ++- 13 files changed, 132 insertions(+), 29 deletions(-) diff --git a/src/Mono.Android/Android.App/Activity.cs b/src/Mono.Android/Android.App/Activity.cs index a8156ec04c6..dd881a6b539 100644 --- a/src/Mono.Android/Android.App/Activity.cs +++ b/src/Mono.Android/Android.App/Activity.cs @@ -1,19 +1,27 @@ using System; - +using System.Diagnostics.CodeAnalysis; using Android.Runtime; namespace Android.App { partial class Activity { - public T? FindViewById (int id) + internal const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors; + + public T? FindViewById< + [DynamicallyAccessedMembers (Constructors)] + T + > (int id) where T : Android.Views.View { return this.FindViewById (id)!.JavaCast (); } // See: https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/app/Activity.java;l=3430 - public T RequireViewById (int id) + public T RequireViewById< + [DynamicallyAccessedMembers (Constructors)] + T + > (int id) where T : Android.Views.View { var view = FindViewById (id); diff --git a/src/Mono.Android/Android.App/Dialog.cs b/src/Mono.Android/Android.App/Dialog.cs index 14f32f00bc1..2a1a1f10ce8 100644 --- a/src/Mono.Android/Android.App/Dialog.cs +++ b/src/Mono.Android/Android.App/Dialog.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using Android.Runtime; namespace Android.App { @@ -8,7 +9,10 @@ public partial class Dialog { protected Dialog (Android.Content.Context context, bool cancelable, EventHandler cancelHandler) : this (context, cancelable, new Android.Content.IDialogInterfaceOnCancelListenerImplementor () { Handler = cancelHandler }) {} - public T? FindViewById (int id) + public T? FindViewById< + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] + T + > (int id) where T : Android.Views.View { return this.FindViewById (id).JavaCast (); diff --git a/src/Mono.Android/Android.App/FragmentManager.cs b/src/Mono.Android/Android.App/FragmentManager.cs index 5d32da4a247..219f8fac228 100644 --- a/src/Mono.Android/Android.App/FragmentManager.cs +++ b/src/Mono.Android/Android.App/FragmentManager.cs @@ -1,18 +1,32 @@ using Android.OS; using Android.Runtime; +using System.Diagnostics.CodeAnalysis; #if ANDROID_11 namespace Android.App { public partial class FragmentManager { - public T? FindFragmentById (int id) where T : Fragment + const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors; + + public T? FindFragmentById< + [DynamicallyAccessedMembers (Constructors)] + T + > (int id) where T : Fragment { return FindFragmentById (id).JavaCast (); } - public T? FindFragmentByTag (string tag) where T : Fragment + + public T? FindFragmentByTag< + [DynamicallyAccessedMembers (Constructors)] + T + > (string tag) where T : Fragment { return FindFragmentByTag (tag).JavaCast (); } - public T? GetFragment (Bundle bundle, string key) where T : Fragment + + public T? GetFragment< + [DynamicallyAccessedMembers (Constructors)] + T + > (Bundle bundle, string key) where T : Fragment { return GetFragment (bundle, key).JavaCast (); } diff --git a/src/Mono.Android/Android.Runtime/AndroidRuntime.cs b/src/Mono.Android/Android.Runtime/AndroidRuntime.cs index cd815b76391..d7876273983 100644 --- a/src/Mono.Android/Android.Runtime/AndroidRuntime.cs +++ b/src/Mono.Android/Android.Runtime/AndroidRuntime.cs @@ -247,6 +247,9 @@ struct JniRemappingReplacementMethod bool jniAddNativeMethodRegistrationAttributePresent; + const DynamicallyAccessedMemberTypes Methods = DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods; + const DynamicallyAccessedMemberTypes MethodsAndPrivateNested = Methods | DynamicallyAccessedMemberTypes.NonPublicNestedTypes; + public AndroidTypeManager (bool jniAddNativeMethodRegistrationAttributePresent) { this.jniAddNativeMethodRegistrationAttributePresent = jniAddNativeMethodRegistrationAttributePresent; @@ -473,7 +476,7 @@ static bool CallRegisterMethodByIndex (JniNativeMethodRegistrationArguments argu public override void RegisterNativeMembers ( JniType nativeClass, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] + [DynamicallyAccessedMembers (MethodsAndPrivateNested)] Type type, string? methods) => RegisterNativeMembers (nativeClass, type, methods.AsSpan ()); @@ -483,7 +486,7 @@ public override void RegisterNativeMembers ( [UnconditionalSuppressMessage ("Trimming", "IL2072", Justification = "Delegate.CreateDelegate() can never statically know the string value parsed from parameter 'methods'.")] public void RegisterNativeMembers ( JniType nativeClass, - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type type, + [DynamicallyAccessedMembers (MethodsAndPrivateNested)] Type type, ReadOnlySpan methods) { try { @@ -619,7 +622,11 @@ public override void WaitForGCBridgeProcessing () AndroidRuntimeInternal.WaitForBridgeProcessing (); } - public override IJavaPeerable? CreatePeer (ref JniObjectReference reference, JniObjectReferenceOptions options, Type? targetType) + public override IJavaPeerable? CreatePeer ( + ref JniObjectReference reference, + JniObjectReferenceOptions options, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] + Type? targetType) { if (!reference.IsValid) return null; diff --git a/src/Mono.Android/Android.Runtime/Extensions.cs b/src/Mono.Android/Android.Runtime/Extensions.cs index 93a442f5356..2d41fa03e2b 100644 --- a/src/Mono.Android/Android.Runtime/Extensions.cs +++ b/src/Mono.Android/Android.Runtime/Extensions.cs @@ -7,7 +7,10 @@ namespace Android.Runtime { public static class Extensions { [return: NotNullIfNotNull ("instance")] - public static TResult? JavaCast (this IJavaObject? instance) + public static TResult? JavaCast< + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] + TResult + > (this IJavaObject? instance) where TResult : class, IJavaObject { return Java.Interop.JavaObjectExtensions.JavaCast(instance); diff --git a/src/Mono.Android/Android.Runtime/JNINativeWrapper.cs b/src/Mono.Android/Android.Runtime/JNINativeWrapper.cs index 87cd87a30da..1b12c7b5243 100644 --- a/src/Mono.Android/Android.Runtime/JNINativeWrapper.cs +++ b/src/Mono.Android/Android.Runtime/JNINativeWrapper.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Reflection.Emit; using System.Threading; @@ -27,6 +28,11 @@ static void get_runtime_types () public static Delegate CreateDelegate (Delegate dlg) { + // FIXME: https://github.com/xamarin/xamarin-android/issues/8724 + [UnconditionalSuppressMessage ("AOT", "IL3050", Justification = "NativeAOT is not yet supported.")] + static DynamicMethod CreateDynamicMethod (Type ret_type, Type [] param_types) => + new DynamicMethod (DynamicMethodNameCounter.GetUniqueName (), ret_type, param_types, typeof (DynamicMethodNameCounter), true); + if (dlg == null) throw new ArgumentNullException (); if (dlg.Target != null) @@ -52,7 +58,7 @@ public static Delegate CreateDelegate (Delegate dlg) param_types [i] = parameters [i].ParameterType; } - var dynamic = new DynamicMethod (DynamicMethodNameCounter.GetUniqueName (), ret_type, param_types, typeof (DynamicMethodNameCounter), true); + var dynamic = CreateDynamicMethod(ret_type, param_types); var ig = dynamic.GetILGenerator (); LocalBuilder? retval = null; diff --git a/src/Mono.Android/Android.Runtime/JavaProxyThrowable.cs b/src/Mono.Android/Android.Runtime/JavaProxyThrowable.cs index 7e350980638..50ec8a7e1f1 100644 --- a/src/Mono.Android/Android.Runtime/JavaProxyThrowable.cs +++ b/src/Mono.Android/Android.Runtime/JavaProxyThrowable.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using StackTraceElement = Java.Lang.StackTraceElement; @@ -38,6 +39,10 @@ public static JavaProxyThrowable Create (Exception innerException) void TranslateStackTrace () { + [UnconditionalSuppressMessage ("Trimming", "IL2026", Justification = "StackFrame.GetMethod() is \"best attempt\", we handle null & exceptions")] + static MethodBase? StackFrameGetMethod (StackFrame frame) => + frame.GetMethod (); + var trace = new StackTrace (InnerException, fNeedFileInfo: true); if (trace.FrameCount <= 0) { return; @@ -59,7 +64,7 @@ void TranslateStackTrace () for (int i = 0; i < frames.Length; i++) { StackFrame managedFrame = frames[i]; - MethodBase? managedMethod = managedFrame.GetMethod (); + MethodBase? managedMethod = StackFrameGetMethod (managedFrame); var throwableFrame = new StackTraceElement ( declaringClass: managedMethod?.DeclaringType?.FullName, diff --git a/src/Mono.Android/Android.Runtime/ResourceDesignerAttribute.cs b/src/Mono.Android/Android.Runtime/ResourceDesignerAttribute.cs index 88f61075d0c..9528a5097e8 100644 --- a/src/Mono.Android/Android.Runtime/ResourceDesignerAttribute.cs +++ b/src/Mono.Android/Android.Runtime/ResourceDesignerAttribute.cs @@ -1,15 +1,19 @@ using System; +using System.Diagnostics.CodeAnalysis; namespace Android.Runtime { [AttributeUsage (AttributeTargets.Assembly)] public class ResourceDesignerAttribute : Attribute { - public ResourceDesignerAttribute (string fullName) + public ResourceDesignerAttribute ( + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] + string fullName) { FullName = fullName; } + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] public string FullName { get; set; } public bool IsApplication { get; set; } diff --git a/src/Mono.Android/Android.Runtime/ResourceIdManager.cs b/src/Mono.Android/Android.Runtime/ResourceIdManager.cs index 4a9590dcba4..c3a41938d48 100644 --- a/src/Mono.Android/Android.Runtime/ResourceIdManager.cs +++ b/src/Mono.Android/Android.Runtime/ResourceIdManager.cs @@ -31,12 +31,19 @@ public static void UpdateIdValues () } } - [UnconditionalSuppressMessage ("Trimming", "IL2026", Justification = "Types in Resource.designer.cs are preserved, because it is the root assembly passed to the linker.")] + [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] static Type? GetResourceTypeFromAssembly (Assembly assembly) { + const string rootAssembly = "Types in Resource.designer.cs are preserved, because it is the @(TrimmerRootAssembly)."; + + [UnconditionalSuppressMessage ("Trimming", "IL2026", Justification = rootAssembly)] + [UnconditionalSuppressMessage ("Trimming", "IL2073", Justification = rootAssembly)] + [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] + static Type AssemblyGetType (Assembly a, string name) => a.GetType (name); + foreach (var customAttribute in assembly.GetCustomAttributes (typeof (ResourceDesignerAttribute), true)) { if (customAttribute is ResourceDesignerAttribute resourceDesignerAttribute && resourceDesignerAttribute.IsApplication) { - var type = assembly.GetType (resourceDesignerAttribute.FullName); + var type = AssemblyGetType (assembly, resourceDesignerAttribute.FullName); if (type != null) return type; } diff --git a/src/Mono.Android/Android.Views/View.cs b/src/Mono.Android/Android.Views/View.cs index 2a17143e167..58de9a2c027 100644 --- a/src/Mono.Android/Android.Views/View.cs +++ b/src/Mono.Android/Android.Views/View.cs @@ -14,6 +14,8 @@ public enum SystemUiFlags { public partial class View { + internal const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors; + #if ANDROID_16 [Obsolete ("This method uses wrong enum type. Please use PerformAccessibilityAction(Action) instead.")] public bool PerformAccessibilityAction (GlobalAction action, Bundle arguments) @@ -22,14 +24,20 @@ public bool PerformAccessibilityAction (GlobalAction action, Bundle arguments) } #endif - public T? FindViewById (int id) + public T? FindViewById< + [DynamicallyAccessedMembers (Constructors)] + T + > (int id) where T : Android.Views.View { return this.FindViewById (id).JavaCast (); } // See: https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/View.java;l=25322 - public T RequireViewById (int id) + public T RequireViewById< + [DynamicallyAccessedMembers (Constructors)] + T + > (int id) where T : Android.Views.View { var view = FindViewById (id); diff --git a/src/Mono.Android/Android.Views/Window.cs b/src/Mono.Android/Android.Views/Window.cs index 6164a970d6a..1d82b614ec4 100644 --- a/src/Mono.Android/Android.Views/Window.cs +++ b/src/Mono.Android/Android.Views/Window.cs @@ -6,7 +6,10 @@ namespace Android.Views { partial class Window { - public T? FindViewById (int id) + public T? FindViewById< + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] + T + > (int id) where T : Android.Views.View { return this.FindViewById (id).JavaCast (); diff --git a/src/Mono.Android/Java.Interop/JavaObjectExtensions.cs b/src/Mono.Android/Java.Interop/JavaObjectExtensions.cs index 27564bb602b..eedb57a8a17 100644 --- a/src/Mono.Android/Java.Interop/JavaObjectExtensions.cs +++ b/src/Mono.Android/Java.Interop/JavaObjectExtensions.cs @@ -8,6 +8,7 @@ namespace Java.Interop { public static class JavaObjectExtensions { + const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors; [Obsolete ("Use Android.Runtime.JavaCollection.ToLocalJniHandle()")] public static JavaCollection ToInteroperableCollection (this ICollection instance) @@ -46,13 +47,19 @@ public static JavaDictionary ToInteroperableCollection (this IDictiona } [return: NotNullIfNotNull ("instance")] - public static TResult? JavaCast (this IJavaObject? instance) + public static TResult? JavaCast< + [DynamicallyAccessedMembers (Constructors)] + TResult + > (this IJavaObject? instance) where TResult : class, IJavaObject { return _JavaCast (instance); } - internal static TResult? _JavaCast (this IJavaObject? instance) + internal static TResult? _JavaCast< + [DynamicallyAccessedMembers (Constructors)] + TResult + > (this IJavaObject? instance) { if (instance == null) return default (TResult); @@ -74,7 +81,10 @@ public static JavaDictionary ToInteroperableCollection (this IDictiona throw new NotSupportedException (FormattableString.Invariant ($"Unable to convert type '{instance.GetType ().FullName}' to '{resultType.FullName}'.")); } - static IJavaObject CastClass (IJavaObject instance, Type resultType) + static IJavaObject CastClass ( + IJavaObject instance, + [DynamicallyAccessedMembers (Constructors)] + Type resultType) { var klass = JNIEnv.FindClass (resultType); try { @@ -97,7 +107,10 @@ static IJavaObject CastClass (IJavaObject instance, Type resultType) return (IJavaObject) TypeManager.CreateProxy (resultType, instance.Handle, JniHandleOwnership.DoNotTransfer); } - internal static IJavaObject? JavaCast (IJavaObject? instance, Type resultType) + internal static IJavaObject? JavaCast ( + IJavaObject? instance, + [DynamicallyAccessedMembers (Constructors)] + Type resultType) { if (resultType == null) throw new ArgumentNullException ("resultType"); @@ -120,23 +133,40 @@ static IJavaObject CastClass (IJavaObject instance, Type resultType) // typeof(Foo) -> FooInvoker // typeof(Foo<>) -> FooInvoker`1 - [UnconditionalSuppressMessage ("Trimming", "IL2026", Justification = "*Invoker types are preserved by the MarkJavaObjects linker step.")] - [UnconditionalSuppressMessage ("Trimming", "IL2055", Justification = "*Invoker types are preserved by the MarkJavaObjects linker step.")] + [return: DynamicallyAccessedMembers (Constructors)] internal static Type? GetInvokerType (Type type) { + const string InvokerTypes = "*Invoker types are preserved by the MarkJavaObjects linker step."; + + [UnconditionalSuppressMessage ("Trimming", "IL2026", Justification = InvokerTypes)] + [UnconditionalSuppressMessage ("Trimming", "IL2055", Justification = InvokerTypes)] + [UnconditionalSuppressMessage ("Trimming", "IL2073", Justification = InvokerTypes)] + [return: DynamicallyAccessedMembers (Constructors)] + static Type? AssemblyGetType (Assembly assembly, string typeName) => + assembly.GetType (typeName); + + // FIXME: https://github.com/xamarin/xamarin-android/issues/8724 + [UnconditionalSuppressMessage ("Trimming", "IL2055", Justification = InvokerTypes)] + [UnconditionalSuppressMessage ("Trimming", "IL2068", Justification = InvokerTypes)] + [UnconditionalSuppressMessage ("AOT", "IL3050", Justification = InvokerTypes)] + [return: DynamicallyAccessedMembers (Constructors)] + static Type MakeGenericType (Type type, params Type [] typeArguments) => type.MakeGenericType (typeArguments); + const string suffix = "Invoker"; + Type[] arguments = type.GetGenericArguments (); if (arguments.Length == 0) - return type.Assembly.GetType (type + suffix); + return AssemblyGetType (type.Assembly, type + suffix); Type definition = type.GetGenericTypeDefinition (); int bt = definition.FullName!.IndexOf ("`", StringComparison.Ordinal); if (bt == -1) throw new NotSupportedException ("Generic type doesn't follow generic type naming convention! " + type.FullName); - Type? suffixDefinition = definition.Assembly.GetType ( + Type? suffixDefinition = AssemblyGetType ( + definition.Assembly, definition.FullName.Substring (0, bt) + suffix + definition.FullName.Substring (bt)); if (suffixDefinition == null) return null; - return suffixDefinition.MakeGenericType (arguments); + return MakeGenericType (suffixDefinition, arguments); } } } diff --git a/src/Mono.Android/Java.Interop/TypeManager.cs b/src/Mono.Android/Java.Interop/TypeManager.cs index c0993e1a9d9..fb4e87216a4 100644 --- a/src/Mono.Android/Java.Interop/TypeManager.cs +++ b/src/Mono.Android/Java.Interop/TypeManager.cs @@ -237,6 +237,10 @@ static Exception CreateJavaLocationException () internal static Type? TypeRegistrationFallback (string class_name) { + [UnconditionalSuppressMessage ("Trimming", "IL2057", Justification = "Type should be preserved by the MarkJavaObjects trimmer step.")] + static Type? TypeGetType (string name) => + Type.GetType (name, throwOnError: false); + __TypeRegistrations.RegisterPackages (); Type? type = null; @@ -250,7 +254,7 @@ static Exception CreateJavaLocationException () return type; } } - if ((type = Type.GetType (JavaNativeTypeManager.ToCliType (class_name))) != null) { + if ((type = TypeGetType (JavaNativeTypeManager.ToCliType (class_name))) != null) { return type; } return null; From 991674c74df2a023a9cc9e9195086f921feac2ce Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 26 Feb 2024 11:44:28 -0600 Subject: [PATCH 2/6] Update BuildReleaseArm64XFormsDotNet.apkdesc --- .../BuildReleaseArm64XFormsDotNet.apkdesc | 148 +++++++++--------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc index ddd5ba9e1b8..58f281d0e0c 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc @@ -5,214 +5,214 @@ "Size": 6652 }, "assemblies/_Microsoft.Android.Resource.Designer.dll": { - "Size": 2281 + "Size": 2279 }, "assemblies/FormsViewGroup.dll": { - "Size": 8100 + "Size": 8090 }, "assemblies/Java.Interop.dll": { - "Size": 69705 + "Size": 72297 }, "assemblies/Mono.Android.dll": { - "Size": 458238 + "Size": 456687 }, "assemblies/Mono.Android.Runtime.dll": { - "Size": 5151 + "Size": 5143 }, "assemblies/mscorlib.dll": { - "Size": 4002 + "Size": 3999 }, "assemblies/netstandard.dll": { - "Size": 5643 + "Size": 5632 }, "assemblies/rc.bin": { "Size": 1512 }, "assemblies/System.Collections.Concurrent.dll": { - "Size": 11530 + "Size": 11523 }, "assemblies/System.Collections.dll": { - "Size": 15430 + "Size": 15415 }, "assemblies/System.Collections.NonGeneric.dll": { - "Size": 7452 + "Size": 7445 }, "assemblies/System.ComponentModel.dll": { - "Size": 1939 + "Size": 1941 }, "assemblies/System.ComponentModel.Primitives.dll": { - "Size": 2549 + "Size": 2555 }, "assemblies/System.ComponentModel.TypeConverter.dll": { - "Size": 6033 + "Size": 6089 }, "assemblies/System.Console.dll": { - "Size": 6578 + "Size": 6582 }, "assemblies/System.Core.dll": { - "Size": 1974 + "Size": 1976 }, "assemblies/System.Diagnostics.DiagnosticSource.dll": { - "Size": 9068 + "Size": 9064 }, "assemblies/System.Diagnostics.TraceSource.dll": { - "Size": 6552 + "Size": 6547 }, "assemblies/System.dll": { - "Size": 2328 + "Size": 2333 }, "assemblies/System.Drawing.dll": { - "Size": 1939 + "Size": 1937 }, "assemblies/System.Drawing.Primitives.dll": { - "Size": 11975 + "Size": 11966 }, "assemblies/System.IO.Compression.Brotli.dll": { - "Size": 11196 + "Size": 11192 }, "assemblies/System.IO.Compression.dll": { - "Size": 15880 + "Size": 15868 }, "assemblies/System.IO.IsolatedStorage.dll": { - "Size": 9875 + "Size": 9899 }, "assemblies/System.Linq.dll": { - "Size": 19599 + "Size": 20517 }, "assemblies/System.Linq.Expressions.dll": { - "Size": 165117 + "Size": 164631 }, "assemblies/System.Net.Http.dll": { - "Size": 67653 + "Size": 67564 }, "assemblies/System.Net.Primitives.dll": { - "Size": 22432 + "Size": 22363 }, "assemblies/System.Net.Requests.dll": { - "Size": 3602 + "Size": 3594 }, "assemblies/System.ObjectModel.dll": { - "Size": 8699 + "Size": 8572 }, "assemblies/System.Private.CoreLib.dll": { - "Size": 849922 + "Size": 869622 }, "assemblies/System.Private.DataContractSerialization.dll": { - "Size": 193991 + "Size": 193441 }, "assemblies/System.Private.Uri.dll": { - "Size": 42860 + "Size": 42907 }, "assemblies/System.Private.Xml.dll": { - "Size": 216226 + "Size": 216025 }, "assemblies/System.Private.Xml.Linq.dll": { - "Size": 16639 + "Size": 16627 }, "assemblies/System.Runtime.dll": { - "Size": 2708 + "Size": 2709 }, "assemblies/System.Runtime.InteropServices.dll": { - "Size": 4028 + "Size": 4022 }, "assemblies/System.Runtime.Serialization.dll": { "Size": 1865 }, "assemblies/System.Runtime.Serialization.Formatters.dll": { - "Size": 2484 + "Size": 2485 }, "assemblies/System.Runtime.Serialization.Primitives.dll": { - "Size": 3758 + "Size": 3757 }, "assemblies/System.Security.Cryptography.dll": { - "Size": 8111 + "Size": 8102 }, "assemblies/System.Text.RegularExpressions.dll": { - "Size": 159112 + "Size": 159848 }, "assemblies/System.Xml.dll": { - "Size": 1758 + "Size": 1760 }, "assemblies/System.Xml.Linq.dll": { - "Size": 1774 + "Size": 1775 }, "assemblies/UnnamedProject.dll": { - "Size": 5015 + "Size": 5007 }, "assemblies/Xamarin.AndroidX.Activity.dll": { - "Size": 16149 + "Size": 16116 }, "assemblies/Xamarin.AndroidX.AppCompat.AppCompatResources.dll": { - "Size": 6225 + "Size": 6216 }, "assemblies/Xamarin.AndroidX.AppCompat.dll": { - "Size": 138721 + "Size": 138025 }, "assemblies/Xamarin.AndroidX.CardView.dll": { - "Size": 6977 + "Size": 6959 }, "assemblies/Xamarin.AndroidX.CoordinatorLayout.dll": { - "Size": 17886 + "Size": 17921 }, "assemblies/Xamarin.AndroidX.Core.dll": { - "Size": 127505 + "Size": 126882 }, "assemblies/Xamarin.AndroidX.CursorAdapter.dll": { - "Size": 8997 + "Size": 8978 }, "assemblies/Xamarin.AndroidX.DrawerLayout.dll": { - "Size": 15319 + "Size": 15286 }, "assemblies/Xamarin.AndroidX.Fragment.dll": { - "Size": 51744 + "Size": 51498 }, "assemblies/Xamarin.AndroidX.Legacy.Support.Core.UI.dll": { - "Size": 6242 + "Size": 6233 }, "assemblies/Xamarin.AndroidX.Lifecycle.Common.dll": { - "Size": 6900 + "Size": 6890 }, "assemblies/Xamarin.AndroidX.Lifecycle.LiveData.Core.dll": { - "Size": 6743 + "Size": 6733 }, "assemblies/Xamarin.AndroidX.Lifecycle.ViewModel.dll": { - "Size": 7011 + "Size": 7002 }, "assemblies/Xamarin.AndroidX.Loader.dll": { - "Size": 13082 + "Size": 13063 }, "assemblies/Xamarin.AndroidX.RecyclerView.dll": { - "Size": 93990 + "Size": 93516 }, "assemblies/Xamarin.AndroidX.SavedState.dll": { - "Size": 5114 + "Size": 5107 }, "assemblies/Xamarin.AndroidX.SwipeRefreshLayout.dll": { - "Size": 13974 + "Size": 13946 }, "assemblies/Xamarin.AndroidX.ViewPager.dll": { - "Size": 19060 + "Size": 19014 }, "assemblies/Xamarin.Forms.Core.dll": { - "Size": 565831 + "Size": 563905 }, "assemblies/Xamarin.Forms.Platform.Android.dll": { - "Size": 374486 + "Size": 373374 }, "assemblies/Xamarin.Forms.Platform.dll": { - "Size": 18767 + "Size": 18753 }, "assemblies/Xamarin.Forms.Xaml.dll": { - "Size": 63655 + "Size": 63542 }, "assemblies/Xamarin.Google.Android.Material.dll": { - "Size": 66417 + "Size": 66169 }, "classes.dex": { - "Size": 9458972 + "Size": 9418292 }, "classes2.dex": { - "Size": 103648 + "Size": 150904 }, "kotlin/annotation/annotation.kotlin_builtins": { "Size": 928 @@ -236,19 +236,19 @@ "Size": 2396 }, "lib/arm64-v8a/libmono-component-marshal-ilgen.so": { - "Size": 87080 + "Size": 87352 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 339864 + "Size": 343896 }, "lib/arm64-v8a/libmonosgen-2.0.so": { - "Size": 3184512 + "Size": 3210968 }, "lib/arm64-v8a/libSystem.IO.Compression.Native.so": { "Size": 723560 }, "lib/arm64-v8a/libSystem.Native.so": { - "Size": 94504 + "Size": 94720 }, "lib/arm64-v8a/libSystem.Security.Cryptography.Native.Android.so": { "Size": 155568 @@ -407,7 +407,7 @@ "Size": 6 }, "META-INF/BNDLTOOL.RSA": { - "Size": 1223 + "Size": 1221 }, "META-INF/BNDLTOOL.SF": { "Size": 97490 @@ -2477,5 +2477,5 @@ "Size": 812848 } }, - "PackageSize": 10864931 + "PackageSize": 10897699 } \ No newline at end of file From 6fab46c18dffb1a4a81900386e37923d9daa438e Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Tue, 27 Feb 2024 13:59:16 -0600 Subject: [PATCH 3/6] Update JavaProxyThrowable.cs Code comments + FIXME --- src/Mono.Android/Android.Runtime/JavaProxyThrowable.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Mono.Android/Android.Runtime/JavaProxyThrowable.cs b/src/Mono.Android/Android.Runtime/JavaProxyThrowable.cs index 50ec8a7e1f1..5755f705f30 100644 --- a/src/Mono.Android/Android.Runtime/JavaProxyThrowable.cs +++ b/src/Mono.Android/Android.Runtime/JavaProxyThrowable.cs @@ -39,6 +39,10 @@ public static JavaProxyThrowable Create (Exception innerException) void TranslateStackTrace () { + // FIXME: https://github.com/xamarin/xamarin-android/issues/8724 + // StackFrame.GetMethod() will return null under NativeAOT; + // However, you can still get useful information from StackFrame.ToString(): + // MainActivity.OnCreate() + 0x37 at offset 55 in file:line:column :0:0 [UnconditionalSuppressMessage ("Trimming", "IL2026", Justification = "StackFrame.GetMethod() is \"best attempt\", we handle null & exceptions")] static MethodBase? StackFrameGetMethod (StackFrame frame) => frame.GetMethod (); From 4234ebb6e46e10a4677200a0103b2b0ce1d62430 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Tue, 27 Feb 2024 14:13:07 -0600 Subject: [PATCH 4/6] `#pragma warning disable IL3050` Doing it this way, keeps the warning present if someone was attempting to *use* NativeAOT, they still get the warning. --- src/Mono.Android/Android.Runtime/JNINativeWrapper.cs | 11 +++++------ src/Mono.Android/Java.Interop/JavaObjectExtensions.cs | 7 +++++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Mono.Android/Android.Runtime/JNINativeWrapper.cs b/src/Mono.Android/Android.Runtime/JNINativeWrapper.cs index 1b12c7b5243..fc87ab63c28 100644 --- a/src/Mono.Android/Android.Runtime/JNINativeWrapper.cs +++ b/src/Mono.Android/Android.Runtime/JNINativeWrapper.cs @@ -28,11 +28,6 @@ static void get_runtime_types () public static Delegate CreateDelegate (Delegate dlg) { - // FIXME: https://github.com/xamarin/xamarin-android/issues/8724 - [UnconditionalSuppressMessage ("AOT", "IL3050", Justification = "NativeAOT is not yet supported.")] - static DynamicMethod CreateDynamicMethod (Type ret_type, Type [] param_types) => - new DynamicMethod (DynamicMethodNameCounter.GetUniqueName (), ret_type, param_types, typeof (DynamicMethodNameCounter), true); - if (dlg == null) throw new ArgumentNullException (); if (dlg.Target != null) @@ -58,7 +53,11 @@ static DynamicMethod CreateDynamicMethod (Type ret_type, Type [] param_types) => param_types [i] = parameters [i].ParameterType; } - var dynamic = CreateDynamicMethod(ret_type, param_types); + // FIXME: https://github.com/xamarin/xamarin-android/issues/8724 + // IL3050 disabled in source: if someone uses NativeAOT, they will get the warning. + #pragma warning disable IL3050 + var dynamic = new DynamicMethod (DynamicMethodNameCounter.GetUniqueName (), ret_type, param_types, typeof (DynamicMethodNameCounter), true); + #pragma warning restore IL3050 var ig = dynamic.GetILGenerator (); LocalBuilder? retval = null; diff --git a/src/Mono.Android/Java.Interop/JavaObjectExtensions.cs b/src/Mono.Android/Java.Interop/JavaObjectExtensions.cs index eedb57a8a17..5b083487c5b 100644 --- a/src/Mono.Android/Java.Interop/JavaObjectExtensions.cs +++ b/src/Mono.Android/Java.Interop/JavaObjectExtensions.cs @@ -146,11 +146,14 @@ static IJavaObject CastClass ( assembly.GetType (typeName); // FIXME: https://github.com/xamarin/xamarin-android/issues/8724 + // IL3050 disabled in source: if someone uses NativeAOT, they will get the warning. [UnconditionalSuppressMessage ("Trimming", "IL2055", Justification = InvokerTypes)] [UnconditionalSuppressMessage ("Trimming", "IL2068", Justification = InvokerTypes)] - [UnconditionalSuppressMessage ("AOT", "IL3050", Justification = InvokerTypes)] [return: DynamicallyAccessedMembers (Constructors)] - static Type MakeGenericType (Type type, params Type [] typeArguments) => type.MakeGenericType (typeArguments); + static Type MakeGenericType (Type type, params Type [] typeArguments) => + #pragma warning disable IL3050 + type.MakeGenericType (typeArguments); + #pragma warning restore IL3050 const string suffix = "Invoker"; From 2f89efaff4b30e18e0e57bb33ae042a606e4564b Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Thu, 29 Feb 2024 13:34:54 -0500 Subject: [PATCH 5/6] Update FragmentManager.cs Code formatting --- src/Mono.Android/Android.App/FragmentManager.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Mono.Android/Android.App/FragmentManager.cs b/src/Mono.Android/Android.App/FragmentManager.cs index 219f8fac228..5269111a1a0 100644 --- a/src/Mono.Android/Android.App/FragmentManager.cs +++ b/src/Mono.Android/Android.App/FragmentManager.cs @@ -10,7 +10,8 @@ public partial class FragmentManager { public T? FindFragmentById< [DynamicallyAccessedMembers (Constructors)] T - > (int id) where T : Fragment + > (int id) + where T : Fragment { return FindFragmentById (id).JavaCast (); } @@ -18,7 +19,8 @@ public T? FindFragmentById< public T? FindFragmentByTag< [DynamicallyAccessedMembers (Constructors)] T - > (string tag) where T : Fragment + > (string tag) + where T : Fragment { return FindFragmentByTag (tag).JavaCast (); } @@ -26,7 +28,8 @@ public T? FindFragmentByTag< public T? GetFragment< [DynamicallyAccessedMembers (Constructors)] T - > (Bundle bundle, string key) where T : Fragment + > (Bundle bundle, string key) + where T : Fragment { return GetFragment (bundle, key).JavaCast (); } From c61f027229805a9d41b2ee479fd40ad50b16c82b Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 29 Feb 2024 16:42:19 -0600 Subject: [PATCH 6/6] Improve justification message in ResourceIdManager --- src/Mono.Android/Android.Runtime/ResourceIdManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mono.Android/Android.Runtime/ResourceIdManager.cs b/src/Mono.Android/Android.Runtime/ResourceIdManager.cs index c3a41938d48..5ef1e6255df 100644 --- a/src/Mono.Android/Android.Runtime/ResourceIdManager.cs +++ b/src/Mono.Android/Android.Runtime/ResourceIdManager.cs @@ -34,7 +34,7 @@ public static void UpdateIdValues () [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] static Type? GetResourceTypeFromAssembly (Assembly assembly) { - const string rootAssembly = "Types in Resource.designer.cs are preserved, because it is the @(TrimmerRootAssembly)."; + const string rootAssembly = "Resources.UpdateIdValues() methods are trimmed away by the LinkResourceDesigner trimmer step. This codepath is not called unless $(AndroidUseDesignerAssembly) is disabled."; [UnconditionalSuppressMessage ("Trimming", "IL2026", Justification = rootAssembly)] [UnconditionalSuppressMessage ("Trimming", "IL2073", Justification = rootAssembly)]