Android Emulator Container Scripts

This is a set of minimal scripts to run the emulator in a container for various systems such as Docker, for external consumption. The scripts are compatible with both Python version 2 and 3.

*Note that this is still an experimental feature and we recommend installing this tool in a python virtual environment. Please file issues if you notice that anything is not working as expected.

Requirements

These demos are intended to be run on a linux OS. Your system must meet the following requirements:

Keep in mind that you will see reduced performance if you are making use of nested virtualization.

Install in a virtual environment

You can install the python package as follows:

source ./configure.sh

This will activate a virtual environment and make the executable emu-docker available. You can get detailed information about the usage by launching it as follows:

emu-docker -h

You will need to accept the android licenses when you are creating images. You will have to accept the license agreements before you can create docker containers.

Quick start, interactively creating and running a docker image

You can interactively select which version of android and emulator you wish to use by running:

emu-docker interactive --start

You will be asked to select a system image and an emulator version, after which a docker file will be created. The system image and emulator will be downloaded to the current directory if needed. The script will provide you with a command to see the logs as well as the command to stop the container.

If the local adb server detected the started container automatically, you have nothing to do to query it through adb. If that's not the case, you can now connect to the running device using adb:

adb connect localhost:5555

To check if adb has seen the container, you can use the:

adb devices

command and check if a device is detected.

Do not forget to stop the docker container once you are done!

Read the section on making the emulator available on the web to run the emulator using webrtc

Obtaining URLs for emulator/system image zip files

Issuing:

emu-docker list

will query the currently published Android SDK and output URLs for the zip files of:

For each system image, the API level, variant, ABI, and URL are displayed. For each emulator, the update channel (stable vs canary), version, host os, and URL are displayed.

Example output:

SYSIMG android 21 L x86_64 https://dl.google.com/android/repository/sys-img/android/x86_64-21_r05.zip
SYSIMG android 22 L x86_64 https://dl.google.com/android/repository/sys-img/android/x86_64-22_r06.zip
SYSIMG android 23 M x86_64 https://dl.google.com/android/repository/sys-img/android/x86_64-23_r10.zip
SYSIMG android 24 N x86_64 https://dl.google.com/android/repository/sys-img/android/x86_64-24_r08.zip
SYSIMG android 25 N x86_64 https://dl.google.com/android/repository/sys-img/android/x86_64-25_r01.zip
SYSIMG android 26 O x86_64 https://dl.google.com/android/repository/sys-img/android/x86_64-26_r01.zip
SYSIMG android 27 O x86_64 https://dl.google.com/android/repository/sys-img/android/x86_64-27_r01.zip
SYSIMG android 28 P x86_64 https://dl.google.com/android/repository/sys-img/android/x86_64-28_r04.zip
SYSIMG android 28 Q x86_64 https://dl.google.com/android/repository/sys-img/android/x86_64-Q_r04.zip
SYSIMG google_apis 21 L x86_64 https://dl.google.com/android/repository/sys-img/google_apis/x86_64-21_r30.zip
SYSIMG google_apis 22 L x86_64 https://dl.google.com/android/repository/sys-img/google_apis/x86_64-22_r24.zip
SYSIMG google_apis 23 M x86_64 https://dl.google.com/android/repository/sys-img/google_apis/x86_64-23_r31.zip
SYSIMG google_apis 24 N x86_64 https://dl.google.com/android/repository/sys-img/google_apis/x86_64-24_r25.zip
SYSIMG google_apis 25 N x86_64 https://dl.google.com/android/repository/sys-img/google_apis/x86_64-25_r16.zip
SYSIMG google_apis 26 O x86_64 https://dl.google.com/android/repository/sys-img/google_apis/x86_64-26_r13.zip
SYSIMG google_apis 28 P x86_64 https://dl.google.com/android/repository/sys-img/google_apis/x86_64-28_r09.zip
SYSIMG google_apis 28 Q x86_64 https://dl.google.com/android/repository/sys-img/google_apis/x86_64-Q_r04.zip
SYSIMG google_apis_playstore 28 P x86_64 https://dl.google.com/android/repository/sys-img/google_apis_playstore/x86_64-28_r08.p
SYSIMG google_apis_playstore 28 Q x86_64 https://dl.google.com/android/repository/sys-img/google_apis_playstore/x86_64-Q_r04.zp
EMU stable 29.0.11 windows https://dl.google.com/android/repository/emulator-windows-5598178.zip
EMU stable 29.0.11 macosx https://dl.google.com/android/repository/emulator-darwin-5598178.zip
EMU stable 29.0.11 linux https://dl.google.com/android/repository/emulator-linux-5598178.zip
EMU stable 28.0.25 windows https://dl.google.com/android/repository/emulator-windows-5395263.zip
EMU canary 29.0.12 windows https://dl.google.com/android/repository/emulator-windows-5613046.zip
EMU canary 29.0.12 macosx https://dl.google.com/android/repository/emulator-darwin-5613046.zip
EMU canary 29.0.12 linux https://dl.google.com/android/repository/emulator-linux-5613046.zip

