Skip to content

Commit f1bbe36

Browse files
[Microsoft.Android.Sdk.ILLink] fix crash when TZ changes
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.
1 parent ecb207b commit f1bbe36

File tree

4 files changed

+42
-20
lines changed

4 files changed

+42
-20
lines changed

src/Microsoft.Android.Sdk.ILLink/PreserveLists/Mono.Android.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
<linker>
33
<assembly fullname="Mono.Android">
44
<type fullname="Android.Runtime.AnnotationAttribute" />
5+
<type fullname="Android.Runtime.AndroidEnvironment">
6+
<method name="NotifyTimeZoneChanged" />
7+
</type>
58
<type fullname="Android.Runtime.IJavaObject" />
69
<type fullname="Android.Runtime.InputStreamAdapter" preserve="methods" />
710
<type fullname="Android.Runtime.InputStreamInvoker" preserve="methods" />

tests/MSBuildDeviceIntegration/Resources/LinkDescTest/MainActivityReplacement.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ protected override void OnCreate(Bundle bundle)
115115
// [Test] Post
116116
Android.Util.Log.Info(TAG, HttpClientTest.Post ());
117117

118+
// [Test] MethodsArePreserved
119+
Android.Util.Log.Info (TAG, PreserveTest.MethodsArePreserved ());
120+
118121
// [Test] TextChanged
119122
Android.Util.Log.Info (TAG, MaterialTextChanged.TextChanged (this));
120123

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System;
2+
using System.Reflection;
3+
4+
public class PreserveTest
5+
{
6+
// [Test]
7+
public static string MethodsArePreserved ()
8+
{
9+
try {
10+
// See src/monodroid/jni/timezones.cc for usage
11+
var androidEnvironment = Type.GetType ("Android.Runtime.AndroidEnvironment, Mono.Android", throwOnError: true);
12+
var notifyTimeZoneChanged = androidEnvironment.GetMethod ("NotifyTimeZoneChanged", BindingFlags.Static | BindingFlags.NonPublic);
13+
if (notifyTimeZoneChanged == null) {
14+
return $"[FAIL] {nameof (PreserveTest)}.{nameof (MethodsArePreserved)} FAILED: {nameof (notifyTimeZoneChanged)} is null)";
15+
}
16+
notifyTimeZoneChanged.Invoke (null, null);
17+
return $"[PASS] {nameof (PreserveTest)}.{nameof (MethodsArePreserved)}";
18+
} catch (Exception ex) {
19+
return $"[FAIL] {nameof (PreserveTest)}.{nameof (MethodsArePreserved)} FAILED: {ex}";
20+
}
21+
}
22+
}

tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -400,22 +400,16 @@ public class LinkModeFullClass {
400400
},
401401
Sources = {
402402
new BuildItem.Source ("Bug21578.cs") {
403-
TextContent = () => {
404-
using (var sr = new StreamReader (typeof (InstallAndRunTests).Assembly.GetManifestResourceStream ("Xamarin.Android.Build.Tests.Resources.LinkDescTest.Bug21578.cs")))
405-
return sr.ReadToEnd ();
406-
},
403+
TextContent = () => getResource("Bug21578")
407404
},
408405
new BuildItem.Source ("Bug35195.cs") {
409-
TextContent = () => {
410-
using (var sr = new StreamReader (typeof (InstallAndRunTests).Assembly.GetManifestResourceStream ("Xamarin.Android.Build.Tests.Resources.LinkDescTest.Bug35195.cs")))
411-
return sr.ReadToEnd ();
412-
},
406+
TextContent = () => getResource("Bug35195")
413407
},
414408
new BuildItem.Source ("HttpClientTest.cs") {
415-
TextContent = () => {
416-
using (var sr = new StreamReader (typeof (InstallAndRunTests).Assembly.GetManifestResourceStream ("Xamarin.Android.Build.Tests.Resources.LinkDescTest.HttpClientTest.cs")))
417-
return sr.ReadToEnd ();
418-
},
409+
TextContent = () => getResource("HttpClientTest")
410+
},
411+
new BuildItem.Source ("PreserveTest.cs") {
412+
TextContent = () => getResource("PreserveTest")
419413
},
420414
},
421415
};
@@ -424,10 +418,7 @@ public class LinkModeFullClass {
424418
// DataContractSerializer is not trimming safe
425419
// https://github.com/dotnet/runtime/issues/45559
426420
lib2.Sources.Add (new BuildItem.Source ("Bug36250.cs") {
427-
TextContent = () => {
428-
using (var sr = new StreamReader (typeof (InstallAndRunTests).Assembly.GetManifestResourceStream ("Xamarin.Android.Build.Tests.Resources.LinkDescTest.Bug36250.cs")))
429-
return sr.ReadToEnd ();
430-
},
421+
TextContent = () => getResource ("Bug36250")
431422
});
432423
}
433424

@@ -450,10 +441,7 @@ public class LinkModeFullClass {
450441
},
451442
Sources = {
452443
new BuildItem.Source ("MaterialTextChanged.cs") {
453-
TextContent = () => {
454-
using (var sr = new StreamReader (typeof (InstallAndRunTests).Assembly.GetManifestResourceStream ("Xamarin.Android.Build.Tests.Resources.LinkDescTest.MaterialTextChanged.cs")))
455-
return sr.ReadToEnd ();
456-
},
444+
TextContent = () => getResource ("MaterialTextChanged")
457445
},
458446
},
459447
OtherBuildItems = {
@@ -512,6 +500,12 @@ public class LinkModeFullClass {
512500
StringAssert.Contains ("[LINKALLPASS]", logcatOutput);
513501
StringAssert.DoesNotContain ("[LINKALLFAIL]", logcatOutput);
514502
}
503+
504+
string getResource (string name)
505+
{
506+
using (var sr = new StreamReader (typeof (InstallAndRunTests).Assembly.GetManifestResourceStream ($"Xamarin.Android.Build.Tests.Resources.LinkDescTest.{name}.cs")))
507+
return sr.ReadToEnd ();
508+
}
515509
}
516510

517511
[Test]

0 commit comments

Comments
 (0)