# Android emulator on CI without KVM vs a cloud phone: timings

One GitHub Actions run: the emulator with KVM, without KVM and a cloud phone from the same runner, timed from launch to first screenshot, tap and APK install.

Comparisons3 min read

In this article

On a GitHub-hosted ubuntu-latest runner, the Android emulator reached its first screenshot in 50 seconds with KVM, after 75 seconds of image download and AVD setup that every fresh job pays. From the same runner, a Mobilebox cloud Android phone ($0.01 a minute) was ready for its first screenshot in 20.3 seconds with nothing to download, and in 19.4 s from a data center in our November 2026 benchmark.

Without KVM, the first of two cold boots of the emulator reached a screenshot after 13.5 minutes, and the second didn’t finish within our 15-minute limit.

We ran both in one GitHub Actions workflow on November 8, 2026: five cold boots of an Android 14 (API 34, google_apis, x86_64) emulator with KVM, the same without KVM, and five Mobilebox phones from the same runner. The workflow and scripts are public in [fifteenA/mobilebox](https://github.com/fifteenA/mobilebox/tree/main/benchmarks); every number is on the [benchmark page](https://mobilebox.dev/benchmarks).

## Timings

| Step | Emulator, KVM | Emulator, no KVM | Mobilebox from the runner |
| --- | --- | --- | --- |
| One-time setup per job | 75 s (system image + AVD) | 38 s (system image + AVD) | none |
| Cold start to first screenshot | 50.0 s (p90 50.3) | 13.5 min (1 of 2 boots finished) | 20.3 s (p90 20.6) |
| Tap to screenshot | 1.04 s (p90 3.5) | 18.7 s (p90 23.4) | 2.1 s (p90 2.2) |
| Install a 4 MB APK | 6.1 s, adb install | 2.1 min, adb install | 1.2 s, from a URL |
| Runner minutes for one smoke test | over 2 min | over 14 min, when it boots | about 0.5 min |

Medians, p90 by nearest rank. The emulator was started with `-no-snapshot -wipe-data -gpu swiftshader_indirect` and timed from launch to `sys.boot_completed` plus one `adb exec-out screencap`. KVM came from the udev rule that [android-emulator-runner](https://github.com/ReactiveCircus/android-emulator-runner) documents; "no KVM" means `-accel off`.

The cloud phone’s tap is slower than the local emulator’s because every tap and screenshot crosses the network: each request took about 90 ms longer from the runner than from a client in Germany (607 against 517 ms per tap), and from Germany the same tap plus screenshot took 1.45 seconds.

## What each path costs

- **Emulator with KVM:** free on public repositories, $0.006 a minute on private ones ([GitHub pricing](https://docs.github.com/en/billing/reference/actions-runner-pricing)). Over two runner minutes per job before the first test step, more if you boot several API levels.

- **Emulator without KVM:** the same runner price, but 13.5 minutes or more of runner time before the first test step, and one of our two boots never finished. In practice the job times out or needs a much longer limit.

- **Cloud phone:** $0.01 a phone-minute on Mobilebox, billed per second once the phone is ready; boot time is free. A one-minute smoke test costs one cent plus half a minute of runner time.

## When to keep the emulator

Keep it when you need ADB, logcat, instrumented tests, several API levels or a debugger: the emulator gives you all of Android’s tooling, and with KVM it is reliable. A cloud phone fits when the job is "install this build, check what a user would see, fail the build if it’s wrong", when the runner has no KVM (containers, many self-hosted and agent sandboxes), or when an AI agent needs to drive the phone through an API or MCP rather than ADB.

## Try the cloud path

[Run an APK smoke test from CI](https://mobilebox.dev/blog/android-apk-ci-smoke-tests) has a complete GitHub Actions job, and [No KVM in CI?](https://mobilebox.dev/blog/android-emulator-without-kvm) has a curl script that works from any runner.

## Try it in your agent in 60 seconds

Paste this into Claude Code, Cursor, Codex or any agent that can read a web page. It asks for your email, gets its own key at once and adds the phone tools; the 6-digit code from your inbox keeps the workspace.

```
Set up Mobilebox for me: read https://mobilebox.dev/setup.md?via=android-emulator-ci-vs-cloud-phone and follow it.
```

[What your agent reads](https://mobilebox.dev/setup.md?via=android-emulator-ci-vs-cloud-phone)

In this article

[All articles](https://mobilebox.dev/blog)

## Next questions

- [How fast do cloud phones start, measured?](https://mobilebox.dev/benchmarks?via=next-benchmarks)

- [Is there a Python package?](https://mobilebox.dev/blog/android-phone-for-python-ai-agent?via=next-python)

- [Mobilebox or Firebase Test Lab?](https://mobilebox.dev/blog/mobilebox-vs-firebase-test-lab?via=next-firebase)

- [Mobilebox or BrowserStack?](https://mobilebox.dev/blog/mobilebox-vs-browserstack?via=next-browserstack)

- [Cloud phone or a local emulator?](https://mobilebox.dev/blog/mobilebox-vs-local-emulator?via=next-emulator)

- [Mobilebox, Limrun or Mobilerun?](https://mobilebox.dev/blog/mobilebox-vs-limrun?via=next-limrun)

- [How do I add it to Cursor, Codex or VS Code?](https://mobilebox.dev/blog/android-mcp-cursor-codex-vscode?via=next-setup)

- [Can my agent run 50 phones in parallel?](https://mobilebox.dev/blog/run-android-phones-in-parallel?via=next-parallel)
