Skip to content

Commit

Permalink
[Microsoft.Android.Sdk.ILLink] fix crash when TZ changes
Browse files Browse the repository at this point in the history
Fixes: #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:

    <?xml version="1.0" encoding="utf-8" ?>
    <linker>
        <assembly fullname="Mono.Android">
    --      <type fullname="Android.Runtime.AndroidEnvironment" />

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.
  • Loading branch information
jonathanpeppers committed Apr 13, 2023
1 parent ecb207b commit f1bbe36
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
<linker>
<assembly fullname="Mono.Android">
<type fullname="Android.Runtime.AnnotationAttribute" />
<type fullname="Android.Runtime.AndroidEnvironment">
<method name="NotifyTimeZoneChanged" />
</type>
<type fullname="Android.Runtime.IJavaObject" />
<type fullname="Android.Runtime.InputStreamAdapter" preserve="methods" />
<type fullname="Android.Runtime.InputStreamInvoker" preserve="methods" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down
Original file line number Diff line number Diff line change
@@ -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}";
}
}
}
34 changes: 14 additions & 20 deletions tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
},
},
};
Expand All @@ -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")
});
}

Expand All @@ -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 = {
Expand Down Expand Up @@ -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]
Expand Down

0 comments on commit f1bbe36

Please sign in to comment.