mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-03-03 16:56:10 +00:00
Support ./build.py emulator with an APK argument
This commit is contained in:
parent
afbfb81837
commit
494615d9a0
245
build.py
245
build.py
@ -2,7 +2,6 @@
|
||||
import argparse
|
||||
import copy
|
||||
import glob
|
||||
import lzma
|
||||
import multiprocessing
|
||||
import os
|
||||
import platform
|
||||
@ -57,14 +56,6 @@ if is_windows:
|
||||
if not sys.version_info >= (3, 8):
|
||||
error("Requires Python 3.8+")
|
||||
|
||||
try:
|
||||
sdk_path = Path(os.environ["ANDROID_HOME"])
|
||||
except KeyError:
|
||||
try:
|
||||
sdk_path = Path(os.environ["ANDROID_SDK_ROOT"])
|
||||
except KeyError:
|
||||
error("Please set Android SDK path to environment variable ANDROID_HOME")
|
||||
|
||||
cpu_count = multiprocessing.cpu_count()
|
||||
os_name = platform.system().lower()
|
||||
|
||||
@ -80,17 +71,6 @@ default_targets = {"magisk", "magiskinit", "magiskboot", "magiskpolicy"}
|
||||
support_targets = default_targets | {"resetprop"}
|
||||
rust_targets = {"magisk", "magiskinit", "magiskboot", "magiskpolicy"}
|
||||
|
||||
# Common paths
|
||||
ndk_root = sdk_path / "ndk"
|
||||
ndk_path = ndk_root / "magisk"
|
||||
ndk_build = ndk_path / "ndk-build"
|
||||
rust_bin = ndk_path / "toolchains" / "rust" / "bin"
|
||||
llvm_bin = ndk_path / "toolchains" / "llvm" / "prebuilt" / f"{os_name}-x86_64" / "bin"
|
||||
cargo = rust_bin / "cargo"
|
||||
gradlew = Path.cwd() / "gradlew"
|
||||
adb_path = sdk_path / "platform-tools" / "adb"
|
||||
native_gen_path = Path("native", "out", "generated").resolve()
|
||||
|
||||
# Global vars
|
||||
config = {}
|
||||
args = {}
|
||||
@ -162,10 +142,6 @@ def cmd_out(cmds: list):
|
||||
)
|
||||
|
||||
|
||||
def xz(data):
|
||||
return lzma.compress(data, preset=9, check=lzma.CHECK_NONE)
|
||||
|
||||
|
||||
###############
|
||||
# Build Native
|
||||
###############
|
||||
@ -256,6 +232,7 @@ def build_cpp_src(targets: set):
|
||||
|
||||
|
||||
def run_cargo(cmds):
|
||||
ensure_paths()
|
||||
env = os.environ.copy()
|
||||
env["PATH"] = f'{rust_bin}{os.pathsep}{env["PATH"]}'
|
||||
env["CARGO_BUILD_RUSTC"] = str(rust_bin / f"rustc{EXE_EXT}")
|
||||
@ -333,6 +310,7 @@ def dump_flag_header():
|
||||
flag_txt += f'#define MAGISK_VER_CODE {config["versionCode"]}\n'
|
||||
flag_txt += f"#define MAGISK_DEBUG {0 if args.release else 1}\n"
|
||||
|
||||
native_gen_path = Path("native", "out", "generated")
|
||||
native_gen_path.mkdir(mode=0o755, parents=True, exist_ok=True)
|
||||
write_if_diff(native_gen_path / "flags.h", flag_txt)
|
||||
|
||||
@ -342,6 +320,8 @@ def dump_flag_header():
|
||||
|
||||
|
||||
def build_native():
|
||||
ensure_paths()
|
||||
|
||||
# Verify NDK install
|
||||
try:
|
||||
with open(Path(ndk_path, "ONDK_VERSION"), "r") as ondk_ver:
|
||||
@ -401,13 +381,14 @@ def find_jdk():
|
||||
if no_jdk:
|
||||
error(
|
||||
"Please set Android Studio's path to environment variable ANDROID_STUDIO,\n"
|
||||
+ "or install JDK 17 and make sure 'javac' is available in PATH"
|
||||
+ "or install JDK 21 and make sure 'javac' is available in PATH"
|
||||
)
|
||||
|
||||
return env
|
||||
|
||||
|
||||
def build_apk(module: str):
|
||||
ensure_paths()
|
||||
env = find_jdk()
|
||||
|
||||
build_type = "Release" if args.release else "Debug"
|
||||
@ -479,6 +460,7 @@ def build_test():
|
||||
|
||||
|
||||
def cleanup():
|
||||
ensure_paths()
|
||||
support_targets = {"native", "cpp", "rust", "app"}
|
||||
if args.targets:
|
||||
targets = set(args.targets) & support_targets
|
||||
@ -540,6 +522,7 @@ def cargo_cli():
|
||||
|
||||
|
||||
def setup_ndk():
|
||||
ensure_paths()
|
||||
ndk_ver = config["ondkVersion"]
|
||||
url = f"https://github.com/topjohnwu/ondk/releases/download/{ndk_ver}/ondk-{ndk_ver}-{os_name}.tar.xz"
|
||||
ndk_archive = url.split("/")[-1]
|
||||
@ -558,79 +541,6 @@ def setup_ndk():
|
||||
mv(ondk_path, ndk_path)
|
||||
|
||||
|
||||
def push_files(script):
|
||||
abi = cmd_out([adb_path, "shell", "getprop", "ro.product.cpu.abi"])
|
||||
if not abi:
|
||||
error("Cannot detect emulator ABI")
|
||||
|
||||
apk = Path(
|
||||
config["outdir"], ("app-release.apk" if args.release else "app-debug.apk")
|
||||
)
|
||||
|
||||
# Extract busybox from APK
|
||||
busybox = Path(config["outdir"], "busybox")
|
||||
with ZipFile(apk) as zf:
|
||||
with zf.open(f"lib/{abi}/libbusybox.so") as libbb:
|
||||
with open(busybox, "wb") as bb:
|
||||
bb.write(libbb.read())
|
||||
|
||||
try:
|
||||
proc = execv([adb_path, "push", busybox, script, "/data/local/tmp"])
|
||||
if proc.returncode != 0:
|
||||
error("adb push failed!")
|
||||
finally:
|
||||
rm_rf(busybox)
|
||||
|
||||
proc = execv([adb_path, "push", apk, "/data/local/tmp/magisk.apk"])
|
||||
if proc.returncode != 0:
|
||||
error("adb push failed!")
|
||||
|
||||
|
||||
def setup_avd():
|
||||
if not args.skip:
|
||||
build_all()
|
||||
|
||||
header("* Setting up emulator")
|
||||
|
||||
push_files(Path("scripts", "avd_magisk.sh"))
|
||||
|
||||
proc = execv([adb_path, "shell", "sh", "/data/local/tmp/avd_magisk.sh"])
|
||||
if proc.returncode != 0:
|
||||
error("avd_magisk.sh failed!")
|
||||
|
||||
|
||||
def patch_avd_file():
|
||||
if not args.skip:
|
||||
build_all()
|
||||
|
||||
input = Path(args.image)
|
||||
if args.output:
|
||||
output = Path(args.output)
|
||||
else:
|
||||
output = input.parent / f"{input.name}.magisk"
|
||||
|
||||
src_file = f"/data/local/tmp/{input.name}"
|
||||
out_file = f"{src_file}.magisk"
|
||||
|
||||
header(f"* Patching {input.name}")
|
||||
|
||||
push_files(Path("scripts", "avd_patch.sh"))
|
||||
|
||||
proc = execv([adb_path, "push", input, "/data/local/tmp"])
|
||||
if proc.returncode != 0:
|
||||
error("adb push failed!")
|
||||
|
||||
proc = execv([adb_path, "shell", "sh", "/data/local/tmp/avd_patch.sh", src_file])
|
||||
if proc.returncode != 0:
|
||||
error("avd_patch.sh failed!")
|
||||
|
||||
proc = execv([adb_path, "pull", out_file, output])
|
||||
if proc.returncode != 0:
|
||||
error("adb pull failed!")
|
||||
|
||||
header(f"Output: {output}")
|
||||
|
||||
|
||||
def setup_rustup():
|
||||
wrapper_dir = Path(args.wrapper_dir)
|
||||
rm_rf(wrapper_dir)
|
||||
@ -660,10 +570,125 @@ def setup_rustup():
|
||||
|
||||
|
||||
##################
|
||||
# Config and args
|
||||
# AVD and testing
|
||||
##################
|
||||
|
||||
|
||||
def push_files(script):
|
||||
if args.build:
|
||||
build_all()
|
||||
ensure_adb()
|
||||
|
||||
abi = cmd_out([adb_path, "shell", "getprop", "ro.product.cpu.abi"])
|
||||
if not abi:
|
||||
error("Cannot detect emulator ABI")
|
||||
|
||||
if args.apk:
|
||||
apk = Path(args.apk)
|
||||
else:
|
||||
apk = Path(
|
||||
config["outdir"], ("app-release.apk" if args.release else "app-debug.apk")
|
||||
)
|
||||
|
||||
# Extract busybox from APK
|
||||
busybox = Path(config["outdir"], "busybox")
|
||||
with ZipFile(apk) as zf:
|
||||
with zf.open(f"lib/{abi}/libbusybox.so") as libbb:
|
||||
with open(busybox, "wb") as bb:
|
||||
bb.write(libbb.read())
|
||||
|
||||
try:
|
||||
proc = execv([adb_path, "push", busybox, script, "/data/local/tmp"])
|
||||
if proc.returncode != 0:
|
||||
error("adb push failed!")
|
||||
finally:
|
||||
rm_rf(busybox)
|
||||
|
||||
proc = execv([adb_path, "push", apk, "/data/local/tmp/magisk.apk"])
|
||||
if proc.returncode != 0:
|
||||
error("adb push failed!")
|
||||
|
||||
|
||||
def setup_avd():
|
||||
header("* Setting up emulator")
|
||||
|
||||
push_files(Path("scripts", "avd_magisk.sh"))
|
||||
|
||||
proc = execv([adb_path, "shell", "sh", "/data/local/tmp/avd_magisk.sh"])
|
||||
if proc.returncode != 0:
|
||||
error("avd_magisk.sh failed!")
|
||||
|
||||
|
||||
def patch_avd_file():
|
||||
input = Path(args.image)
|
||||
output = Path(args.output)
|
||||
|
||||
header(f"* Patching {input.name}")
|
||||
|
||||
push_files(Path("scripts", "avd_patch.sh"))
|
||||
|
||||
proc = execv([adb_path, "push", input, "/data/local/tmp"])
|
||||
if proc.returncode != 0:
|
||||
error("adb push failed!")
|
||||
|
||||
src_file = f"/data/local/tmp/{input.name}"
|
||||
out_file = f"{src_file}.magisk"
|
||||
|
||||
proc = execv([adb_path, "shell", "sh", "/data/local/tmp/avd_patch.sh", src_file])
|
||||
if proc.returncode != 0:
|
||||
error("avd_patch.sh failed!")
|
||||
|
||||
proc = execv([adb_path, "pull", out_file, output])
|
||||
if proc.returncode != 0:
|
||||
error("adb pull failed!")
|
||||
|
||||
header(f"Output: {output}")
|
||||
|
||||
|
||||
##########################
|
||||
# Config, paths, argparse
|
||||
##########################
|
||||
|
||||
|
||||
def ensure_paths():
|
||||
global sdk_path, ndk_root, ndk_path, ndk_build, rust_bin
|
||||
global llvm_bin, cargo, gradlew, adb_path, native_gen_path
|
||||
|
||||
# Skip if already initialized
|
||||
if "sdk_path" in globals():
|
||||
return
|
||||
|
||||
try:
|
||||
sdk_path = Path(os.environ["ANDROID_HOME"])
|
||||
except KeyError:
|
||||
try:
|
||||
sdk_path = Path(os.environ["ANDROID_SDK_ROOT"])
|
||||
except KeyError:
|
||||
error("Please set Android SDK path to environment variable ANDROID_HOME")
|
||||
|
||||
ndk_root = sdk_path / "ndk"
|
||||
ndk_path = ndk_root / "magisk"
|
||||
ndk_build = ndk_path / "ndk-build"
|
||||
rust_bin = ndk_path / "toolchains" / "rust" / "bin"
|
||||
llvm_bin = (
|
||||
ndk_path / "toolchains" / "llvm" / "prebuilt" / f"{os_name}-x86_64" / "bin"
|
||||
)
|
||||
cargo = rust_bin / "cargo"
|
||||
adb_path = sdk_path / "platform-tools" / "adb"
|
||||
gradlew = Path.cwd() / "gradlew"
|
||||
|
||||
|
||||
# We allow using several functionality with only ADB
|
||||
def ensure_adb():
|
||||
global adb_path
|
||||
if "adb_path" not in globals():
|
||||
adb_path = shutil.which("adb")
|
||||
if not adb_path:
|
||||
error("Command 'adb' cannot be found in PATH")
|
||||
else:
|
||||
adb_path = Path(adb_path)
|
||||
|
||||
|
||||
def parse_props(file):
|
||||
props = {}
|
||||
with open(file, "r") as f:
|
||||
@ -761,17 +786,19 @@ def parse_args():
|
||||
ndk_parser = subparsers.add_parser("ndk", help="setup Magisk NDK")
|
||||
|
||||
emu_parser = subparsers.add_parser("emulator", help="setup AVD for development")
|
||||
emu_parser.add_argument("apk", help="a Magisk APK to use", nargs="?")
|
||||
emu_parser.add_argument(
|
||||
"-s", "--skip", action="store_true", help="skip building binaries and the app"
|
||||
"-b", "--build", action="store_true", help="build before patching"
|
||||
)
|
||||
|
||||
avd_patch_parser = subparsers.add_parser(
|
||||
"avd_patch", help="patch AVD ramdisk.img or init_boot.img"
|
||||
)
|
||||
avd_patch_parser.add_argument("image", help="path to ramdisk.img or init_boot.img")
|
||||
avd_patch_parser.add_argument("output", help="optional output file name", nargs="?")
|
||||
avd_patch_parser.add_argument("output", help="output file name")
|
||||
avd_patch_parser.add_argument("--apk", help="a Magisk APK to use")
|
||||
avd_patch_parser.add_argument(
|
||||
"-s", "--skip", action="store_true", help="skip building binaries and the app"
|
||||
"-b", "--build", action="store_true", help="build before patching"
|
||||
)
|
||||
|
||||
cargo_parser = subparsers.add_parser(
|
||||
@ -807,7 +834,13 @@ def parse_args():
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
args = parse_args()
|
||||
load_config()
|
||||
vars(args)["force_out"] = False
|
||||
args.func()
|
||||
def main():
|
||||
global args
|
||||
args = parse_args()
|
||||
load_config()
|
||||
vars(args)["force_out"] = False
|
||||
args.func()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
13
docs/faq.md
13
docs/faq.md
@ -7,9 +7,10 @@ If you have USB debugging enabled in developer options, connect your phone to th
|
||||
If unfortunately you do not have USB debugging enabled you can boot using the Safe Mode key combo to cause Magisk to create an empty file named 'disable' in modules directories which disables modules when next booted with Magisk. Most modern Android devices support such a special key combo at boot to enter system Safe Mode as an emergency option, but **please note** that Magisk's key combo detection occurs _earlier_ than system detection so the key combo timing indicated by many online guides may need to be altered to activate Magisk's Safe Mode. (It's possible to activate system Safe Mode but not Magisk Safe Mode and vice versa.)
|
||||
|
||||
The following details should ensure that modules are properly disabled:
|
||||
1) Many online guides for entering Safe Mode say 'When the animated logo appears, press and hold the volume down button until the system boots' or similar. This may actually be _too late_ for Magisk detection however and result in activating system Safe Mode but modules are not disabled.
|
||||
2) By pressing the volume down button some seconds before the animation and releasing it as soon as the boot animation appears, Magisk's Safe Mode should be activated without activating system Safe Mode (thus avoiding disabling other device and app settings) and the device should then simply boot to normal system with modules disabled.
|
||||
3) By pressing the volume down button some seconds before the animation and holding it until the system boots, both Magisk's Safe Mode and system Safe Mode should be activated. Next, after booting back to normal system, modules will be disabled.
|
||||
|
||||
1. Many online guides for entering Safe Mode say 'When the animated logo appears, press and hold the volume down button until the system boots' or similar. This may actually be _too late_ for Magisk detection however and result in activating system Safe Mode but modules are not disabled.
|
||||
2. By pressing the volume down button some seconds before the animation and releasing it as soon as the boot animation appears, Magisk's Safe Mode should be activated without activating system Safe Mode (thus avoiding disabling other device and app settings) and the device should then simply boot to normal system with modules disabled.
|
||||
3. By pressing the volume down button some seconds before the animation and holding it until the system boots, both Magisk's Safe Mode and system Safe Mode should be activated. Next, after booting back to normal system, modules will be disabled.
|
||||
|
||||
### Q: Why is X app detecting root?
|
||||
|
||||
@ -23,6 +24,6 @@ When you open the hidden Magisk app, it will offer you the option to create a sh
|
||||
|
||||
### Q: How to use Magisk in the emulator?
|
||||
|
||||
[avd_magisk.sh](../scripts/avd_magisk.sh) script can run Magisk in the emulator, Magisk will be lost after reboot, so please re-execute the script instead of tapping the reboot button.
|
||||
Only official Android Virtual Device (AVD) is supported, other emulators may work, but emulators without SELinux will never be supported.
|
||||
For more information, read the script comments.
|
||||
With the emulator running and accessible via ADB, run `./build.py emulator <path to Magisk APK>` to temporarily install Magisk on to the emulator. The patch is not persistent, meaning Magisk will be lost after a reboot, so re-execute the script to emulate a reboot if required.
|
||||
|
||||
The script is only tested on the official Android Virtual Device (AVD) shipped alongside Android Studio; other emulators may work, but the emulator must have SELinux enabled.
|
||||
|
@ -2,14 +2,7 @@
|
||||
# AVD Magisk Setup
|
||||
#####################################################################
|
||||
#
|
||||
# Support API level: 23 - 34
|
||||
#
|
||||
# Push files to AVD:
|
||||
# /data/local/tmp/magisk.apk
|
||||
# /data/local/tmp/busybox (extract from apk)
|
||||
# /data/local/tmp/avd_magisk.sh (this file)
|
||||
# Then execute, you must use non-interactive shell:
|
||||
# adb shell sh /data/local/tmp/avd_magisk.sh
|
||||
# Support API level: 23 - 35
|
||||
#
|
||||
# For developing Magisk, just use:
|
||||
# ./build.py emulator
|
||||
|
@ -2,7 +2,7 @@
|
||||
# AVD MagiskInit Setup
|
||||
#####################################################################
|
||||
#
|
||||
# Support API level: 23 - 34
|
||||
# Support API level: 23 - 35
|
||||
#
|
||||
# With an emulator booted and accessible via ADB, usage:
|
||||
# ./build.py avd_patch path/to/booted/avd-image/ramdisk.img
|
||||
@ -18,7 +18,7 @@
|
||||
# rootfs w/o early mount: API 23 - 25
|
||||
# rootfs with early mount: API 26 - 27
|
||||
# Legacy system-as-root: API 28
|
||||
# 2 stage init: API 29 - 34
|
||||
# 2 stage init: API 29 - 35
|
||||
#####################################################################
|
||||
|
||||
if [ ! -f /system/build.prop ]; then
|
||||
|
@ -146,7 +146,7 @@ test_main() {
|
||||
|
||||
if [ -z "$AVD_TEST_SKIP_DEBUG" ]; then
|
||||
# Patch and test debug build
|
||||
./build.py avd_patch -s "$ramdisk" magisk_patched.img
|
||||
./build.py avd_patch "$ramdisk" magisk_patched.img
|
||||
kill -INT $emu_pid
|
||||
wait $emu_pid
|
||||
test_emu debug $api
|
||||
@ -154,7 +154,7 @@ test_main() {
|
||||
|
||||
if [ -z "$AVD_TEST_SKIP_RELEASE" ]; then
|
||||
# Patch and test release build
|
||||
./build.py -r avd_patch -s "$ramdisk" magisk_patched.img
|
||||
./build.py -r avd_patch "$ramdisk" magisk_patched.img
|
||||
kill -INT $emu_pid
|
||||
wait $emu_pid
|
||||
test_emu release $api
|
||||
|
@ -84,11 +84,11 @@ test_main() {
|
||||
adb wait-for-device
|
||||
|
||||
# Patch and test debug build
|
||||
./build.py avd_patch -s "$CF_HOME/init_boot.img" magisk_patched.img
|
||||
./build.py avd_patch "$CF_HOME/init_boot.img" magisk_patched.img
|
||||
test_cf debug
|
||||
|
||||
# Patch and test release build
|
||||
./build.py -r avd_patch -s "$CF_HOME/init_boot.img" magisk_patched.img
|
||||
./build.py -r avd_patch "$CF_HOME/init_boot.img" magisk_patched.img
|
||||
test_cf release
|
||||
|
||||
# Cleanup
|
||||
|
Loading…
x
Reference in New Issue
Block a user