Skip to content

feat: install addons as Magisk modules when root is active#49

Merged
Shmayro merged 1 commit into
refactor/self-contained-installsfrom
feat/arm-translation-magisk-module
May 29, 2026
Merged

feat: install addons as Magisk modules when root is active#49
Shmayro merged 1 commit into
refactor/self-contained-installsfrom
feat/arm-translation-magisk-module

Conversation

@Shmayro
Copy link
Copy Markdown
Owner

@Shmayro Shmayro commented May 29, 2026

Stacked on #48. When ROOT_SETUP=1, install the addons as Magisk modules instead of direct /system pushes, and finish the Magisk install inline so no manual "additional setup" tap is needed in the Magisk app.

Why

rootAVD only patches the ramdisk. The Magisk app's first-launch "additional setup" prompt is what normally populates /data/adb/magisk/ with the actual binaries (magisk64, magiskinit, magiskboot, magiskpolicy, busybox, stub.apk, etc.) — without that step, Magisk reports "environment incomplete, abort" on every boot and refuses to mount modules. That means modules dropped under /data/adb/modules/<id>/ are silently ignored.

Result of leaving it alone:

  • Addon files have to be pushed to /system directly, polluting the qcow2 system overlay
  • Once Magisk is live, /system is wrapped in a read-only magic mount and any subsequent push-based install fails (the INSTALL_FAILED you'd hit if you toggle a flag on an already-rooted container)
  • User has to open the Magisk app and tap "additional setup" before modules are usable

Changes

install_root

  • adb root before any /data/adb/* write (the previous omission silently failed every write as the shell user — turned out to be the root cause of an earlier "fix" that didn't fix anything).
  • After rootAVD.sh patches the ramdisk, reproduce the Magisk app's FixEnv: extract Magisk.zip's lib/x86_64/ and assets/, rename lib<name>.so<name> (same naming the Magisk updater-script does), drop the app-only files (bootctl, main.jar, module_installer.sh, uninstaller.sh), chmod -R 755. Now /data/adb/magisk/ is complete by the time the patched ramdisk activates on the next QEMU restart.

install_gapps / install_arm_translation

  • New _magisk_module siblings to the existing _system paths. They write the payload under /data/adb/modules/<id>/system/ plus a module.prop.
  • For ARM specifically: a system.prop with the ABI / native-bridge properties (Magisk's resetprop overrides the ro.* first-write-wins rule) and a post-fs-data.sh that registers binfmt_misc (init.rc files injected via Magisk overlay aren't parsed by init).
  • install_arm_translation() / install_gapps() branch on a tightened magisk_active() — now checks for the magiskinit binary, not just the directory, so the rootAVD-empty case correctly evaluates to "not yet ready".

Main flow ordering

  • install_root now runs before install_gapps and install_arm_translation. When ROOT is enabled, the magisk-env is complete by the time the other two run, so they automatically take the module path.

Result

Verified end-to-end on a fresh AVD with ROOT_SETUP=GAPPS_SETUP=ARM_TRANSLATION=1:

  • /data/adb/magisk/ populated with magisk64, magiskinit, magiskboot, magiskpolicy, busybox, stub.apk, etc.
  • /data/adb/modules/ contains gapps/ and ndk_translation/
  • adb shell getprop ro.product.cpu.abilistx86_64,x86,arm64-v8a,armeabi-v7a,armeabi
  • adb shell ls /system/priv-app/ shows Google services (GoogleBackupTransport, GoogleExtServices, …) via Magisk's overlay
  • adb install v2rayNG_2.1.7_arm64-v8a.apk succeeds and the app launches cleanly (both com.v2ray.ang and com.v2ray.ang:bg processes alive, no SIGABRT in native_bridge_initialize)
  • No "Additional setup required" prompt when opening the Magisk app

When ROOT_SETUP is enabled, finish the Magisk install inline so the
addon installs land as proper Magisk modules instead of direct /system
pushes. Reproduces what the Magisk app does on first launch (the
"additional setup" prompt) without requiring a manual tap.

install_root now:
- Calls adb root first (the previous omission silently failed all
  writes into /data/adb/ as the shell user)
- After rootAVD patches the ramdisk, extracts Magisk.zip's lib/x86_64/
  and assets/ and stages them into /data/adb/magisk/, renaming
  lib<name>.so -> <name> and dropping bootctl/main.jar/installer scripts
  — same layout the Magisk updater-script produces

install_gapps and install_arm_translation gain a parallel
_magisk_module path that writes the payload under
/data/adb/modules/<id>/system/, plus a module.prop and (for ARM) a
system.prop with the ABI / native-bridge properties and a
post-fs-data.sh that registers binfmt_misc (init.rc files injected via
Magisk overlay aren't parsed by init).

magisk_active() checks for the magiskinit binary rather than just the
/data/adb/magisk directory, since the rootAVD-patched ramdisk creates
that directory empty and the old check returned a false positive.

The main flow now calls install_root before install_gapps and
install_arm_translation so the latter two see a populated Magisk env
and take the module path automatically.

Verified end-to-end on a fresh AVD with ROOT_SETUP=GAPPS_SETUP=
ARM_TRANSLATION=1: /data/adb/magisk/ ends up populated, modules
created under /data/adb/modules/{gapps,ndk_translation}, ABI list
advertises arm64-v8a,armeabi-v7a,armeabi, Google services visible at
/system/priv-app/ via Magisk's overlay, and an arm64-v8a-only APK
(v2rayNG) installs and launches.
@Shmayro Shmayro marked this pull request as ready for review May 29, 2026 03:30
@Shmayro Shmayro merged commit 79cc247 into refactor/self-contained-installs May 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant