Run Android using QEMU

History

Android Emulator (goldfish/ranchu)

Google has been providing android emulator for application development through Android Studio. It’s possible to create virtual devices with various characteristics, and images are available for every Android major/minor versions.

This emulator is based on a downstream fork of QEMU (last merge was QEMU 2.12 + various patches applied):

It provides specific devices, new command line switches and a UI based on Qt. goldfish was the first name of this platform, and it was later superseded by ranchu (https://groups.google.com/g/android-emulator-dev/c/dltBnUW_HzU).

Despite being called an emulator, it provides also virtualization acceleration (through kvm on Linux, whpx/haxm on Windows and hvf on MacOS), and it seems to be the main use case these days.

Note: I have not been able to launch any aarch64 vm from a Linux/Windows x64 host. It seems like command line generated is incorrect for any Android image (>= 7.0). So virtualization seems to be the only solution working nowadays.

Cuttlefish

In 2018 (AOSP 9.0), Google started to work on a new solution for Android virtualization, named Cuttlefish.
https://source.android.com/docs/devices/cuttlefish

The idea is to provide a virtualization oriented solution, with less maintenance:

  • use upstream Kernel/QEMU

  • use virtio devices

  • leverage kvm for acceleration (thus, it’s only available on Linux)

  • adapted for cloud environment

Initially, QEMU was used. It was later replaced by CrosVM. However, it’s still possible to use QEMU, with or without kvm acceleration.

Those two presentations can help to understand the philosophy or Cuttlefish:

Conclusion

Today, we have two solutions for running Android VM.

The first, named Android emulator, goldfish, or ranchu, is integrated in Android Studio, and targets applications developers. It uses a downstream fork of QEMU.

The second, named Cuttlefish, targets AOSP developers, working on the system itself. It uses upstream QEMU/Kernel.

Run Android using Cuttlefish

Now we saw the different existing solutions, we’ll focus on Cuttlefish. It’s supported on any Debian/Ubuntu distribution. https://source.android.com/docs/devices/cuttlefish/get-started

1. Install cuttlefish tools

First, you need to install cuttlefish packages on your machine, and reboot.

sudo apt install -y git devscripts equivs config-package-dev debhelper-compat golang curl git clone https://github.com/google/android-cuttlefish cd android-cuttlefish tools/buildutils/build_packages.sh sudo dpkg -i ./cuttlefish-base_*_*64.deb || sudo apt-get install -f sudo dpkg -i ./cuttlefish-user_*_*64.deb || sudo apt-get install -f sudo usermod -aG kvm,cvdnetwork,render $USER sudo reboot

2. Download Android image and cvd-host package

Images can be compiled from source (https://source.android.com/docs/setup/build/building), or simply downloaded from https://ci.android.com (aosp-main branch for x64, aosp-main-throttled for aarch64).

Select artifacts, then download aosp_cf_*img*.zip and cvd-host_package.tar.gz

3. Decompress cvd tools and image in the same directory

mkdir android-image pushd android-image unzip ../aosp_cf_*.zip tar xzvf ../cvd-host_package.tar.gz

4. Run Cuttlefish

By default, vm will be ran using crosvm. Option -vm_manager allows to use qemu instead.

HOME=$(pwd) ./bin/launch_cvd -vm_manager qemu_cli -report_anonymous_usage_stats=n --start_webrtc=false

5. Access system

Cuttlefish redirects various logs, including kernel (cuttlefish/instances/cvd-1/kernel.log).

VM will be booted once this message appears (either in your terminal, or in kernel log).

The easiest way to access VM, is to use adb. adb shell will provide a shell running on the system.

For graphical access, cvd offers a web page. However, it seems to work only with crosvm, and not when using QEMU. The easiest way is to use https://github.com/Genymobile/scrcpy instead.

To build scrcpy (https://github.com/Genymobile/scrcpy/blob/master/doc/linux.md):

You can then access your Android display by simply using scrcpy.

Screenshot_2024-08-22_17-05-44.png

Run Android using Cuttlefish and a custom build of QEMU

Cuttlefish comes with a prebuilt upstream QEMU (very recent, tracking master), located in bin/x86_64-linux-gnu/qemu/, and coming from cvd package.

launch_cvd allows you to specify a custom path where to find qemu-system-* binaries using -qemu_binary_dir= option. You can then point directory to your QEMU build folder, or to a directory containing a wrapper script, if you want to edit QEMU options, or wrap it with a tool, like perf.

Note: launch_cvd parses stdout from QEMU. Thus, if you have a wrapping script, you need to write output to stderr instead.

Note: launch_cvd requires to set your HOME folder to current directory. Thus, you should be aware of this in case you write a wrapper script using this.

This is an example with a custom wrapper to print QEMU full command line: