Files
DarkRoom/docker/android
dtourolle 82a5e21ec6 Initial workspace: GPU context, compute pass, adaptive Slint shell
Establishes the v0.1 foundations on both platforms:

- dr-types: SourceRef (never a filesystem path — Android SAF has none),
  Format, Availability, Validator with ETag quote normalisation
- dr-gpu: wgpu device, compute pass writing a storage texture, resize
- dr-ui: Slint shell with FR-UI-1 adaptive layout, computed in Rust to
  avoid a binding loop
- docker/android: pinned toolchain, verified producing API 28 ARM binaries

Measured the cost of the temporary CPU readback path (dr-gpu bench):
compute is 0.06-0.28ms across sizes while readback is 0.63-7.43ms, so
readback is 90-96% of frame time and scales with area. Recorded in
ARCH §6.1 — this is why spike S1 is the priority.

Mitigations pending S1: reuse the staging buffer, apply at most one
resize per frame, and cap render resolution at 2048 on the long edge.

10 tests passing; core crates cross-compile for aarch64-linux-android.
2026-08-09 07:42:05 +02:00
..

Android build environment

Reproducible container for cross-compiling DarkRoom to Android. CI and local builds use the same image, so a break appears in one place rather than two.

Use

# Cross-compile for a device ABI
./docker/android/build.sh cargo ndk -t arm64-v8a build --release

# All four ABIs
./docker/android/build.sh cargo ndk -t arm64-v8a -t armeabi-v7a -t x86_64 -t x86 build --release

# Type-check without linking
./docker/android/build.sh cargo check --target aarch64-linux-android

# Interactive shell
./docker/android/build.sh

# After editing the Dockerfile
./docker/android/build.sh --rebuild

Prefers podman, falls back to docker. First run builds the image, which takes several minutes; after that it is cached.

Pinned versions

Component Version Why this one
JDK 17 AGP's stable target. The host's JDK 25 breaks Gradle.
Compile SDK API 36 Required for Play distribution
Min API 28 (Android 9) Floor where Vulkan support is dependable (NFR-COMPAT-1)
Build tools 36.0.0 Matches compile SDK
NDK 27.2.12479018 (r27c) Current LTS
Rust 1.92.0 Slint 1.17 requires it; cargo-ndk 4.1.x needs ≥ 1.86
cargo-ndk 4.1.2

Bumping any of these is a reviewable change, not silent drift.

Compile SDK versus min API

These are different and both matter. ANDROID_API (36) is what the SDK compiles against — the newest APIs available. MIN_API (28) is what native code links against, and determines the oldest device that can run the result.

cargo-ndk defaults to API 21 if not told otherwise, which is far below what this app needs. CARGO_NDK_PLATFORM and the per-target linker paths both pin it to MIN_API. Verify with:

file target/aarch64-linux-android/release/*.so
# → "... for Android 28, built by NDK r27c"

Caching

The cargo registry and target directory persist in ~/.cache/darkroom-android, so rebuilds do not re-download the crate index. Clear with:

rm -rf ~/.cache/darkroom-android

The Android target dir is kept separate from the host's target/ — sharing one directory between host and container builds causes constant rebuilds as they invalidate each other's fingerprints.

What is not here

No emulator, no adb device access. This image cross-compiles; it does not run or deploy. Device testing (spikes S2 and S10, which need two GPU vendors) happens on real hardware — the emulator's GPU behaviour is not representative of Adreno or Mali, which is precisely what those spikes exist to test.