Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Xamarin.Android.Build.Tasks] Add directBootAware if needed. #2621

Merged
merged 6 commits into from
Jan 18, 2019

Conversation

dellis1972
Copy link
Contributor

Fixes #2081

If a user needs to use the directBootAware attribute on
an application, activity or service we also need
to include it on the MonoRuntimeProvider so that
native libraries can be resolved correctly. Not doing
so results in the following

java.lang.UnsatisfiedLinkError: No implementation found for void mono.android.Runtime.register

This commit looks to see if any elements in the manifest
contain directBootAware. If there are , then we also
include it in the provider.

Copy link
Member

@jonathanpeppers jonathanpeppers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In one of the comments on #2081 they linked to: https://android-developers.googleblog.com/2016/04/developing-for-direct-boot.html

That might be a good link to add to the commit message.

@dellis1972 dellis1972 requested a review from jonpryor as a code owner January 16, 2019 16:53
@dellis1972
Copy link
Contributor Author

build

@jonathanpeppers
Copy link
Member

@dellis1972 one of the test failures on Windows seems new.

It might be worth rebasing on master for the SwitchBetweenDesignTimeBuild test, too.

Fixes dotnet#2081

If a user needs to use the `directBootAware` attribute on
an `application`, `activity` or `service` we also need
to include it on the `MonoRuntimeProvider` so that
native libraries can be resolved correctly. Not doing
so results in the following

	java.lang.UnsatisfiedLinkError: No implementation found for void mono.android.Runtime.register

This commit looks to see if any elements in the manifest
contain `directBootAware`. If there are , then we also
include it in the `provider`.
Copy link
Member

@jonathanpeppers jonathanpeppers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Windows test failure here should be fixed by: #2631

It is unrelated to this PR.

@jonpryor jonpryor merged commit 7c9dea8 into dotnet:master Jan 18, 2019
jonpryor pushed a commit to jonpryor/xamarin-android that referenced this pull request Jan 18, 2019
…t#2621)

Fixes: dotnet#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/
jonpryor added a commit that referenced this pull request Jan 21, 2019
#2637)

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/
@github-actions github-actions bot locked and limited conversation to collaborators Feb 1, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

DirectBoot execution fails with java.lang.UnsatisfiedLinkError
3 participants