Skip to content

Commit 4fc03ac

Browse files
authored
feat: install addons as Magisk modules when root is active (#51)
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.
1 parent c0aa391 commit 4fc03ac

1 file changed

Lines changed: 139 additions & 7 deletions

File tree

first-boot.sh

Lines changed: 139 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,48 @@ prepare_system() {
4141
adb remount
4242
}
4343

44-
install_gapps() {
44+
magisk_active() {
45+
# Magisk env is ready (binaries populated) — either by install_root in this
46+
# session or by a previously-rooted run. Empty /data/adb/magisk doesn't count.
47+
adb shell 'test -x /data/adb/magisk/magiskinit && echo MAGISK_READY' 2>/dev/null | grep -q MAGISK_READY
48+
}
49+
50+
install_gapps_magisk_module() {
51+
echo "Installing GAPPS as a Magisk module ..."
52+
local MOD=/data/adb/modules/gapps
53+
adb push gapps-11/etc /data/local/tmp/gapps-etc
54+
adb push gapps-11/framework /data/local/tmp/gapps-framework
55+
adb push gapps-11/app /data/local/tmp/gapps-app
56+
adb push gapps-11/priv-app /data/local/tmp/gapps-priv-app
57+
adb shell "
58+
rm -rf $MOD
59+
mkdir -p $MOD/system
60+
mv /data/local/tmp/gapps-etc $MOD/system/etc
61+
mv /data/local/tmp/gapps-framework $MOD/system/framework
62+
mv /data/local/tmp/gapps-app $MOD/system/app
63+
mv /data/local/tmp/gapps-priv-app $MOD/system/priv-app
64+
cat > $MOD/module.prop <<'PROP'
65+
id=gapps
66+
name=PICO GAPPS
67+
version=20220503
68+
versionCode=20220503
69+
author=Open GAPPS
70+
description=Open GAPPS PICO for Android 11 x86_64
71+
PROP
72+
"
73+
}
74+
75+
install_gapps_system() {
4576
prepare_system
77+
adb push gapps-11/etc /system
78+
adb push gapps-11/framework /system
79+
adb push gapps-11/app /system
80+
adb push gapps-11/priv-app /system
81+
}
82+
83+
install_gapps() {
84+
adb wait-for-device
85+
adb root
4686
echo "Installing GAPPS ..."
4787
wget https://sourceforge.net/projects/opengapps/files/x86_64/20220503/open_gapps-x86_64-11.0-pico-20220503.zip/download -O gapps-11.zip
4888
unzip gapps-11.zip 'Core/*' -d gapps-11 && rm gapps-11.zip
@@ -51,10 +91,11 @@ install_gapps() {
5191
for f in gapps-11/Core/*.tar; do
5292
tar -x --strip-components 2 -f "$f" -C gapps-11
5393
done
54-
adb push gapps-11/etc /system
55-
adb push gapps-11/framework /system
56-
adb push gapps-11/app /system
57-
adb push gapps-11/priv-app /system
94+
if magisk_active; then
95+
install_gapps_magisk_module
96+
else
97+
install_gapps_system
98+
fi
5899
rm -r gapps-11
59100
adb reboot
60101
adb wait-for-device
@@ -63,21 +104,96 @@ install_gapps() {
63104

64105
install_root() {
65106
adb wait-for-device
107+
adb root
66108
echo "Root Script Starting..."
67109
# Root the AVD by patching the ramdisk.
68110
git clone https://gitlab.com/newbit/rootAVD.git
69111
pushd rootAVD
70112
sed -i 's/read -t 10 choice/choice=1/' rootAVD.sh
71113
./rootAVD.sh system-images/android-30/default/x86_64/ramdisk.img
72114
cp /opt/android-sdk/system-images/android-30/default/x86_64/ramdisk.img /data/android.avd/ramdisk.img
115+
116+
# Pre-populate /data/adb/magisk so Magisk's env-check passes on next boot.
117+
# rootAVD only patches the ramdisk; the "additional setup" tap in the Magisk
118+
# app would normally extract Magisk.zip into /data/adb/magisk/ (with the
119+
# lib*.so files renamed to their binary names). Doing it here means the next
120+
# QEMU restart comes up with a complete Magisk environment, no manual setup
121+
# prompt, and any modules in /data/adb/modules/ are loaded on boot.
122+
echo "Bootstrapping Magisk environment ..."
123+
rm -rf /tmp/magisk-stage
124+
mkdir -p /tmp/magisk-stage
125+
unzip -q -o Magisk.zip 'lib/*' 'assets/*' -d /tmp/magisk-stage
126+
pushd /tmp/magisk-stage/lib/x86_64
127+
for f in lib*.so; do mv "$f" "$(echo "$f" | sed -e 's/^lib//' -e 's/\.so$//')"; done
128+
cp -f ../x86/libmagisk32.so magisk32 2>/dev/null || true
129+
popd
130+
adb push /tmp/magisk-stage/lib/x86_64/. /data/local/tmp/magiskbin/
131+
adb push /tmp/magisk-stage/assets/. /data/local/tmp/magiskbin/
132+
adb shell '
133+
mkdir -p /data/adb/magisk
134+
cp -a /data/local/tmp/magiskbin/. /data/adb/magisk/
135+
rm -f /data/adb/magisk/bootctl /data/adb/magisk/main.jar \
136+
/data/adb/magisk/module_installer.sh /data/adb/magisk/uninstaller.sh
137+
chmod -R 755 /data/adb/magisk
138+
rm -rf /data/local/tmp/magiskbin
139+
'
140+
rm -rf /tmp/magisk-stage
141+
73142
popd
74143
echo "Root Done"
75144
sleep 10
76145
rm -r rootAVD
77146
touch /data/.root-done
78147
}
79148

80-
install_arm_translation() {
149+
install_arm_translation_magisk_module() {
150+
echo "Installing ARM translation as a Magisk module ..."
151+
local MOD=/data/adb/modules/ndk_translation
152+
adb push /opt/ndk-translation /data/local/tmp/ndk
153+
adb shell "
154+
rm -rf $MOD
155+
mkdir -p $MOD/system/bin $MOD/system/etc $MOD/system/lib $MOD/system/lib64
156+
cp -r /data/local/tmp/ndk/bin/. $MOD/system/bin/
157+
cp -r /data/local/tmp/ndk/etc/. $MOD/system/etc/
158+
cp -r /data/local/tmp/ndk/lib/. $MOD/system/lib/
159+
cp -r /data/local/tmp/ndk/lib64/. $MOD/system/lib64/
160+
rm -rf /data/local/tmp/ndk
161+
chmod 755 $MOD/system/bin/ndk_translation_program_runner_binfmt_misc $MOD/system/bin/ndk_translation_program_runner_binfmt_misc_arm64
162+
chmod -R 755 $MOD/system/bin/arm $MOD/system/bin/arm64
163+
cat > $MOD/module.prop <<'PROP'
164+
id=ndk_translation
165+
name=NDK Translation (ARM on x86)
166+
version=v0.2.3
167+
versionCode=23
168+
author=dockerify-android
169+
description=Run ARM/ARM64 apps on x86_64 emulator via libndk_translation native bridge
170+
PROP
171+
cat > $MOD/system.prop <<'PROP'
172+
ro.product.cpu.abilist=x86_64,x86,arm64-v8a,armeabi-v7a,armeabi
173+
ro.product.cpu.abilist32=x86,armeabi-v7a,armeabi
174+
ro.product.cpu.abilist64=x86_64,arm64-v8a
175+
ro.dalvik.vm.isa.arm=x86
176+
ro.dalvik.vm.isa.arm64=x86_64
177+
ro.enable.native.bridge.exec=1
178+
ro.enable.native.bridge.exec64=1
179+
ro.dalvik.vm.native.bridge=libndk_translation.so
180+
ro.ndk_translation.version=0.2.3
181+
PROP
182+
cat > $MOD/post-fs-data.sh <<'PFS'
183+
#!/system/bin/sh
184+
# init.rc files aren't parsed when injected via Magisk overlay (init scans
185+
# /system/etc/init early, before module mounts). Register binfmt_misc here.
186+
mount binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc 2>/dev/null
187+
for f in arm_exe arm_dyn arm64_exe arm64_dyn; do
188+
[ -f \"\$MODPATH/system/etc/binfmt_misc/\$f\" ] &&
189+
cat \"\$MODPATH/system/etc/binfmt_misc/\$f\" > /proc/sys/fs/binfmt_misc/register 2>/dev/null
190+
done
191+
PFS
192+
chmod 755 $MOD/post-fs-data.sh
193+
"
194+
}
195+
196+
install_arm_translation_system() {
81197
prepare_system
82198
echo "Installing ARM translation (ndk_translation) ..."
83199

@@ -109,7 +225,18 @@ ro.dalvik.vm.native.bridge=libndk_translation.so
109225
ro.ndk_translation.version=0.2.3
110226
EOF
111227
'
228+
}
112229

230+
install_arm_translation() {
231+
adb wait-for-device
232+
adb root
233+
# On a live-Magisk device, /system is wrapped in a read-only magic mount;
234+
# install as a Magisk module so the changes land via Magisk's own overlay.
235+
if magisk_active; then
236+
install_arm_translation_magisk_module
237+
else
238+
install_arm_translation_system
239+
fi
113240
adb reboot
114241
adb wait-for-device
115242
touch /data/.arm-translation-done
@@ -144,8 +271,13 @@ fi
144271
# Each install is self-contained: prepares the system, applies its changes,
145272
# reboots, waits for adbd, then writes its done-marker. Safe to run after the
146273
# first boot — only the missing markers will fire.
147-
[ "$gapps_needed" = true ] && install_gapps
274+
#
275+
# Root is installed first so it can bootstrap /data/adb/magisk/; the gapps
276+
# and arm_translation installs then detect a ready Magisk env and write their
277+
# payload to /data/adb/modules/<id>/ instead of /system. Modules sit dormant
278+
# until the next QEMU restart loads the patched ramdisk and Magisk activates.
148279
[ "$root_needed" = true ] && install_root
280+
[ "$gapps_needed" = true ] && install_gapps
149281
[ "$arm_translation_needed" = true ] && install_arm_translation
150282
apply_settings
151283
copy_extras

0 commit comments

Comments
 (0)