One can then use tools like wget or a browser to download a desired emulator and system image. After the two are obtained, we can build a Docker image.

Given an emulator zip file and a system image zip file, we can build a directory that can be sent to docker build via the following invocation of emu-docker:

emu-docker create <emulator-zip> <system-image-zip>  [--dest docker-src-dir
(getcwd()/src by default)]

This places all the right elements to run a docker image, but does not build, run or publish yet. A Linux emulator zip file must be used.

Building the Docker image: Setting up the source dir

To build the Docker image corresponding to these emulators and system images:

docker build <docker-src-dir, either ./src or specified argument to
emu_docker.py>

A Docker image ID will output; save this image ID.

Running the Docker image

We currently assume that KVM will be used with docker in order to provide CPU virtualization capabilities to the resulting Docker image.

We provide the following run script:

./run.sh <docker-image-id> <additional-emulator-params>

It does the following:

docker run -e "ADBKEY=$(cat ~/.android/adbkey)" --device /dev/kvm --publish
8554:8554/tcp --publish 5555:5555/tcp <docker-image-id>

Running the Docker image with GPU acceleration

We currently only support hardware acceleration for NVIDIA. In order to make use of hardware acceleration you might have to install the NVIDIA docker extensions from here if you are running an older version of docker (<19.03). You must make sure you have a minimal X installation if you are using a cloud instance. For example Xvfb can be used. You must build the containers by passing in the --gpu flag:

emu-docker create stable Q --gpu

You can now launch the emulator with the run-with-gpu.sh script:

./run-with-gpu.sh <docker-image-id> <additional-emulator-params>

The script is similar as to the one described above with the addition that it will:

Hardware acceleration will significantly improve performance of applications that heavily rely on graphics. Note that even though we need a X11 server for gpu acceleratation there will be no ui displayed.

Pushing images to a repository

You can push the created images to a repository by providing the --push and --repo and --tag parameters when creating an image. The --tag parameter is optional and is used to indicate the version of the created image. This will default to the build-id of the emulator, as system images are rarely updated.

We adopted the following naming scheme for images:

{desert}-{sort}-{abi}

Where:

For example: q-playstore-x86:29.3.2 indicates a playstore enabled system image with Q running on 32-bit x86.

Note: We are in the process of migrating from version number to emulator build numbers, which are more accurate

An example invocation for publishing all Q images to google cloud repo could be:

    emu-docker -v create --push --repo us.gcr.io/emulator-project/ stable "Q"

Images that have been pushed to a repository can be launched directly from the repository. For example:

    docker run --device /dev/kvm --publish 8554:8554/tcp --publish 5555:5555/tcp \
    us.gcr.io/emulator-project/q-playstore-x86:29.3.2

Note: The projects above are samples, we are not yet hosting any of these images.

Communicating with the emulator in the container

adb

We forward the port 5555 for adb access to the emulator running inside the container (TODO: make this configurable per container). Adb might not automatically detect the device, so run:

adb connect localhost:5555

Your device should now show up as:

$ adb devices

List of devices attached:
emulator-5554   device

Make the emulator accessible on the web

This repository also contains an example that demonstrates how you can use docker to make the emulator accessible through the web. This is done by composing the following set of docker containers:

Important Notice!

In order to run this sample and be able to interact with the emulator you must keep the following in mind:

Requirements

Running the emulator on the web

In order to create the web containers you must have the following tools available:

On debian based systems you can install these as follows:

sudo apt-get install build-essential nodejs npm libprotoc-dev protobuf-compiler pkg-config

Next you must create a container with the emulator & system image version you wish to use. For example:

. ./configure.sh && emu-docker create canary "P.*x64"

Running the create script

Once you have taken care of the steps above you can create the containers using the create_web_container.sh script:

$ ./create_web_container.sh -h
   usage: create_web_container.sh [-h] [-a] [-s] [-i] -p user1,pass1,user2,pass2,...

   optional arguments:
   -h        show this help message and exit.
   -a        expose adb. Requires ~/.android/adbkey.pub to be available at run.
   -s        start the container after creation.
   -p        list of username password pairs.  Defaults to: [jansene,hello]
   -i        install systemd service, with definition in /opt/emulator

For example:

./create_web_container.sh -p user1,passwd1,user2,passwd2,....

This will do the following:

You can now launch the container as follows:

docker-compose -f js/docker/docker-compose.yaml up

If you wish to make ADB available you can apply the overlay found in js/docker/development.yaml as follows:

docker-compose -f js/docker/docker-compose.yaml -f js/docker/development.yaml up

Point your browser to localhost. You will likely get a warning due to the usage of the self signed certificate. Once you accept the cert you should be able to login and start using the emulator.

Keep the following things in mind when you make the emulator accessible over adb:

$ adb connect localhost:5555
$ adb shell getprop

Troubleshooting

We have a separate document related to dealing with issues.

Modifying the demo

Details on the design and how to modify the React application can be found here