Skip to content

Latest commit

 

History

History
177 lines (137 loc) · 5.87 KB

emulator_setup.md

File metadata and controls

177 lines (137 loc) · 5.87 KB

Emulator setup

Basically we have 2 choices:

  • Manage devices automatically via avd
  • Manage docker containers with emulators with docker

Using a docker image is the easiest way, however it's important to understand how docker creates emulators for you.

Creating an emulator

Before starting to read this, make sure you've read the official documentation

Firstly, you need to create an ini configuration file for the emulator:

PlayStore.enabled=false
abi.type=x86_64
avd.ini.encoding=UTF-8
hw.cpu.arch=x86_64
hw.cpu.ncore=2
hw.ramSize=2048
hw.lcd.density=120
hw.lcd.width=320
hw.lcd.height=480
hw.audioInput=no
hw.audioOutput=no
hw.accelerometer=no
hw.gyroscope=no
hw.dPad=no
hw.mainKeys=yes
hw.keyboard=no
hw.sensors.proximity=no
hw.sensors.magnetic_field=no
hw.sensors.orientation=no
hw.sensors.temperature=no
hw.sensors.light=no
hw.sensors.pressure=no
hw.sensors.humidity=no
hw.sensors.magnetic_field_uncalibrated=no
hw.sensors.gyroscope_uncalibrated=no
image.sysdir.1=system-images/android-29/google_apis/x86_64/
tag.display=Google APIs
tag.id=google_apis
skin.dynamic=yes
skin.name=320x480
disk.dataPartition.size=8G

Pay attention to what we have disabled:

  • Accelerometer
  • Audio input/output
  • Play Store
  • Sensors:Accelerometer, Humidity, Pressure, Light
  • Gyroscope

We don't really need them for our test runs. It also may improve our tests performance, because there are no background operations related to those tasks.

After that, you can run your emulator via avd manager, which is part of the android sdk manager. After creating the emulator, you need to switch the default generated ini file to the custom one we defined previously. You can achieve that with a script like this one:

function define_android_sdk_environment_if_needed() {
  android_env=$(printenv ANDROID_HOME)
  if [ -z "$android_env" ]; then
    if [[ -d "$HOME/Library/Android/sdk" ]]; then
      export ANDROID_HOME="$HOME/Library/Android/sdk"
    else
      printf "Can't locate your android sdk. Please set ANDROID_HOME manually"
      exit
    fi
  fi
}

function define_path_environment_if_needed() {
  if ! command -v adb &>/dev/null; then
    export PATH=~/Library/Android/sdk/tools:$PATH
    export PATH=~/Library/Android/sdk/platform-tools:$PATH
  fi
}

function create_and_patch_emulator() {
  EMULATOR_API_VERSION=29
  EMULATOR_NAME="ui_tests_emulator_api_${EMULATOR_API_VERSION}"

  # Install sdk
  $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "system-images;android-${EMULATOR_API_VERSION};google_apis;x86_64"

  # Create new emulator
  echo "no" | $ANDROID_HOME/cmdline-tools/latest/bin/avdmanager create avd --force \
    --name "${EMULATOR_NAME}" \
    --package "system-images;android-${EMULATOR_API_VERSION};google_apis;x86_64" \
    --abi google_apis/x86_64

  # Change emulator's config after emulator's creation
  cp -p YOUR_INI_FILE.ini $HOME/.android/avd/${EMULATOR_NAME}.avd/config.ini

  # Run new emulator
  pushd ${ANDROID_HOME}/emulator/

  nohup ${ANDROID_HOME}/emulator/emulator @${EMULATOR_NAME} >/dev/null 2>&1 &
}

define_android_sdk_environment_if_needed
define_path_environment_if_needed
create_and_patch_emulator

Keep in mind that the emulator must fully boot before running any test. Otherwise the tests will fail because there is still no device ready on which they can run.

Summary

  1. create an ini configuration file for the emulator
  2. run your emulator via avd manager and
  3. switch the ini file generated in 2. with the one we create in 1.

How to run an emulator in Docker?

Running an emulator in a docker is way easier than manually, because it encapsulates all this logic. If you don't have experience with docker, check this guide to get familiarized with the basics.

There are some popular docker images already built for you:

Talking about the Avito emulator, it also patches your emulator with adb commands to prevent tests flakiness and to speed them up.

Run Avito emulator
#run emulator 1 in a headless mode
docker run -d -p 5555:5555 -p 5554:5554 -p 8554:8554 --privileged avitotech/android-emulator-29:915c1f20be
adb connect localhost:5555

#run emulator 2 in a headless mode
docker run -d -p 5557:5555 -p 5556:5554 -p 8555:8554 --privileged avitotech/android-emulator-29:915c1f20be
adb connect localhost:5557

#run emulator 3 in a headless mode
docker run -d -p 5559:5555 -p 5558:5554 -p 8556:8554 --privileged avitotech/android-emulator-29:915c1f20be
adb connect localhost:5559

#...etc
Stop all emulators
docker kill $(docker ps -q)
docker rm $(docker ps -a -q)

Conclusion

  • Use docker emulators
    You'll also have the opportunity to run them with Kubernetes, to make it scalable in the future

  • Start fresh emulators on each test batch and kill them after all of your tests finished
    Emulators tend to freeze and may not work properly after idling for some time

  • Use the same emulator locally as on your CI
    All devices are different. It can save you a lot of time with debugging and understanding why your test works locally and fails on CI. It won't be possible to run Docker emulators on macOS or Windows, because of haxm#51. Use AVD to launch them on such machines (script above may help you)

!!! warning

To run an emulator on CI with a docker, make sure that nested virtualisation is supported and KVM is installed.
You can check more details [here](https://developer.android.com/studio/run/emulator-acceleration#vm-linux)