AgregoreWeb / agregore-mobile

Mobile version of the Agregore browser for Android, based on Chromium and Bromite
MIT License
31 stars 6 forks source link

Get gateway loading on startup #6

Closed RangerMauve closed 2 years ago

RangerMauve commented 2 years ago

There might be some issues here.

Looking at the docs for chromium Android they mentioned that Android doesn't support forking processes. https://docs.google.com/document/d/1PTI3udZ6TI-R0MlSsl2aflxRcnZ5blnkGGHE5JRI_Z8/edit#

Chromium folks work around this by having processes run inside separate services.

We might need to run the gateway within its own service and to run it from Java using this method

RangerMauve commented 2 years ago

More details for running the binary. https://stackoverflow.com/questions/16179062/using-exec-with-ndk

RangerMauve commented 2 years ago

We will likely want to use a bound service launched from our activity. This should also make the lifecycle of the service easy to manage because it can terminate the gateway once all activities have stopped asking for it.

RangerMauve commented 2 years ago

We'll want to bundle the gateway binary in here: https://www.chromium.org/developers/design-documents/java-resources-on-android/

RangerMauve commented 2 years ago

We could potentially make a Java class for starting the gateway and invoke it via JNI from the C++ code when the context is created. https://chromium.googlesource.com/chromium/src/+/HEAD/base/android/jni_generator/README.md

RangerMauve commented 2 years ago

Maybe we can reuse Chrome's ChildProcessLauncher class?

RangerMauve commented 2 years ago

This class is wrapped by the C++ code in here: https://source.chromium.org/chromium/chromium/src/+/main:content/browser/child_process_launcher_helper_android.cc;l=100;drc=4f70b046f82976388f68084840bd3e9b2811ec27;bpv=1;bpt=1

RangerMauve commented 2 years ago

The CommandLine class might be relevant for us.

It takes a path and some commandline options.

This is used in the ChildProcessLauncher class which I think launches child processes.

This is used to implement the BrowserChildProcessHost and the RendererProcessHost

RangerMauve commented 2 years ago

We could also use the ProcessSingleton class which takes a FilePath to a user directory and has methods for controlling the lifecycle like .Create() and .Cleanup(). Though this might be specific to the Chrome process and won't have options for using the gateway. 🤔

RangerMauve commented 2 years ago

Feels like it might be easier to just use a Java service in Android and invoke some JNI

RangerMauve commented 2 years ago

I think the right place to bind to the IPFSService would be inside ChromeActivity.initDeferrdStartupForActivity which gets invoked once the top level activity is initialized.

Inside it we can do whatever we want with the activity context to bind and unbind the service.

RangerMauve commented 2 years ago

The method I used where we copy the binary from the res/raw folder isn't working because Android Q blocks running binaries from writable directories.

Instead I'm going to find a way to move the binary into the lib folder for the correct architecture and follow something like this

RangerMauve commented 2 years ago

We potentially have no choice but to use gomobile or CGO or something to generate a regular library file to invoke via JNI somehow. 😭

Google's reponse has basically be "Oh well sucks to suck, deal with it GG no Re", and there's been no updates since 2020. 🙃

https://issuetracker.google.com/issues/160129591

The alternative is to publish the app as debuggable? But that seems wrong too.

As well, to use the work around, we'd need to use android:extractnativeLibs="true" which conflicts with chrome setting android:extractnativeLibs="false" in the manifest.

RangerMauve commented 2 years ago

But Google does run multiple processes from the binary... so there must be something going on there.

RangerMauve commented 2 years ago

So, manually copying the daemon as a .so file in the APK doesn't work because the APK is signed. We could either figure out how to generate unsigned APKs, or to keep looking into the build process.

So far it looks like we'll need to modify third_party/android_deps/BUILD.gn to add a .jar or .aar

We might be able to get away with prebuilding an aar with gomobile in @makeworld-the-better-one 's GithubActions workflow, but we might also need to add the gateway as a submodule within third_party/ and have it's own BUILD.gn in there to trigger the build.

To add the gateway to the source tree, we'll need to add the repo to the root DEPS file with a commit and repo.

RangerMauve commented 2 years ago

For example, inside third_party/android_deps/com_android_support_coordinatorlayout there's an .aar file with a bit of metadata which we can likely look at for our structure.

RangerMauve commented 2 years ago

Going to instead base things off of the arcore-android-sdk-client library since it's at the top level of third_party and might be easier to pull in.

RangerMauve commented 2 years ago

Managed to get the AAR and the libgojni.so binary loaded in the GN build system.

Now running into a runtime error due to the MitlicastLock not being enabled. https://github.com/ipfs-shipyard/gomobile-ipfs/issues/68

I think I can just aquire the lock inside the IPFSService before starting the go thread and to relinquish it on destroy (or on error?)

RangerMauve commented 2 years ago

It's working, but we need to figure out why it's crashing on boot sometimes. Might be related to zeroconf errors we're seeing in the logs.

RangerMauve commented 2 years ago

@makeworld-the-better-one fixed the zeroconf issues in the latest version of the daemon and it's all good to go as of #11 !