diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/MarkJavaObjects.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/MarkJavaObjects.cs index e8ac80cdef1..66893206bd8 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/MarkJavaObjects.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/MarkJavaObjects.cs @@ -60,6 +60,9 @@ void PreserveJavaObjectImplementation (TypeDefinition type) PreserveIntPtrConstructor (type); PreserveAttributeSetConstructor (type); PreserveInvoker (type); +#if ILLINK + PreserveInterfaces (type); +#endif // ILLINK } void PreserveAttributeSetConstructor (TypeDefinition type) @@ -196,7 +199,63 @@ void PreserveInvoker (TypeDefinition type) PreserveConstructors (type, invoker); PreserveIntPtrConstructor (invoker); PreserveInterfaceMethods (type, invoker); +#if ILLINK + PreserveInterfaces (invoker); +#endif // ILLINK + } + +#if ILLINK + void PreserveInterfaces (TypeDefinition type) + { + if (!type.HasInterfaces) + return; + + if (!ShouldPreserveInterfaces (type)) + return; + + foreach (var iface in type.Interfaces) { + var td = iface.InterfaceType.Resolve (); + if (!td.ImplementsIJavaPeerable ()) + continue; + Annotations.Mark (td); + } + } + + // False if [Register(DoNotGenerateAcw=true)] is on the type + // False if [JniTypeSignature(GenerateJavaPeer=false)] is on the type + bool ShouldPreserveInterfaces (TypeDefinition type) + { + if (!type.HasCustomAttributes) + return true; + + foreach (var attr in type.CustomAttributes) { + switch (attr.AttributeType.FullName) { + case "Android.Runtime.RegisterAttribute": + foreach (var property in attr.Properties) { + if (property.Name == "DoNotGenerateAcw") { + if (property.Argument.Value is bool value && value) + return false; + break; + } + } + break; + case "Java.Interop.JniTypeSignatureAttribute": + foreach (var property in attr.Properties) { + if (property.Name == "GenerateJavaPeer") { + if (property.Argument.Value is bool value && !value) + return false; + break; + } + } + break; + default: + break; + } + } + + return true; } +#endif // ILLINK TypeDefinition GetInvokerType (TypeDefinition type) { diff --git a/tests/MSBuildDeviceIntegration/Resources/LinkDescTest/MainActivityReplacement.cs b/tests/MSBuildDeviceIntegration/Resources/LinkDescTest/MainActivityReplacement.cs index a8f648afb2c..31aa2f0ef4e 100644 --- a/tests/MSBuildDeviceIntegration/Resources/LinkDescTest/MainActivityReplacement.cs +++ b/tests/MSBuildDeviceIntegration/Resources/LinkDescTest/MainActivityReplacement.cs @@ -115,6 +115,9 @@ protected override void OnCreate(Bundle bundle) // [Test] Post Android.Util.Log.Info(TAG, HttpClientTest.Post ()); + // [Test] TextChanged + Android.Util.Log.Info (TAG, MaterialTextChanged.TextChanged (this)); + var cldt = new CustomLinkerDescriptionTests(); Android.Util.Log.Info(TAG, cldt.TryAccessNonXmlPreservedMethodOfLinkerModeFullClass()); Android.Util.Log.Info(TAG, LinkTestLib.Bug21578.MulticastOption_ShouldNotBeStripped()); diff --git a/tests/MSBuildDeviceIntegration/Resources/LinkDescTest/MaterialTextChanged.cs b/tests/MSBuildDeviceIntegration/Resources/LinkDescTest/MaterialTextChanged.cs new file mode 100644 index 00000000000..721b01d7ba8 --- /dev/null +++ b/tests/MSBuildDeviceIntegration/Resources/LinkDescTest/MaterialTextChanged.cs @@ -0,0 +1,18 @@ +using System; +using Android.Content; +using Google.Android.Material.TextField; + +public class MaterialTextChanged +{ + // [Test] + public static string TextChanged (Context context) + { + try { + var view = new TextInputEditText (context); + view.TextChanged += (s, e) => { }; + return $"[PASS] {nameof (MaterialTextChanged)}.{nameof (TextChanged)}"; + } catch (Exception ex) { + return $"[FAIL] {nameof (MaterialTextChanged)}.{nameof (TextChanged)} FAILED: {ex}"; + } + } +} diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index d00dc301db8..9fe8bc19948 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -421,6 +421,24 @@ public class LinkModeFullClass { new BuildItem ("ProjectReference", "..\\Library1\\Library1.csproj"), new BuildItem ("ProjectReference", "..\\LinkTestLib\\LinkTestLib.csproj"), }, + PackageReferences = { + KnownPackages.AndroidXMigration, + KnownPackages.AndroidXAppCompat, + KnownPackages.AndroidXAppCompatResources, + KnownPackages.AndroidXBrowser, + KnownPackages.AndroidXMediaRouter, + KnownPackages.AndroidXLegacySupportV4, + KnownPackages.AndroidXLifecycleLiveData, + KnownPackages.XamarinGoogleAndroidMaterial, + }, + Sources = { + new BuildItem.Source ("MaterialTextChanged.cs") { + TextContent = () => { + using (var sr = new StreamReader (typeof (InstallAndRunTests).Assembly.GetManifestResourceStream ("Xamarin.Android.Build.Tests.Resources.LinkDescTest.MaterialTextChanged.cs"))) + return sr.ReadToEnd (); + }, + }, + }, OtherBuildItems = { new BuildItem ("LinkDescription", "linker.xml") { TextContent = () => linkMode == AndroidLinkMode.SdkOnly ? "" : @"