dotnet/android

Services with isolated processes and custom Application class fail to resolve overloads properly

Opened this issue · 10 comments

Basically if we have a Custom Application class + a service with IsolatedProcess = true, it crashes.

See more details about it on:

This issue was reported on 2017-01-29, confirmed by Xamarin Team, but no fix so far.

tipa commented

Is there any update on this? The bug is still present

Bumped into this issue as well and can confirm the bug is still present. Any estimated fix?

Any updates?

The crash is also observed on a Service run in a separate process, which is not an isolated process.

<service android:name=".SeparateProcessService" android:enabled="true" android:process=":sepService" />

This service does not have the android:isolatedProcess="true" attribute set, but this still crashes with the same error.

@jonathanpeppers , can you please have a look into this, for us it is a blocker in production release.

Jonathan Pryor describes what the problem here is:

Jumping off of Frank in Comment 3, this appears to be related to //service/@android:isolatedProcess.

https://developer.android.com/guide/topics/manifest/service-element.html#isolated

If I remove the use of ServiceAttribute.IsolatedProcess -- thus removing that attribute -- then the ContactSample app works as expected. I also see the log messages I expected to see, which is always a bonus. :-)

I thus have to suspect that //*/@android:isolatedProcess not only has "no permissions of its own," but also doesn't launch any <provider/>s, thus killing our entire bootstrap mechanism.

I have no idea how to fix this right now, or what the timeframe for supporting isolatedProcess will be. Research needed.

Xamarin.Android bootstraps Mono by using an Android content provider:

https://github.com/xamarin/xamarin-android/blob/53cdc642f4c1298b0ff5e3b073113d77f8785124/src/Xamarin.Android.Build.Tasks/Resources/MonoRuntimeProvider.Bundled.java

Content providers are called by Android before the first Application or Activity, and so it is an ideal place to "start up" Mono.

From this content provider written in Java, we can then call into native C/C++ to start Mono, then start managed C# code. This is fundamental to how Xamarin.Android currently works.

It appears that content providers are not called by Android for out of process services. Right now, the problem is we don't know how to fix this. We need a Java callback before the out of process service starts, so if anyone has some ideas, we would like to know, thanks!

Just a shot in the dark - The Magisk root managment tool uses ptrace and inotify events to listen for process forks. Can a similar method be used to detect the new process? Magisk runs its process monitor with root privileges to detect all child processes of zygote and unmount some partitions for some processes. But I think root privileges are not required for a process to detect its own child processes. I see one problem with this approach, even though the parent process can detect a child process, I am not sure if we can execute code in the child process to hook a Java callback.

Can the bootstrapping be done in Application.onCreate() instead of in ContentProvider.attachinfo()? Or in the Xamarin Application onCreate() code that the Application.onCreate() extends from. Why can't it be done in the Application class lifecycle itself?

I don't understand the bootstrapping mechanism, so I am not sure how big of a change this is.

VaslD commented

I think it’s because Mono bootstrap has to complete before ANY C# code can be run, that includes any Application subclasses defined in C# and thus Application.OnCreate()

But you’re also making a good point that maybe hacking Application (the Java side Application) can be of some help? IIRC multi-dexing uses a somewhat similar mechanism to inject bootstrap code.

I’m also not an expert on Android runtime so just saying.

from @MediumOne: The Magisk root managment tool uses ptrace and inotify events to listen for process forks

I think we need a callback inside the new process. I think this would be listening for new processes starting?

from @VaslD: But you’re also making a good point that maybe hacking Application (the Java side Application) can be of some help?

Do we know if the Application class is even called for an out-of-process service?

If so, it might be possible to create a Java Application class that manually starts Mono. You would not be able to have a C# Application class, though.

You could add a Application.java class to a project with a build action of AndroidJavaSource with code exactly like this: https://github.com/xamarin/xamarin-android/blob/53cdc642f4c1298b0ff5e3b073113d77f8785124/src/Xamarin.Android.Build.Tasks/Resources/MonoRuntimeProvider.Bundled.java#L21-L36

I will put this on my list to try and see if I can get it to work.