Skip to content

Emulator Support

Full emulator lifecycle management from the dashboard and API. Create, start, stop, and delete Android emulators (AVDs), and scale to 20+ concurrent headless instances via the EmulatorPool.

Wraps Android SDK tools for single-emulator lifecycle:

~/Android/Sdk/emulator/emulator # Emulator binary
~/Android/Sdk/cmdline-tools/latest/ # avdmanager, sdkmanager
~/.android/avd/ # AVD configs

Operations: list, start, stop, delete, setup (disable animations, max timeout, stay awake), install APK, save/load snapshots.

Manages parallel headless emulators for testing and skill generation:

  • Thread-safe serial-to-status tracking (idle/busy)
  • System resource monitoring via psutil (CPU, RAM, disk)
  • Scale up: create + start N headless emulators
  • Scale down: stop idle emulators
  • Job assignment via mark_busy/mark_idle

Both are lazy-initialized singletons accessed via get_manager() and get_pool().

Both emulators and physical phones are ADB serials. Device(serial) works unchanged. The function is_emulator(serial) checks the emulator- prefix when emulator-specific behavior is needed.

Terminal window
# Required
~/Android/Sdk/emulator/emulator # Emulator binary
adb # In PATH
/dev/kvm # KVM acceleration (Linux)
# Optional (for creating new AVDs)
sdkmanager --install "cmdline-tools;latest"
# Install a system image
sdkmanager --install "system-images;android-35;google_apis_playstore;x86_64"

Without cmdline-tools, you can still start/stop/list/delete existing AVDs but cannot create new ones.

MethodEndpointPurpose
GET/api/emulatorsList all AVDs with running status
POST/api/emulatorsCreate new AVD
DELETE/api/emulators/<name>Delete AVD
POST/api/emulators/<name>/startStart (headless, gpu, cold_boot options)
POST/api/emulators/<name>/stopStop emulator
GET/api/emulators/<name>/boot-statusCheck boot progress
POST/api/emulators/<name>/setupRun automation setup
POST/api/emulators/<name>/install-apkInstall APK
POST/api/emulators/<name>/snapshot/saveSave snapshot
POST/api/emulators/<name>/snapshot/loadLoad snapshot
GET/api/emulators/<name>/snapshotsList snapshots
GET/api/emulators/runningList running emulators
GET/api/emulators/prerequisitesCheck SDK availability
POST/api/emulators/stop-by-serialStop by serial
GET/api/emulators/system-imagesList installed images
POST/api/emulators/system-images/installDownload new image
MethodEndpointPurpose
GET/api/emulator-pool/statusPool status + resources
POST/api/emulator-pool/scale-upStart N emulators
POST/api/emulator-pool/scale-downStop idle emulators
POST/api/emulator-pool/stop-allStop all pool emulators
GET/api/emulator-pool/resourcesCPU/RAM/disk usage
Terminal window
curl -X POST http://localhost:5055/api/emulators/Medium_Phone_API_36.1/start \
-H "Content-Type: application/json" \
-d '{"headless": true, "cold_boot": true}'

After starting, run setup to configure the emulator for automation:

Terminal window
curl -X POST http://localhost:5055/api/emulators/Medium_Phone_API_36.1/setup

This disables animations, sets maximum screen timeout, and enables stay-awake mode.

Terminal window
# Start 3 headless emulators
curl -X POST http://localhost:5055/api/emulator-pool/scale-up \
-H "Content-Type: application/json" \
-d '{"count": 3}'
# Check resource usage
curl -s http://localhost:5055/api/emulator-pool/resources | python3 -m json.tool

The Emulators tab has two sub-tabs:

  • Emulators — AVD list with start/stop/setup/delete buttons, creation form, system image selector
  • Pool — active/idle/busy counts, resource usage bars (RAM/CPU/disk), scale up/down controls

When starting headless (no display required), the emulator uses swiftshader_indirect GPU rendering automatically. Cold boot skips snapshot loading to avoid ADB offline issues.

Terminal window
# Async boot: returns immediately, boot runs in background
# Poll boot-status for progress
curl -s http://localhost:5055/api/emulators/Medium_Phone_API_36.1/boot-status
FileLinesPurpose
marketing_system/services/emulator_service.py726EmulatorManager + EmulatorPool
marketing_system/routers/emulators.py282Flask Blueprint, 21 routes

The Flask Blueprint is zero-coupled to server.py (4-line registration).

  • Phone Farm — using emulators alongside physical phones
  • ADB Device — Device class works identically with emulators
  • Scheduler — assign jobs to emulators