Files
gitlab-instance-0a899031_re…/README.md
2026-04-04 16:24:48 -05:00

282 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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)
- `tools/ssh_remote.py` (Paramiko SSH: remote `docker` / `adb` diagnostics)
- `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:<ver>-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 guest` (default):** software GLES — most stable on headless / server GPUs where host EGL inside the guest often breaks boot or **adbd**.
- **`--gpu-mode auto`:** stays **`guest`** unless **`REDROID_USE_HOST_GPU=1`** (or `true`/`yes`/`on`) **and** `/dev/dri` nodes exist; then **`host`** and `docker run --device …` per DRI node.
- **`--gpu-mode host`:** pass-through when DRI exists; otherwise **falls back to `guest`** with a warning.
Quick probe only:
```bash
python tools/compat.py
python tools/compat.py -c podman --gpu-mode guest
```
## Build the 5570 image
```bash
python redroid.py -mtg -i -m
```
Build flags (short options):
| Flag | Long form | Meaning |
|------|-----------|---------|
| **`-mtg`** | `--install-mindthegapps` | Bake **MindTheGapps** (Google apps framework) into the image |
| **`-i`** | `--install-houdini` | Bake **libhoudini** + **redroid houdini hack** (ARM translation on x86) |
| **`-m`** | `--install-magisk` | Bake **Kitsune Mask / Magisk** bootless payload into the image |
Together they produce `redroid/redroid:13.0.0_mindthegapps_houdini_magisk`. None of these control the **screen**; display is set when you **run** the container (`run_redroid.py`).
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.**
### Persist after reboot (default)
By default **`run_redroid.py` does not pass `--rm`**: the container stays on disk when it stops, and uses **`--restart unless-stopped`** so **Docker/Podman will start it again after the daemon or host reboots** (unless you ran `docker stop <name>`).
- **Always restart** even after explicit stop: `--restart always`
- **No auto-restart** but still keep the container (no `--rm`): `--restart no`
- **One-off / dev only** (old behavior, removed on stop): pass **`--rm`**
On Ubuntu, ensure the engine starts on boot:
```bash
sudo systemctl enable docker --now
# or: sudo systemctl enable podman.socket --now # if you use Podman rootful similarly
```
```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
```
On the **same machine as Docker**, one-shot status + logs + `logcat` after start:
```bash
python run_redroid.py ... --adb-insecure --diagnose --diagnose-settle 20
```
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
```
## Remote diagnostics over SSH (Paramiko)
When redroid runs on **another Linux machine**, you can drive checks from your PC with **`tools/ssh_remote.py`** (uses [Paramiko](https://www.paramiko.org/), declared in `requirements.txt`).
**Do not put passwords in Git.** Use a key file or a one-time prompt:
```bash
pip install -r requirements.txt
export REDROID_SSH_HOST=192.168.2.179
export REDROID_SSH_USER=eric
python tools/ssh_remote.py --password-prompt diagnose
```
Key-based:
```bash
export REDROID_SSH_HOST=... REDROID_SSH_USER=eric REDROID_SSH_KEY=$HOME/.ssh/id_ed25519
python tools/ssh_remote.py diagnose
```
Optional env: **`REDROID_CONTAINER`** (default `redroid_13.0.0_mindthegapps_houdini_magisk`), **`REDROID_ADB_PORT`** (default `5570`). You can also pass **`--container-name`** / **`--adb-port`**.
Arbitrary remote command (note the **`--`** before the shell snippet):
```bash
python tools/ssh_remote.py -H 192.168.2.179 -U eric --password-prompt exec -- bash -lc 'docker ps -a | head -20'
```
The `shell` subcommand is a minimal pseudo-shell only; for a full TTY, use normal OpenSSH **`ssh`**.
## ADB `failed to connect` / connection refused
This means **nothing is listening on the host port** (not the same as `unauthorized`). Typical causes:
1. **Container exited** — if you used **`--rm`**, a crash removes the instance. By default the container is **kept**; use `docker ps -a` and `docker logs` to inspect. Ensure **`--restart`** is not `no` if you want auto-start after reboot.
2. **`androidboot.redroid_gpu_mode=host`** — Mesa/EGL or DRI inside the guest can fail on some hosts; Android never reaches **adbd**. **Workaround:** force software rendering:
```bash
python run_redroid.py ... --adb-insecure --gpu-mode guest
```
3. **Still booting** — wait longer, or use **`--wait-tcp 90`** on `run_redroid.py` to block until TCP opens and print logs if it does not.
## Black screen or flickering
With **`--gpu-mode guest`** (the default), the display uses **software GLES** (SwiftShader). On many **headless servers**, SurfaceFlinger may still show **black screen** or **flicker** — try **`--soft-display`** and more RAM. Host GPU needs **`REDROID_USE_HOST_GPU=1`** with **`--gpu-mode auto`** or **`--gpu-mode host`** when DRI works inside the guest.
**What to try**
1. **GPU on the host:** set **`REDROID_USE_HOST_GPU=1`** and **`--gpu-mode auto`**, or **`--gpu-mode host`**. If **ADB never connects**, host EGL is likely broken — use default **`--gpu-mode guest`**. Manual devices 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. **Software GLES (`guest`)** — force low load on the virtual display (often reduces black screen / flicker):
```bash
python run_redroid.py ... --adb-insecure --gpu-mode guest --soft-display --memory 4g
```
`--soft-display` sets 720×1280, 15 FPS, dpi 280. You can tune further with `--extra-prop` if needed.
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