From f1bbe36b7599e198a5c7b68a33641aa44130fb93 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Wed, 12 Apr 2023 14:50:40 -0500 Subject: [PATCH] [Microsoft.Android.Sdk.ILLink] fix crash when TZ changes Fixes: https://github.com/xamarin/xamarin-android/issues/7953 When a timezone changes in a `Release` app, it can crash with: [monodroid] Unable to find Android.Runtime.AndroidEnvironment.NotifyTimeZoneChanged()! In 11f0e1b, we removed the line: -- Unfortunately, this method is called from native code, so we need to *always* preserve it. Added a test for this scenario, we may want to audit all `mono_class_get_method_from_name` calls and add more tests cases. I also cleaned up the tests a bit with a `getResource()` local function. --- .../PreserveLists/Mono.Android.xml | 3 ++ .../LinkDescTest/MainActivityReplacement.cs | 3 ++ .../Resources/LinkDescTest/PreserveTest.cs | 22 ++++++++++++ .../Tests/InstallAndRunTests.cs | 34 ++++++++----------- 4 files changed, 42 insertions(+), 20 deletions(-) create mode 100644 tests/MSBuildDeviceIntegration/Resources/LinkDescTest/PreserveTest.cs diff --git a/src/Microsoft.Android.Sdk.ILLink/PreserveLists/Mono.Android.xml b/src/Microsoft.Android.Sdk.ILLink/PreserveLists/Mono.Android.xml index 1f27591ef8f..8cd89166720 100644 --- a/src/Microsoft.Android.Sdk.ILLink/PreserveLists/Mono.Android.xml +++ b/src/Microsoft.Android.Sdk.ILLink/PreserveLists/Mono.Android.xml @@ -2,6 +2,9 @@ + + + diff --git a/tests/MSBuildDeviceIntegration/Resources/LinkDescTest/MainActivityReplacement.cs b/tests/MSBuildDeviceIntegration/Resources/LinkDescTest/MainActivityReplacement.cs index 31aa2f0ef4e..44860c14466 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] MethodsArePreserved + Android.Util.Log.Info (TAG, PreserveTest.MethodsArePreserved ()); + // [Test] TextChanged Android.Util.Log.Info (TAG, MaterialTextChanged.TextChanged (this)); diff --git a/tests/MSBuildDeviceIntegration/Resources/LinkDescTest/PreserveTest.cs b/tests/MSBuildDeviceIntegration/Resources/LinkDescTest/PreserveTest.cs new file mode 100644 index 00000000000..d822000a399 --- /dev/null +++ b/tests/MSBuildDeviceIntegration/Resources/LinkDescTest/PreserveTest.cs @@ -0,0 +1,22 @@ +using System; +using System.Reflection; + +public class PreserveTest +{ + // [Test] + public static string MethodsArePreserved () + { + try { + // See src/monodroid/jni/timezones.cc for usage + var androidEnvironment = Type.GetType ("Android.Runtime.AndroidEnvironment, Mono.Android", throwOnError: true); + var notifyTimeZoneChanged = androidEnvironment.GetMethod ("NotifyTimeZoneChanged", BindingFlags.Static | BindingFlags.NonPublic); + if (notifyTimeZoneChanged == null) { + return $"[FAIL] {nameof (PreserveTest)}.{nameof (MethodsArePreserved)} FAILED: {nameof (notifyTimeZoneChanged)} is null)"; + } + notifyTimeZoneChanged.Invoke (null, null); + return $"[PASS] {nameof (PreserveTest)}.{nameof (MethodsArePreserved)}"; + } catch (Exception ex) { + return $"[FAIL] {nameof (PreserveTest)}.{nameof (MethodsArePreserved)} FAILED: {ex}"; + } + } +} diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 1f0d4000992..8504f47d421 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -400,22 +400,16 @@ public class LinkModeFullClass { }, Sources = { new BuildItem.Source ("Bug21578.cs") { - TextContent = () => { - using (var sr = new StreamReader (typeof (InstallAndRunTests).Assembly.GetManifestResourceStream ("Xamarin.Android.Build.Tests.Resources.LinkDescTest.Bug21578.cs"))) - return sr.ReadToEnd (); - }, + TextContent = () => getResource("Bug21578") }, new BuildItem.Source ("Bug35195.cs") { - TextContent = () => { - using (var sr = new StreamReader (typeof (InstallAndRunTests).Assembly.GetManifestResourceStream ("Xamarin.Android.Build.Tests.Resources.LinkDescTest.Bug35195.cs"))) - return sr.ReadToEnd (); - }, + TextContent = () => getResource("Bug35195") }, new BuildItem.Source ("HttpClientTest.cs") { - TextContent = () => { - using (var sr = new StreamReader (typeof (InstallAndRunTests).Assembly.GetManifestResourceStream ("Xamarin.Android.Build.Tests.Resources.LinkDescTest.HttpClientTest.cs"))) - return sr.ReadToEnd (); - }, + TextContent = () => getResource("HttpClientTest") + }, + new BuildItem.Source ("PreserveTest.cs") { + TextContent = () => getResource("PreserveTest") }, }, }; @@ -424,10 +418,7 @@ public class LinkModeFullClass { // DataContractSerializer is not trimming safe // https://github.com/dotnet/runtime/issues/45559 lib2.Sources.Add (new BuildItem.Source ("Bug36250.cs") { - TextContent = () => { - using (var sr = new StreamReader (typeof (InstallAndRunTests).Assembly.GetManifestResourceStream ("Xamarin.Android.Build.Tests.Resources.LinkDescTest.Bug36250.cs"))) - return sr.ReadToEnd (); - }, + TextContent = () => getResource ("Bug36250") }); } @@ -450,10 +441,7 @@ public class LinkModeFullClass { }, 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 (); - }, + TextContent = () => getResource ("MaterialTextChanged") }, }, OtherBuildItems = { @@ -512,6 +500,12 @@ public class LinkModeFullClass { StringAssert.Contains ("[LINKALLPASS]", logcatOutput); StringAssert.DoesNotContain ("[LINKALLFAIL]", logcatOutput); } + + string getResource (string name) + { + using (var sr = new StreamReader (typeof (InstallAndRunTests).Assembly.GetManifestResourceStream ($"Xamarin.Android.Build.Tests.Resources.LinkDescTest.{name}.cs"))) + return sr.ReadToEnd (); + } } [Test]