Using gradle managed devices for Android

Hi everyone,

In November 2022, the Gradle-managed devices were introduced for Android. It hopefully would make running tests more reliable by adding consistency between local and CI environments.

The Gradle task will simply take over anything related to creating the emulator, running the instrumented tests, and providing the test results in the build folder. The task will even automatically detect the CPU type of the environment and set up the device accordingly, which means the same config can run on a local ARM environment and on an x86 CI environment without changes. This is all simpler, requires less configuration, and Gradle tasks are more familiar to Android developers. Also, it is supported by the Android team at Google.

All one has to do, is to add the device in their module’s build.gradle file:

android {
  testOptions {
    managedDevices {
      devices {
        maybeCreate<>("pixel2api31").apply {
          device = "Pixel 2"
          apiLevel = 31
          systemImageSource = "google"

Now, the instrumented tests for the debug build variant can be run using ./gradlew pixel2api31DebugAndroidTest

More info about Gradle Managed devices in Android official docs.

The Challenge is to run on CircleCI: using it requires vt-x/haxm support.

The MacOS executors seem to provide vt-x, and I also used them before CircleCI provides the android machine images to manually set up the Android environment. Now I am back to the MacOS to use the gradle-managed devices.

The following script installs the android command line tools, accepts the licenses, and eventually runs the instrumented tests:

# install android commandline tools and required packages
brew install --cask android-commandlinetools
yes | sdkmanager "tools" "platform-tools" "build-tools;33.0.1" "platforms;android-33" "system-images;android-31;google_apis;x86_64" "extras;intel;Hardware_Accelerated_Execution_Manager"

# accept licenses
yes | sdkmanager --licenses
export ANDROID_HOME=/usr/local/share/android-commandlinetools
export PATH=$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/tools/bin:$ANDROID_HOME/platform-tools

# install intel haxm
cd $ANDROID_HOME/extras/intel/Hardware_Accelerated_Execution_Manager/
chmod +x
sudo ./
/usr/local/share/android-commandlinetools/tools/emulator -accel-check
cd ~/project/

# run the instrumented tests using gradle managed devices
./gradlew pixel2api31DebugAndroidTest

Using this script in a step will endup with the following error:

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:pixel2api31Setup'.
> A failure occurred while executing$ManagedDeviceSetupRunnable
   > java.lang.IllegalStateException: Gradle was not able to complete device setup for: dev31_google_apis_x86_64_Pixel_2
     This could be due to having insufficient resources to provision the number of
     devices requested. Try running the test again and request fewer devices or
     fewer shards.

The full CircleCI step (having the script mentioned above under /scripts/

      xcode: 11.7.0
      resource_class: large
      - checkout
      - run:
          name: Run instrumented tests
          command: |
      - store_test_results:
          path: app/build/outputs/androidTest-results
      - store_artifacts:
          path: app/build/outputs/managed_device_android_test_additional_output/pixel2api31/screc

Even though the macOS machines on CircleCI seem to support nested virtualization, this is failing.
Any help to fix this is appreciated! :slight_smile: