From 5c6d293ebfb96d5ec56814bc2ae44209eb923caa Mon Sep 17 00:00:00 2001 From: Joshua Ford Date: Thu, 31 Oct 2019 17:51:35 -0500 Subject: [PATCH] CI: Use emulator acceleration To take advantage of some of the new nested virtualization capabilities of some of the images in Travis, you must be using the newest LTS release of Ubuntu, 18.04 Bionic Beaver. However, the Travis image of Bionic does not include support for JDK 8, which we need to utilize the Android SDK manager. To circumvent this issue, we change from the "android" language type to "generic", and take care of both the JDK and the Android SDK ourselves. As such, this commit makes the following changes: * Switch `dist` from `trusty` to `bionic` * Switch `language` from `android` to `generic` * Enable the use of `sudo` * Install libpulse0 for emulator audio * Set up KVM inside the allocated Travis image * Use Gravis repository to download and install Java * Version android-wait-for-emulator in our repo * Download and install the Android SDK ourselves * Switch to `emulator-headless` for the x86 emulators Since we're free to switch Java versions as we please, we can finally support JDK 11 by switching to it after starting our emulator. --- .travis.yml | 86 ++++++++++++++++++++++-------- tools/android-wait-for-emulator.sh | 26 +++++++++ 2 files changed, 90 insertions(+), 22 deletions(-) create mode 100755 tools/android-wait-for-emulator.sh diff --git a/.travis.yml b/.travis.yml index 74bf696fb8..129b7fafaf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,28 @@ -language: android -dist: trusty +sudo: true +language: generic +dist: bionic -jdk: - - oraclejdk8 +addons: + apt: + packages: + - bridge-utils + - libpulse0 + - libvirt-bin + - qemu-kvm + - virtinst + - ubuntu-vm-builder env: global: - - ADB_INSTALL_TIMEOUT=8 - ABI=x86_64 + - ADB_INSTALL_TIMEOUT=8 + - ANDROID_HOME=${HOME}/android-sdk + - ANDROID_TOOLS_URL="https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip" - EMU_FLAVOR=default # use google_apis flavor if no default flavor emulator - # PATH order is incredibly important. e.g. the 'emulator' script exists in more than one place! - - ANDROID_HOME=/usr/local/android-sdk + - GRAVIS="https://raw.githubusercontent.com/DanySK/Gravis-CI/master/" + - JDK="1.8" - TOOLS=${ANDROID_HOME}/tools + # PATH order is incredibly important. e.g. the 'emulator' script exists in more than one place! - PATH=${ANDROID_HOME}:${ANDROID_HOME}/emulator:${TOOLS}:${TOOLS}/bin:${ANDROID_HOME}/platform-tools:${PATH} matrix: #- API=15 # only runs locally. Create+Start once from AndroidStudio to init sdcard. Then only from command-line w/-engine classic @@ -34,33 +45,44 @@ jobs: fast_finish: true # We can report success without waiting for jobs that we # allow / expect to fail. include: - - jdk: oraclejdk11 - env: API=24 + - env: API=24 JDK="1.11" # The test stage is implicit, we only need to define a post-test stage for codacy finalization - stage: finalize_coverage env: FINALIZE_COVERAGE=TRUE API=NONE install: skip script: echo finalize codacy coverage uploads allow_failures: - - jdk: oraclejdk11 + - env: API=24 JDK="1.11" # API=28/Q are probably fixable but we don't need allow_failures to be on # in master to work through them. #- env: API=28 #- env: API=Q -android: - components: - # installing tools to start, then use `sdkmanager` below to get the rest - - tools +before_install: + # Set up KVM + - sudo adduser $USER libvirt + - sudo adduser $USER kvm -licenses: - - 'android-sdk-preview-license-.+' - - 'android-sdk-license-.+' - - 'google-gdk-license-.+' + # Set up JDK 8 for Android SDK + - curl "${GRAVIS}.install-jdk-travis.sh" --output ~/.install-jdk-travis.sh + - export TARGET_JDK="${JDK}" + - JDK="1.8" + - source ~/.install-jdk-travis.sh + + # Set up Android SDK + - wget -q "${ANDROID_TOOLS_URL}" -O android-sdk-tools.zip + - unzip -q android-sdk-tools.zip -d ${ANDROID_HOME} + - rm android-sdk-tools.zip + + # Avoid harmless sdkmanager warning + - mkdir ~/.android + - echo 'count=0' > ~/.android/repositories.cfg + + # Accept all Android license agreements + - yes | sdkmanager --licenses -# Emulator Management: Create, Start and Wait install: - - echo 'count=0' > /home/travis/.android/repositories.cfg # Avoid harmless sdkmanager warning + # Download SDK tools - echo y | sdkmanager "platform-tools" >/dev/null - echo y | sdkmanager "tools" >/dev/null # A second time per Travis docs, gets latest versions - echo y | sdkmanager "build-tools;28.0.3" >/dev/null # Implicit gradle dependency - gradle drives changes @@ -69,11 +91,28 @@ install: - echo y | sdkmanager "emulator" >/dev/null - echo y | sdkmanager "extras;android;m2repository" >/dev/null - echo y | sdkmanager "system-images;android-$API;$EMU_FLAVOR;$ABI" >/dev/null # install our emulator + + # Create an Android emulator - echo no | avdmanager create avd --force -n test -k "system-images;android-$API;$EMU_FLAVOR;$ABI" -c 10M - - emulator -verbose -avd test -no-accel -no-snapshot -no-window $AUDIO -camera-back none -camera-front none -selinux permissive -qemu -m 2048 & - - android-wait-for-emulator + - | + EMU_PARAMS="-verbose -no-snapshot -no-window -camera-back none -camera-front none -selinux permissive -qemu -m 2048" + EMU_COMMAND="emulator" + if [[ $ABI =~ "x86" ]]; then + EMU_COMMAND="emulator-headless" + fi + # This double "sudo" monstrosity is used to have Travis execute the + # emulator with its new group permissions and help preserve the rule + # of least privilege. + sudo -E sudo -u $USER -E bash -c "${ANDROID_HOME}/emulator/${EMU_COMMAND} -avd test ${AUDIO} ${EMU_PARAMS} &" + + # Wait for emulator to be ready + - ./tools/android-wait-for-emulator.sh - adb shell input keyevent 82 & + # Switch back to our target JDK version to build and run tests + - JDK="${TARGET_JDK}" + - source ~/.install-jdk-travis.sh + script: - ./gradlew jacocoTestReport # This produces an error while doing the API getprop on API 28... @@ -82,6 +121,8 @@ after_success: before_cache: - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock + - curl "${GRAVIS}.clean_gradle_cache.sh" --output ~/.clean_gradle_cache.sh + - bash ~/.clean_gradle_cache.sh cache: directories: @@ -91,3 +132,4 @@ cache: notifications: email: - flerda+ankidroid-continuous@gmail.com + diff --git a/tools/android-wait-for-emulator.sh b/tools/android-wait-for-emulator.sh new file mode 100755 index 0000000000..6c4ee96019 --- /dev/null +++ b/tools/android-wait-for-emulator.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Originally written by Ralf Kistner , but placed in the public domain + +set +e + +bootanim="" +failcounter=0 +timeout_in_sec=600 # 10 minutes + +until [[ "$bootanim" =~ "stopped" ]]; do + bootanim=`adb -e shell getprop init.svc.bootanim 2>&1 &` + if [[ "$bootanim" =~ "device not found" || "$bootanim" =~ "device offline" + || "$bootanim" =~ "running" || "$bootanim" =~ "error: no emulators found" ]]; then + let "failcounter += 1" + echo "Waiting for emulator to start" + if [[ $failcounter -gt timeout_in_sec ]]; then + echo "Timeout ($timeout_in_sec seconds) reached; failed to start emulator" + exit 1 + fi + fi + sleep 1 +done + +echo "Emulator is ready" +