Repository navigation
android: Let debug builds of host-driven Activities load a pushed library without reinstalling - #39
Open
Bombatomica64 wants to merge 1 commit into
Open
Bombatomica64 wants to merge 1 commit into
Bombatomica64 wants to merge 1 commit into
Conversation
Loads lib<name>.so once per process. In a debuggable build it prefers files/dev/lib<name>.so in the app's data directory, so a dev tool can push a new build of the Rust code and restart the app without reinstalling. Release builds always load the packaged library. Opt-in: nothing calls it unless the host does. NativeActivity hosts can't use it (NativeActivity loads the packaged library itself). Implements the loader discussed in longbridge#34. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the loader discussed in #34.
A Java helper,
GpuiLibraryLoader, for host-driven Activities (android::host) to call instead ofSystem.loadLibrary. In a debuggable build, if a dev tool has pushed a newer build of the Rust library to the app's data directory, it loads that one, so a Rust change no longer needs Gradle and an APK install. This PR adds no Rust code and no dependency. Nothing calls the loader unless a host chooses to.Change
example/android/gradle/app/src/main/java/dev/gpui/mobile/GpuiLibraryLoader.java(47 lines), next to the other Java helpers that hosts copy.GpuiLibraryLoader.load(context, name)loadslib<name>.soonce per process:ApplicationInfo.FLAG_DEBUGGABLE) andfiles/dev/lib<name>.soexists, it callsSystem.loadon that file and logsloading dev library …;System.loadLibrary(name), as today.host.rsmodule doc ("What the host has to do") now starts with loading the library, and mentions the loader.Development only
The loader is for development loops only. Store policy forbids downloading executable code, so this is not, and cannot become, an over-the-air update path (see the comment on #34). Two things keep it out of release builds:
files/devpath is not even checked.files/withadb shell run-as <package>, andrun-asonly works for debuggable packages.NativeActivityhosts can't use it:NativeActivityloads the packaged library itself. The example app is aNativeActivity, so it doesn't call the loader. The class is there for host-driven apps to copy, likeGpuiInputActivity.How it is used
cargo-gpui uses it for
cargo gpui reload. The tool rebuilds the library, pushes a zstd delta, copies it read-only intofiles/dev/withrun-as(Android 14 requires dynamically loaded code to be read-only), and restarts the app on the screen it was on. On a OnePlus CPH2581 (Android 16) reached over an adb tunnel, a reload with a 1.4 MB delta takes about 8.3 s, with no install.The same tool's hot patching (
cargo gpui dev) doesn't need this loader. It is built on Subsecond from Dioxus, and its patch builder adapts parts of the Dioxus CLI (dx serve --hotpatch), credited in that repo. A reload with this loader covers the changes a patch can't make, such as a struct's layout or the dependencies.From the hot-patching prototype: a title, a colour and a layout changed while the app was running, and the click counter kept its value (3).
Testing
cargo gpui reloadon the OnePlus CPH2581 (Android 16). After a reload the log showsloading dev library …. Without a pushed file the packaged library loads.javac --release 17againstandroid-34/android.jarwith-Xlint:allgives no warnings.cargo fmt --all -- --check,cargo check --target aarch64-linux-android --all-targets(crate andexample/),cargo clippy --target aarch64-linux-android(no new warnings) andcargo test --liball pass. Onlyhost.rsdocs change on the Rust side.One change from the fork version: the "already loaded" flag is now set after a successful load, not before.
Open questions
#34 also asked where the tool should live (stay separate, move under longbridge, or come into gpui-mobile). This PR only adds the loader, which is useful whatever you decide. If you would rather keep the loader in cargo-gpui as well, that works too.
🤖 Generated with Claude Code