Skip to end of banner
Go to start of banner

Run Android using QEMU

Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 4 Next »

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).

VIRTUAL_DEVICE_BOOT_COMPLETED
Virtual device booted successfully

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

$ adb devices
List of devices attached
0.0.0.0:6520	device
$ adb shell uname -a
Linux localhost 6.6.30-android15-8-gf1e954acf0f0-ab12203337 #1 SMP PREEMPT Thu Aug  8 15:57:59 UTC 2024 x86_64 Toybox

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):

sudo apt install ffmpeg libsdl2-2.0-0 adb wget \
                 gcc git pkg-config meson ninja-build libsdl2-dev \
                 libavcodec-dev libavdevice-dev libavformat-dev libavutil-dev \
                 libswresample-dev libusb-1.0-0 libusb-1.0-0-dev
git clone https://github.com/Genymobile/scrcpy
cd scrcpy
./install_release.sh

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), 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:

$ cat ../qemu-system-x86_64 
#!/usr/bin/env bash

set -euo pipefail

log()
{
    echo "$@" 1>&2
}

qemu=/home/user/.work/qemu/build/qemu-system-x86_64
sleep 1
log -------------------------------------------------------
$qemu --version
log -------------------------------------------------------
args="$(echo $@)"
args="$(echo "$args" | sed -e 's/accel=kvm/accel=tcg/g' -e 's/-cpu host/-cpu max/g') -monitor unix:$HOME/qemu-monitor-socket,server,nowait"
log "$qemu $(echo $args | tr ' ' '\n' | sed -e 's/$/ \\/')"
log -------------------------------------------------------
$qemu $args
log -------------------------------------------------------

# Now we run launch_cvd with this:
$ HOME=$(pwd) ./bin/launch_cvd -vm_manager qemu_cli -report_anonymous_usage_stats=n --start_webrtc=false -qemu_binary_dir=$(pwd)/..
...
-------------------------------------------------------
QEMU emulator version 9.0.92 (v9.1.0-rc2-68-g8d7c8cc9081)
Copyright (c) 2003-2024 Fabrice Bellard and the QEMU Project developers
-------------------------------------------------------
/home/user/.work/qemu/build/qemu-system-x86_64 -name \
guest=cvd-1,debug-threads=on \
-machine \
pc,nvdimm=on,accel=tcg,usb=off,dump-guest-core=off \
-m \
size=4096M,maxmem=4102M,slots=2 \
-overcommit \
mem-lock=off \
-smp \
2,cores=2,threads=1 \
...
  • No labels