Skip to main content
Android emulators are generally available as of Orka 4.0. They were introduced as early access in Orka 3.7.0-alpha. Contact support@macstadium.com with questions or feedback.

Overview

Orka lets you run Android emulators as first-class resources alongside your macOS VMs. The emulator runs on the same physical host Mac as the VM, connected to it via an ADB relay bridge. From inside your VM, you interact with the Android emulator exactly as you would in any other Android CI setup: adb connect and go. This is useful any time you want iOS and Android tests in the same job, without coordinating across separate infrastructure.

How it works

Android emulators cannot run inside macOS VMs because Apple silicon does not support nested virtualization. Orka works around this by running the emulator directly on the host Mac as a separate process. Relay ports are reachable by any VM running on the same physical node: if a node is running two VMs, both can reach either VM’s emulator(s). Per-VM network isolation is planned for a future release. From your VM’s perspective, the emulator is reachable at a relay IP on a port assigned at deploy time. Always use the relay IP and relay port returned by the CLI or API rather than hardcoding them. The emulator lifecycle is tied to its paired VM:
  • When the VM is deleted, the emulator is cleaned up automatically. You can also delete an emulator manually before deleting the VM.
  • If the VM stops or fails, the emulator fails with the reason PairedVMStopped, and its ports are released for the next emulator on that node. Deploying an emulator against a VM that has already stopped fails right away with the same reason.
  • The Kubernetes scheduler places the emulator on its paired VM’s node. If it can’t, for example because the node is cordoned, the emulator stays Pending with the scheduler’s reason in its error message. After 5 minutes it fails with the reason EmulatorUnschedulable.

Prerequisites

  • An Orka cluster and CLI running Orka 4.0 or later
  • Your Orka cluster must be provisioned with Apple silicon (M-series) nodes
  • Android SDK and adb installed in your VM image, or installed as part of your CI setup

Deploying an emulator

Emulators are deployed through the Orka CLI or API. The deploy request specifies the paired VM and the emulator’s platform and system image type, either directly or through an emulator configuration. The emulator starts on the same host node as the VM and enters Pending state while the AVD boots. Once ready, it transitions to Running. Supported configurations: Platform, device profile, and image type values are passed straight through to the Android SDK’s avdmanager and sdkmanager tooling. Any combination those tools support works on a best-effort basis. The only hard constraint is architecture: Orka supports only platforms with an ARM-native system image, since the emulator runs directly on the Apple silicon host. Commonly used values:
  • Platforms: android-35, android-36 (any platform with an ARM system image works)
  • Device profiles: pixel_8, pixel_9, pixel_tablet (any avdmanager-recognized device profile works)
  • Image types: google_apis, google_apis_playstore, default
ADB doesn’t work with google_apis_playstore images yet. Use google_apis or default. See Known limitations.

CLI interface

The Orka CLI manages emulators with orka emulator deploy, list, and delete, and emulator configurations with orka emulator-config create, list, and delete. For the full flag reference, see Manage Android emulators with the Orka CLI.
The following table lists the most common orka emulator deploy flags.

API interface

Base URL: /api/v1/namespaces/{namespace} Auth: Authorization: Bearer <token> on every call. RBAC is enforced the same as for VMs.

Emulator instances

The following table lists the emulator instance endpoints. Deploy request body Required: vmName (the paired VM, which must be running), and either platform and imageType, or config. Optional: name, shouldGenerateName (bool, appends a unique suffix to the name), deviceProfile, config (name of an emulator configuration; request fields override it), grpc (bool), and timeout (minutes, default 10).
Deploy blocks until the emulator reaches Running or Failed, or until the timeout passes. An emulator stays Pending while its AVD boots and while the paired VM finishes coming up. If the emulator reaches Failed, Orka deletes it and the call returns a 500 with the failure message. If the timeout passes first, the call returns a 500, but the emulator isn’t deleted. Use GET to check whether it reached Running. Response fields The deploy, get, and list responses include name, status, nodeName, relayIP, relayPort, and, for an emulator deployed with gRPC, grpcRelayPort. Get and list responses also include vmName, platform, imageType, and deviceProfile. errorMessage appears only when the emulator has failed. relayIP and relayPort are how you connect (adb connect <RELAY_IP>:<RELAY_PORT>). DELETE returns 200 with no body. Errors: 400 missing vmName, or neither config nor both platform and imageType. 403 RBAC. 404 emulator not found. 409 an emulator with that name already exists. 422 the request failed validation. 500 the deploy failed or timed out, or an unexpected error.

Emulator configurations

The following table lists the emulator configuration endpoints. The create request requires name, platform, and imageType. deviceProfile and grpc (bool) are optional. Emulators deployed from a configuration with grpc set to true start their gRPC endpoint unless the deploy request sets grpc to false.

Emulator configurations

An emulator configuration stores a platform, system image type, and optionally a device profile and gRPC setting, so you can deploy with --config instead of repeating the same flags in every pipeline:
  • Configurations reside in the orka-default namespace and are available to every user and service account with access to it.
  • Any of --platform, --image-type, and --device-profile set at deploy time override the configuration. Pass --device-profile "" to use the avdmanager default instead of the configuration’s profile.
  • Orka copies the configuration’s settings into the emulator when it’s deployed, so changing or deleting a configuration never affects emulators that are already running.

Connecting from inside the VM

Once the emulator is Running, get its relay IP and relay port from orka emulator list (the RELAY-IP and RELAY-PORT columns) or from the API response. From inside the macOS VM, connect:
Standard ADB operations work once connected: adb install, adb shell, adb pull, adb push. This applies to google_apis and default images. google_apis_playstore images reject ADB commands. See Known limitations.

gRPC endpoint

If you deploy with --grpc, or from a configuration that turns gRPC on, the emulator also starts its gRPC endpoint, so a gRPC client can drive the emulator or stream its display. Connect from the paired VM at the relay IP, on the port in the GRPC-PORT column of orka emulator list (grpcRelayPort in the API). Like the ADB endpoint, the gRPC endpoint speaks plaintext gRPC over HTTP/2 with no TLS and no authentication, and only VMs on the same host can reach it. To reach it from elsewhere, forward the port through the paired VM.

Sizing and density

Each emulator runs on the host next to the VMs, so it uses host memory and CPU on top of theirs. An emulator’s CPU and memory come from its device profile, and you can’t set them at deploy time.
  • Plan for about 5 to 6 GB of host memory per emulator. In MacStadium’s capacity testing, an emulator using the pixel_9 profile (4 cores and about 2.5 GB of guest RAM) used about 5.7 GB of host memory.
  • Memory usually limits how many emulators a node can run. Add the emulators’ memory to the memory of the VMs on the node, and leave room for the host itself. For example, four emulators use about 23 GB of host memory, which leaves little room for VMs on a 32 GB node.
  • Emulators slow down first when a node is busy. Orka runs emulators at a lower scheduling priority than VMs, so under CPU or memory contention the emulator loses first. Emulators also render in software on the CPU, so a busy CPU affects them before memory runs out. UI and screenshot tests can then become flaky, for example with small pixel shifts between runs. If you see this, try fewer emulators per node.
For UI and screenshot tests, turn off animations in the emulator after you connect:

Known limitations

  • google_apis_playstore images don’t accept ADB commands. The emulator reaches Running and returns a relay port, but every adb command from the VM fails with device unauthorized. Play Store images are production Android builds that require you to approve each ADB key on the device. Orka emulators run headless, so there’s no screen to approve it on. There’s no workaround for Play Store images. Use google_apis instead. It includes Google Play services (Firebase Cloud Messaging, Maps, Sign-In, Location, and ML Kit), so most Google Mobile Services testing works. It doesn’t include the Play Store app or Play certification. You can’t test Play Store install and update flows, Play Billing or in-app purchases, or install referrer. Play Integrity checks also behave differently. MacStadium is working on a fix.
  • Network isolation is scoped to the node, not the VM. Relay ports are reachable by any VM running on the same physical node. For example, if a node is running two VMs, both can reach either VM’s emulator(s). Emulators are not reachable from VMs on other nodes. Per-VM isolation is planned for a future release.
  • Bridged networking is not supported for Android emulators. The emulator relies on the host NAT network to set up the ADB relay, so emulators are available only on NAT-networked VMs.
  • Emulators are ephemeral: there is no persistent AVD state between runs. Each deploy creates a fresh emulator.
  • No support yet for packaging custom AVD configurations as Orka images.
  • Android SDK components (roughly 2 to 4 GB per platform and image pair) are downloaded at deploy time if not already cached on the host node. First-run deploys on a node may take longer.
If a specific platform or device profile fails to deploy, contact support@macstadium.com.