Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Xamarin.Android.Build.Tasks] Add
directBootAware
if needed. (#2621)
Fixes: #2081 Context? http://work.devdiv.io/727120 The [`//application/@android:directBootAware`][0] attribute *changes* how process startup semantics work, in [non-obvious ways][1]. Consider the following: 1. Start with an Android v7.0 Nougat device. 2. Build, Install, & Run the [Direct Boot Sample][2] 3. Create an alarm within the Direct Boot Sample app. 4. Reboot the Android device. 5. Wait for the alarm to go off without unlocking the device. Expected results: An alarm goes off. Actual results: Nothing happens, and `adb logcat` contains: java.lang.UnsatisfiedLinkError: No implementation found for void mono.android.Runtime.register(java.lang.String, java.lang.Class, java.lang.String) (tried Java_mono_android_Runtime_register and Java_mono_android_Runtime_register__Ljava_lang_String_2Ljava_lang_Class_2Ljava_lang_String_2) at mono.android.Runtime.register(Native Method) at md511db93b05d0fbee144be45ad6fb54d50.BootBroadcastReceiver.(BootBroadcastReceiver.java:15) at java.lang.Class.newInstance(Native Method) at android.app.ActivityThread.handleReceiver(ActivityThread.java:3671) ... One of the apparent changes when `directBootAware` is used is that `<provider/>`s must *also* "opt-in" to `directBootAware`. If a `<provider/>` *isn't* also `directBootAware`, then the `<provider/>` can't be used before the device is unlocked. Our Bootstrap code within `MonoRuntimeProvider` is "injected" via `<provider/>`. Meaning if the app uses `directBootAware` but the `MonoRuntimeProvider` *isn't* `directBootAware`, then the app can't use any managed code before the device has been unlocked. Which is why the `UnsatisfiedLinkError` is generated: the `MonoRuntimeProvider` hasn't been created, meaning `mono` hasn't been initialized, meaning nothing can work *until the device is unlocked*. The fix? If *anything* within `AndroidManifest` sets `//*[@android:directBootAware='true']`, then add a `@android:directBootAware="true"` attribute to the generated `<provider/>` for `mono.MonoRuntimeProvider`. This will ensure that managed code is properly initialized and can execute after the device has been rebooted and before the user has unlocked the device. [0]: https://developer.android.com/guide/topics/manifest/application-element#directBootAware [1]: https://android-developers.googleblog.com/2016/04/developing-for-direct-boot.html [2]: https://developer.xamarin.com/samples/monodroid/android-n/DirectBoot/
- Loading branch information