I was recently presented with the problem of testing a system that required two android emulators running side by side in coordination. Our QA team had set this up to work on a local windows machine, but we were exploring alternatives and desired moving our testing activities to the cloud.
We started out exploring CircleCI. This is a familiar Cloud CI tool, but they do not support emulators. We also explored using their MacOS variants, which appear to be hosted on ESX, but I ran into GPU driver issues.
EC2 instances did not have any virtualization extensions exposed to the VM. This left us with only being able to use ARM emulation which is extremely slow and would probably take us an entire day or more to run our entire test suite.
After reading the docs on how to configure hardware acceleration for the Android Emulator, I realized that we needed to have access to virtualization extensions inside our VM/container. In virtualization speak, we needed “nested virtualization.” Both Google Cloud and Azure support nested virtualization, but I am more familiar with Google Cloud Platform so I started out on GCP.
A virtual machine hosted inside GCP that supports nested virtualization. We are going to setup our solution on Debian, but I have also had it working on Ubuntu. Let’s get started.
To begin, we will follow the instructions defined here
Create a disk to use:
gcloud compute disks create disk1 --size=30gb --image-project ubuntu-os-cloud --image-family ubuntu-1604-lts --zone us-central1-b
Create an image from the disk and enable nested virtualization
gcloud compute images create android-emulator-image \ --source-disk disk1 --source-disk-zone us-central1-b \ --licenses "https://www.googleapis.com/compute/v1/projects/vm-options/global/licenses/enable-vmx"
Create an instance from the image. It needs to be at least Haswell and we are using a machine-type that has a few extra cores which will help us run both emulators at the same time.
gcloud compute instances create android-emulator-vm --zone us-central1-b \ --machine-type n1-standard-4 \ --min-cpu-platform "Intel Haswell" \ --image android-emulator-image
Let’s SSH to the instance and make sure that we have virtualization available
gcloud compute ssh android-emulator-vm #! Inside VM grep -cw vmx /proc/cpuinfo
You should get a non zero value to indicate that nested virtualization is enabled.
Now, let’s configure our VM so that we can connect to it using VNC and use virtualization.
sudo apt-get update -y sudo apt-get install xfce4 qemu-kvm tightvncserver iceweasel -y
We can now start our VNC server using the following command. We will be prompted for a password. Enter in a password and remember it.
Once we start the server it will create a few configuration files for us. We need to stop our VNC server nad update our config files so that we get a more usable display when we connect to our VNC server.
vncserver -kill :1 vi ~/.vnc/xstartup
Inside xstartup, enter in the following details:
#!/bin/sh unset SESSION_MANAGER unset DBUS_SESSION_BUS_ADDRESS startxfce4 & [ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup [ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources xsetroot -solid grey vncconfig -iconic &
Let’s startup our VNC server with the new config and connect to it.