# redroid-android13 This repo is the minimal Android 13 redroid bundle that matches the optimized `5570` instance. It keeps only the parts that were actually used: - `redroid/redroid:13.0.0` - `MindTheGapps` - `libhoudini` - `Kitsune Mask / Magisk Delta` - `Pixel 7 Pro` device profile - the `post-fs-data` fix that keeps `Magisk Installed` and the settings page healthy ## Included files - `redroid.py` - `run_redroid.py` - `bootstrap_redroid.py` - `verify_offline_bundle.py` - `tools/compat.py` (host / GPU / runtime checks) - `offline/README.md` - `offline/manifest.json` - `stuff/mindthegapps.py` - `stuff/houdini.py` - `stuff/houdini_hack.py` - `stuff/magisk.py` - `assets/redroid_extreme_post_fs_data.sh` - local `offline/downloads/` - local `offline/images/` ## Offline archive The repo tracks the offline bundle metadata under [offline](offline). The large zip/apk/tar payloads are intentionally kept out of Git and should be stored locally under `offline/downloads/` and `offline/images/`. Use [offline/manifest.json](offline/manifest.json) for checksums and source metadata, and [offline/README.md](offline/README.md) for the expected local layout. Expected local files: - `offline/downloads/mindthegapps.zip` - `offline/downloads/libhoudini.zip` - `offline/downloads/libhoudini_hack.zip` - `offline/downloads/magisk.apk` - `offline/downloads/magisk.version` - `offline/images/redroid-redroid-13.0.0-latest.tar` (optional if the base image is already in local Docker storage) ### Build resource order (`redroid.py`) - **Base image:** prefers an existing local `redroid/redroid:-latest`, then `offline/images/redroid-redroid-13.0.0-latest.tar` (`docker load`), then a registry pull (skipped when offline-only). - **Zips / APK:** prefers files under `offline/downloads/` whose **MD5** matches the pinned upstream artifacts; downloads only if missing or mismatch (skipped when offline-only). - **Strict no-network builds:** pass `--offline` or set `REDROID_OFFLINE=1` so missing bundles fail fast instead of downloading. ### Verify script notes ```bash python verify_offline_bundle.py ``` - `magisk.version` is checked against exact **size** and **sha256** from `manifest.json`. A short version string without the expected newline/padding will report `size mismatch` even when `magisk.apk` is fine for the image build. - A missing `offline/images/*.tar` is expected to **FAIL** here if you rely on a pre-pulled Docker image instead; that does not block `redroid.py` when the base image already exists locally. ## Dependencies ```bash python -m pip install -r requirements.txt ``` ## Compatibility checks The project probes the **host** before critical steps (no separate manual checklist required): | Step | What it checks | Opt-out | |------|----------------|---------| | `redroid.py` | Container runtime (`docker`/`podman`) responds; OS is plausible for redroid | `--no-compat-check` | | `run_redroid.py` | Same + Linux **`/dev/dri`** for GPU; **`binder_linux`** module hint on Linux | `--no-compat-check` | **GPU mode (`run_redroid.py`):** - **`--gpu-mode auto` (default):** uses **`host`** when DRI devices exist and automatically adds `docker run --device …` for each `/dev/dri/card*` / `renderD*` node; otherwise **`guest`** (software GLES). - **`--gpu-mode host`:** pass-through when DRI exists; otherwise **falls back to `guest`** with a warning. - **`--gpu-mode guest`:** force software rendering (common black-screen case on headless servers). Quick probe only: ```bash python tools/compat.py python tools/compat.py -c podman --gpu-mode auto ``` ## Build the 5570 image ```bash python redroid.py -mtg -i -m ``` Air-gapped (requires a complete `offline/` tree): ```bash REDROID_OFFLINE=1 python redroid.py -mtg -i -m # or python redroid.py -mtg -i -m --offline ``` Expected image tag: ```bash redroid/redroid:13.0.0_mindthegapps_houdini_magisk ``` ## Launch the container Headless servers have **no screen** to approve the USB debugging RSA dialog. Always pass **`--adb-insecure`** so boot props disable ADB RSA checks and apply **before** the Pixel user profile (`androidboot.adb.secure=0`, `ro.adb.secure=0`, `ro.secure=0`, `ro.debuggable=1`). **Do not expose the ADB port on a public network.** ```bash python run_redroid.py \ --image redroid/redroid:13.0.0_mindthegapps_houdini_magisk \ --bridge libhoudini \ --device-profile pixel-7-pro \ --data-dir ~/data-redroid13 \ --port 5570 \ --replace \ --adb-insecure ``` Then: ```bash adb kill-server && adb start-server adb connect 127.0.0.1:5570 adb devices ``` If you still see `unauthorized` after an upgrade, stop the container, remove persisted keys on the host, and retry: ```bash rm -rf ~/data-redroid13/misc/adb ``` ## Black screen or flickering With **`--gpu-mode guest`** (or **`auto`** when no `/dev/dri` exists), the display uses **software GLES** (SwiftShader). On many **headless servers**, SurfaceFlinger may show a **black screen**, **flicker**, or very low FPS. That is a **display stack** issue, not ADB. The default **`auto`** mode uses **host** GPU when DRI nodes are visible and injects **`--device`** flags automatically. **What to try** 1. **GPU on the host:** ensure **`--gpu-mode auto`** (default) so DRI is detected, or set **`--gpu-mode host`** explicitly. If you must pass devices manually (unusual when `auto` works), for example: ```bash docker run ... --device /dev/dri ... ``` The exact device path varies (Intel/AMD/NVIDIA, `nvidia-docker`, etc.); see [redroid-doc](https://github.com/remote-android/redroid-doc) GPU notes. 2. **Stay on software rendering** but tune the virtual panel (sometimes reduces glitches): ```bash python run_redroid.py ... --adb-insecure \ --extra-prop androidboot.redroid_width=720 \ --extra-prop androidboot.redroid_height=1280 \ --extra-prop androidboot.redroid_fps=15 ``` 3. **First boot / SetupWizard** can sit on a dark screen for a while. Run **`bootstrap_redroid.py`** once `adb` shows `device` so provisioning and wizard are skipped as intended. 4. **Debug with logcat** (on the host, after `adb connect`): ```bash adb -s 127.0.0.1:5570 logcat -d | grep -iE 'SurfaceFlinger|EGL|GLES|redroid' ``` ## Apply the 5570 hardening ```bash python bootstrap_redroid.py \ --serial 127.0.0.1:5570 \ --device-profile pixel-7-pro \ --proxy-host auto \ --install-extreme-script ``` This post-boot step: - disables SetupWizard - marks the device provisioned - enables high accuracy location mode - allows `com.android.shell` to use mock location - applies the `Pixel 7 Pro / user / release-keys / locked / green` identity With `--install-extreme-script`, the validated script [assets/redroid_extreme_post_fs_data.sh](assets/redroid_extreme_post_fs_data.sh) is copied to `/data/adb/post-fs-data.d/20-redroid-extreme.sh` so that: - `vendor/bin/su` stays visible to app namespaces after reboot - `Pixel 7 Pro` properties are re-applied on every boot ## Verified 5570 state The matching `5570` instance was already validated with: - `ro.product.model=Pixel 7 Pro` - `ro.build.type=user` - `ro.build.tags=release-keys` - `ro.boot.vbmeta.device_state=locked` - `ro.boot.verifiedbootstate=green` - app UID `su -V = 27001` - app UID `su -mm -c id = uid=0(root)` - `Kitsune` home page shows a normal `Installed` state - `Kitsune` settings page opens normally and `SuList / MagiskHide` is configurable ## Current scope This repo only reproduces the system environment for the optimized `5570` build. It does not yet include: - virtual camera - camera HAL - TikTok Live specific patches