🖥️ Emulator Support
Full Android emulator lifecycle management via Docker containers with KVM hardware acceleration. Create, start, stop, and delete emulators from the dashboard or REST API, and scale to multiple concurrent headless instances for testing.
Architecture
Section titled “Architecture”Docker+KVM backend
Section titled “Docker+KVM backend”Ghost uses budtmo/docker-android containers instead of the Android SDK emulator. Each container runs a full Android 11 emulator, exposes ADB on port 5555, and is hardware-accelerated via KVM.
Ghost backend | vDocker daemon → budtmo/docker-android container | Android 11 (API 30) | ADB server :5555 | vadb connect localhost:<host_port> | vDevice(serial) — same API as a physical phoneWhy Docker instead of SDK AVDs:
- No Android SDK required — just Docker + KVM
- Works on any Linux machine with
/dev/kvm - Emulators are isolated, reproducible, and easy to reset
- No SDK version management headaches
EmulatorPool
Section titled “EmulatorPool”Manages multiple containers for parallel testing:
- Thread-safe serial-to-status tracking (idle/busy)
- System resource monitoring (CPU, RAM, disk)
- Scale up: spin N containers at once
- Scale down: stop idle containers
- Job assignment via mark_busy/mark_idle
Prerequisites
Section titled “Prerequisites”# Checkdocker info # Docker daemon runningls /dev/kvm # KVM available (Linux)adb version # ADB in PATH
# Pull the image (6.9 GB, one-time)docker pull budtmo/docker-android:emulator_11.0
# Verify via Ghostcurl http://localhost:5055/api/emulators/prerequisitesThe prerequisites endpoint returns:
{ "backend": "docker", "docker_available": true, "kvm_available": true, "adb_binary": true, "hw_accel": true, "hw_accel_type": "KVM", "image": "budtmo/docker-android:emulator_11.0"}Quick Start
Section titled “Quick Start”Via dashboard
Section titled “Via dashboard”Open the Emulators tab → click Create → enter a name → the container starts and connects via ADB automatically.
Via API
Section titled “Via API”# Create + startcurl -X POST http://localhost:5055/api/emulators \ -H "Content-Type: application/json" \ -d '{"name": "test-emu", "api_level": 30}'
# Poll boot statuscurl http://localhost:5055/api/emulators/test-emu/boot-status# {"serial": "localhost:5555", "booted": true}
# Use it — same as a physical phonecurl http://localhost:5055/api/phone/devices
# Stop + deletecurl -X POST http://localhost:5055/api/emulators/test-emu/stopcurl -X DELETE http://localhost:5055/api/emulators/test-emuManual Docker (no Ghost backend)
Section titled “Manual Docker (no Ghost backend)”# docker-compose.emulators.yml — ships with the reposervices: emu-1: image: budtmo/docker-android:emulator_11.0 devices: - /dev/kvm:/dev/kvm ports: - "5555:5555"docker compose -f docker-compose.emulators.yml up -dadb connect localhost:5555Emulators = Phones
Section titled “Emulators = Phones”Both emulators and physical phones are ADB serials. Device("localhost:5555") works identically to Device("L9AIB7603188953"). All 38 MCP tools, all skills, all agent workflows run unchanged on emulators.
API Reference
Section titled “API Reference”Emulator Management
Section titled “Emulator Management”| Method | Endpoint | Description |
|---|---|---|
| GET | /api/emulators | List all containers with status |
| POST | /api/emulators | Create + start a new container |
| DELETE | /api/emulators/<name> | Stop + remove container |
| POST | /api/emulators/<name>/stop | Stop container |
| GET | /api/emulators/<name>/boot-status | {serial, booted} |
| GET | /api/emulators/running | Running containers reachable via ADB |
| GET | /api/emulators/prerequisites | Docker + KVM availability check |
| GET | /api/emulators/system-images | Available Docker images |
| POST | /api/emulators/system-images/install | Pull a Docker image |
Pool Management
Section titled “Pool Management”| Method | Endpoint | Description |
|---|---|---|
| GET | /api/emulator-pool/status | Active / idle / busy counts |
| GET | /api/emulator-pool/resources | CPU / RAM / disk usage |
| POST | /api/emulator-pool/scale-up | Start N containers |
| POST | /api/emulator-pool/scale-down | Stop idle containers |
| POST | /api/emulator-pool/stop-all | Stop all pool containers |
| File | Purpose |
|---|---|
gitd/services/emulator_service.py | EmulatorManager + EmulatorPool |
gitd/services/_emulator_helpers.py | Docker client, discovery, config dataclass |
gitd/services/_emulator_pool.py | Pool lifecycle |
gitd/routers/emulators.py | REST API routes |
docker-compose.emulators.yml | Manual multi-emulator compose file |
Snapshots
Section titled “Snapshots”Snapshots are not supported in Docker mode — containers start fresh each time. For persistent state, commit a custom Docker image from a running container:
docker commit <container_id> my-emulator-state:v1Related
Section titled “Related”- ADB Device — Device class works identically with emulators
- Scheduler — assign automated jobs to emulators
- Ghost Bench — run benchmark suites across emulator pools