Files
gitlab-instance-0a899031_re…/redroid.py
2026-04-04 00:21:41 -05:00

171 lines
4.8 KiB
Python

#!/usr/bin/env python3
import argparse
import os
import subprocess
from stuff.houdini import Houdini
from stuff.houdini_hack import Houdini_Hack
from stuff.magisk import Magisk
from stuff.mindthegapps import MindTheGapps
import tools.helper as helper
SUPPORTED_ANDROID_VERSIONS = ["13.0.0"]
def ensure_base_image(container_runtime, android_version):
base_image = "redroid/redroid:{}-latest".format(android_version)
inspect = subprocess.run(
[container_runtime, "image", "inspect", base_image],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
check=False,
)
local_present = inspect.returncode == 0
helper.print_color(
"Trying to pull base image {} first ...".format(base_image),
helper.bcolors.GREEN,
)
pull = subprocess.run([container_runtime, "pull", base_image], check=False)
if pull.returncode == 0:
return "pulled"
if local_present:
helper.print_color(
"Online pull failed, falling back to local image cache ...",
helper.bcolors.YELLOW,
)
return "present"
tar_name = "redroid-redroid-{}-latest.tar".format(android_version)
tar_path = os.path.join(helper.get_image_dir(), tar_name)
if not os.path.isfile(tar_path):
raise FileNotFoundError(
"Online pull for {} failed, local image cache is missing, and offline archive {} was not found".format(
base_image,
tar_path,
)
)
helper.print_color(
"Online pull failed, loading local image archive {} ...".format(tar_path),
helper.bcolors.YELLOW,
)
subprocess.run([container_runtime, "load", "-i", tar_path], check=True)
return tar_path
def build_layers(args):
dockerfile = "FROM redroid/redroid:{}-latest\n".format(args.android)
tags = [args.android]
if args.mindthegapps:
MindTheGapps(args.android).install()
dockerfile += "COPY mindthegapps /\n"
tags.append("mindthegapps")
if args.houdini:
arch = helper.host()[0]
if arch not in {"x86", "x86_64"}:
raise ValueError("Houdini only makes sense on x86/x86_64 hosts")
Houdini(args.android).install()
Houdini_Hack(args.android).install()
dockerfile += "COPY houdini /\n"
tags.append("houdini")
if args.magisk:
Magisk().install()
dockerfile += "COPY magisk /\n"
tags.append("magisk")
return dockerfile, tags
def print_recommended_flow(image_name):
print("\nRecommended 5570 launch")
print(
"python run_redroid.py "
"--image {} "
"--bridge libhoudini "
"--device-profile pixel-7-pro "
"--data-dir ~/data-redroid13 "
"--port 5570 "
"--replace\n".format(image_name)
)
print("Recommended post-boot hardening")
print(
"python bootstrap_redroid.py "
"--serial 127.0.0.1:5570 "
"--device-profile pixel-7-pro "
"--proxy-host auto "
"--install-extreme-script\n"
)
def main():
parser = argparse.ArgumentParser(
description="Build the minimal Android 13 redroid image used for the optimized 5570 setup."
)
parser.add_argument(
"-a",
"--android-version",
dest="android",
default="13.0.0",
choices=SUPPORTED_ANDROID_VERSIONS,
help="Android base image to build from",
)
parser.add_argument(
"-mtg",
"--install-mindthegapps",
dest="mindthegapps",
action="store_true",
help="Install MindTheGapps into the image",
)
parser.add_argument(
"-i",
"--install-houdini",
dest="houdini",
action="store_true",
help="Install libhoudini and the Android 13 compatibility hack",
)
parser.add_argument(
"-m",
"--install-magisk",
dest="magisk",
action="store_true",
help="Install Kitsune Mask / Magisk Delta bootless payload",
)
parser.add_argument(
"-c",
"--container",
dest="container",
default="docker",
choices=["docker", "podman"],
help="Container runtime",
)
args = parser.parse_args()
base_image_source = ensure_base_image(args.container, args.android)
dockerfile, tags = build_layers(args)
print("\nDockerfile\n{}".format(dockerfile))
with open("./Dockerfile", "w", encoding="utf-8") as handle:
handle.write(dockerfile)
image_name = "redroid/redroid:" + "_".join(tags)
subprocess.run([args.container, "build", "-t", image_name, "."], check=True)
helper.print_color(
"Successfully built {}".format(image_name),
helper.bcolors.GREEN,
)
print("Base image source: {}".format(base_image_source))
if args.houdini:
print_recommended_flow(image_name)
if __name__ == "__main__":
main()