Skip to content

Commit d94c3fb

Browse files
committed
Merge branch 'main' into release/v2
* main: Prepare for release 2.28.0. Cleanup action description. Update `test-fixture` dependencies and workflows (#332) SDK command-line tools 9.0. (#331) Add emulator-boot-timeout parameter (#326) Update dependency androidx.appcompat:appcompat to v1.6.1 (#322) Add renovate.json (#320) Support non-integer API level (#317) Replace deprecated `ANDROID_SDK_ROOT` with `ANDROID_HOME`. Update npm packages. Include ACRA in list of users (#295) Update readme with new info on hypervisors (#292) SDK command-line tools 8.0. (#291)
2 parents 50986b1 + b35b1c6 commit d94c3fb

26 files changed

+337
-250
lines changed

.github/workflows/main.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,11 @@ jobs:
6161
npm run lint
6262
npm test
6363
64-
- name: Java 15
65-
uses: actions/setup-java@v3
64+
- uses: actions/setup-java@v3
6665
with:
6766
distribution: 'zulu'
68-
java-version: 15
67+
java-version: 19
68+
6969
- uses: actions/cache@v3
7070
id: avd-cache
7171
with:

.github/workflows/manually.yml

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,14 @@ jobs:
5151
npm run lint
5252
npm test
5353
54-
- name: Java 15
55-
uses: actions/setup-java@v3
54+
- uses: actions/setup-java@v3
5655
with:
5756
distribution: 'zulu'
58-
java-version: 15
59-
- uses: actions/cache@v3
57+
java-version: 19
58+
59+
- uses: gradle/gradle-build-action@v2
6060
with:
61-
path: |
62-
~/.gradle/caches
63-
~/.gradle/wrapper
64-
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}
61+
gradle-home-cache-cleanup: true
6562

6663
- name: run action
6764
uses: ./

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Change Log
22

3+
## v2.28.0
4+
5+
* Add `emulator-boot-timeout` to support configuring maximum time waiting for emulator boot. - [#326](https://github.com/ReactiveCircus/android-emulator-runner/pull/326)
6+
* Support non-integer `api-level`. - [#317](https://github.com/ReactiveCircus/android-emulator-runner/pull/317)
7+
* Replace deprecated `ANDROID_SDK_ROOT` with `ANDROID_HOME`. - [304](https://github.com/ReactiveCircus/android-emulator-runner/pull/304)
8+
* Update SDK command-line tools to `9.0`. - [#331](https://github.com/ReactiveCircus/android-emulator-runner/pull/331)
9+
* Update SDK build tools to `33.0.2`. - [#331](https://github.com/ReactiveCircus/android-emulator-runner/pull/331)
10+
311
## v2.27.0
412

513
* Added `pre-emulator-launch-script` to support running script after creating the AVD and before launching the emulator. - [#247](https://github.com/ReactiveCircus/android-emulator-runner/pull/247) @nilsreichardt.

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,11 @@ The old ARM-based emulators were slow and are no longer supported by Google. The
1010

1111
This presents a challenge when running emulators on CI especially when running emulators within a docker container, because **Nested Virtualization** must be supported by the host VM which isn't the case for most cloud-based CI providers due to infrastructural limits. If you want to learn more about Emulators on CI, here's an article [Yang](https://github.com/ychescale9) wrote: [Running Android Instrumented Tests on CI](https://dev.to/ychescale9/running-android-emulators-on-ci-from-bitrise-io-to-github-actions-3j76).
1212

13-
## HAXM support on Github's MacOS Runners
13+
## A note on VM Acceleration and why we don't need HAXM anymore
1414

15-
The 10.x **macOS** VM provided by **GitHub Actions** had **HAXM** [pre-installed](https://github.com/actions/runner-images/blob/main/images/macos/macos-10.15-Readme.md). However, Github's [macOS-11](https://github.com/actions/runner-images/blob/main/images/macos/macos-11-Readme.md) and [macOS-12](https://github.com/actions/runner-images/blob/main/images/macos/macos-12-Readme.md) VMs **no longer** come pre-installed with HAXM. See [here](https://github.com/actions/runner-images/issues/183#issuecomment-610723516) and [here](https://github.com/actions/runner-images/issues/6388) for more info.
15+
According to [this documentation](https://developer.android.com/studio/run/emulator-acceleration#vm-mac), "on Mac OS X v10.10 Yosemite and higher, the Android Emulator uses the built-in [Hypervisor.Framework](https://developer.apple.com/documentation/hypervisor) by default, and falls back to using Intel HAXM if Hypervisor.Framework fails to initialize." This means that **HAXM is only needed to achieve VM Acceleration if this default Hypervisor is not available on macOS machines.**
1616

17-
**To run with HAXM on the macOS-11 and macOS-12 agents, you must install HAXM before starting your emulator**. See: [this snippet](https://gist.github.com/mrk-han/a0a11ed9bed966bb8b775ff55f2a87e9) for more info. This will enable VM acceleration, but as of right now running with GPU acceleration, e.g. `emulator -gpu host` is not possible with Github's standard runners.
18-
19-
For Linux, Nested virtualization is possible on a self-hosted or 3rd party runner, but the VM will need to be hosted on a compatible machine that allows you to [enable KVM](https://developer.android.com/studio/run/emulator-acceleration#vm-linux), or is already configured with - for example the AWS EC2 Bare Metal instances. **The Github-hosted Linux runners are not currently KVM compatible.**
17+
**Note**: Manually enabling and downloading HAXM is not recommended because it is redundant and not needed (see above), and for users of macOS 10.13 High Sierra and higher: macOS 10.13 [disables installation of kernel extensions by default](https://developer.apple.com/library/archive/technotes/tn2459/_index.html#//apple_ref/doc/uid/DTS40017658). Because Intel HAXM is a kernel extension, we would need to manually enable its installation on the base runner VM. Furthermore, manually trying to install HAXM on a Github Runner [brings up a popup](https://github.com/ReactiveCircus/android-emulator-runner/discussions/286#discussioncomment-4026120) which further hinders tests from running.
2018

2119
## Purpose
2220

@@ -156,6 +154,7 @@ jobs:
156154
| `disk-size` | Optional | N/A | Disk size, or partition size to use for this AVD. Either in bytes or KB, MB or GB, when denoted with K, M or G. - e.g. `2048M` |
157155
| `avd-name` | Optional | `test` | Custom AVD name used for creating the Android Virtual Device. |
158156
| `force-avd-creation` | Optional | `true` | Whether to force create the AVD by overwriting an existing AVD with the same name as `avd-name` - `true` or `false`. |
157+
| `emulator-boot-timeout` | Optional | `600` | Emulator boot timeout in seconds. If it takes longer to boot, the action would fail - e.g. `300` for 5 minutes. |
159158
| `emulator-options` | Optional | See below | Command-line options used when launching the emulator (replacing all default options) - e.g. `-no-window -no-snapshot -camera-back emulated`. |
160159
| `disable-animations` | Optional | `true` | Whether to disable animations - `true` or `false`. |
161160
| `disable-spellchecker` | Optional | `false` | Whether to disable spellchecker - `true` or `false`. |
@@ -210,5 +209,6 @@ These are some of the open-source projects using (or used) **Android Emulator Ru
210209
- [dotanuki-labs/norris](https://github.com/dotanuki-labs/norris/blob/master/.github/workflows/main.yml)
211210
- [tinylog-org/tinylog](https://github.com/tinylog-org/tinylog/blob/v3.0/.github/workflows/build.yaml)
212211
- [hzi-braunschweig/SORMAS-Project](https://github.com/hzi-braunschweig/SORMAS-Project/blob/development/.github/workflows/sormas_app_ci.yml)
212+
- [ACRA/acra](https://github.com/ACRA/acra/blob/master/.github/workflows/test.yml)
213213

214214
If you are using **Android Emulator Runner** and want your project included in the list, please feel free to open a pull request.

__tests__/input-validator.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ describe('api-level validator tests', () => {
3232
validator.checkApiLevel('29');
3333
};
3434
expect(func2).not.toThrow();
35+
const func3 = () => {
36+
validator.checkApiLevel('UpsideDownCake-ext5');
37+
};
38+
expect(func3).not.toThrow();
39+
const func4 = () => {
40+
validator.checkApiLevel('TiramisuPrivacySandbox');
41+
};
42+
expect(func4).not.toThrow();
3543
});
3644
});
3745

action-types.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ inputs:
3535
type: string
3636
force-avd-creation:
3737
type: boolean
38+
emulator-boot-timeout:
39+
type: integer
3840
emulator-options:
3941
type: string
4042
disable-animations:

action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ inputs:
3333
force-avd-creation:
3434
description: 'whether to force create the AVD by overwriting an existing AVD with the same name as `avd-name` - `true` or `false`'
3535
default: 'true'
36+
emulator-boot-timeout:
37+
description: 'Emulator boot timeout in seconds. If it takes longer to boot, the action would fail - e.g. `300` for 5 minutes'
38+
default: '600'
3639
emulator-options:
3740
description: 'command-line options used when launching the emulator - e.g. `-no-window -no-snapshot -camera-back emulated`'
3841
default: '-no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim'

lib/emulator-manager.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3535
exports.killEmulator = exports.launchEmulator = void 0;
3636
const exec = __importStar(require("@actions/exec"));
3737
const fs = __importStar(require("fs"));
38-
const EMULATOR_BOOT_TIMEOUT_SECONDS = 600;
3938
/**
4039
* Creates and launches a new AVD instance with the specified configurations.
4140
*/
42-
function launchEmulator(apiLevel, target, arch, profile, cores, ramSize, heapSize, sdcardPathOrSize, diskSize, avdName, forceAvdCreation, emulatorOptions, disableAnimations, disableSpellChecker, disableLinuxHardwareAcceleration, enableHardwareKeyboard) {
41+
function launchEmulator(apiLevel, target, arch, profile, cores, ramSize, heapSize, sdcardPathOrSize, diskSize, avdName, forceAvdCreation, emulatorBootTimeout, emulatorOptions, disableAnimations, disableSpellChecker, disableLinuxHardwareAcceleration, enableHardwareKeyboard) {
4342
return __awaiter(this, void 0, void 0, function* () {
4443
try {
4544
console.log(`::group::Launch Emulator`);
@@ -73,7 +72,7 @@ function launchEmulator(apiLevel, target, arch, profile, cores, ramSize, heapSiz
7372
}
7473
// start emulator
7574
console.log('Starting emulator.');
76-
yield exec.exec(`sh -c \\"${process.env.ANDROID_SDK_ROOT}/emulator/emulator -avd "${avdName}" ${emulatorOptions} &"`, [], {
75+
yield exec.exec(`sh -c \\"${process.env.ANDROID_HOME}/emulator/emulator -avd "${avdName}" ${emulatorOptions} &"`, [], {
7776
listeners: {
7877
stderr: (data) => {
7978
if (data.toString().includes('invalid command-line parameter')) {
@@ -83,7 +82,7 @@ function launchEmulator(apiLevel, target, arch, profile, cores, ramSize, heapSiz
8382
},
8483
});
8584
// wait for emulator to complete booting
86-
yield waitForDevice();
85+
yield waitForDevice(emulatorBootTimeout);
8786
yield exec.exec(`adb shell input keyevent 82`);
8887
if (disableAnimations) {
8988
console.log('Disabling animations.');
@@ -125,12 +124,12 @@ exports.killEmulator = killEmulator;
125124
/**
126125
* Wait for emulator to boot.
127126
*/
128-
function waitForDevice() {
127+
function waitForDevice(emulatorBootTimeout) {
129128
return __awaiter(this, void 0, void 0, function* () {
130129
let booted = false;
131130
let attempts = 0;
132131
const retryInterval = 2; // retry every 2 seconds
133-
const maxAttempts = EMULATOR_BOOT_TIMEOUT_SECONDS / 2;
132+
const maxAttempts = emulatorBootTimeout / 2;
134133
while (!booted) {
135134
try {
136135
let result = '';

lib/input-validator.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ exports.VALID_TARGETS = ['default', 'google_apis', 'aosp_atd', 'google_atd', 'go
66
exports.VALID_ARCHS = ['x86', 'x86_64', 'arm64-v8a'];
77
exports.VALID_CHANNELS = ['stable', 'beta', 'dev', 'canary'];
88
function checkApiLevel(apiLevel) {
9+
if (apiLevel.startsWith('UpsideDownCake') || apiLevel === 'TiramisuPrivacySandbox')
10+
return;
911
if (isNaN(Number(apiLevel)) || !Number.isInteger(Number(apiLevel))) {
1012
throw new Error(`Unexpected API level: '${apiLevel}'.`);
1113
}

lib/main.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,8 @@ function run() {
6161
}
6262
}
6363
// API level of the platform and system image
64-
const apiLevelInput = core.getInput('api-level', { required: true });
65-
(0, input_validator_1.checkApiLevel)(apiLevelInput);
66-
const apiLevel = Number(apiLevelInput);
64+
const apiLevel = core.getInput('api-level', { required: true });
65+
(0, input_validator_1.checkApiLevel)(apiLevel);
6766
console.log(`API level: ${apiLevel}`);
6867
// target of the system image
6968
const targetInput = core.getInput('target');
@@ -100,6 +99,9 @@ function run() {
10099
(0, input_validator_1.checkForceAvdCreation)(forceAvdCreationInput);
101100
const forceAvdCreation = forceAvdCreationInput === 'true';
102101
console.log(`force avd creation: ${forceAvdCreation}`);
102+
// Emulator boot timeout seconds
103+
const emulatorBootTimeout = parseInt(core.getInput('emulator-boot-timeout'), 10);
104+
console.log(`Emulator boot timeout: ${emulatorBootTimeout}`);
103105
// emulator options
104106
const emulatorOptions = core.getInput('emulator-options').trim();
105107
console.log(`emulator options: ${emulatorOptions}`);
@@ -191,7 +193,7 @@ function run() {
191193
console.log(`::endgroup::`);
192194
}
193195
// launch an emulator
194-
yield (0, emulator_manager_1.launchEmulator)(apiLevel, target, arch, profile, cores, ramSize, heapSize, sdcardPathOrSize, diskSize, avdName, forceAvdCreation, emulatorOptions, disableAnimations, disableSpellchecker, disableLinuxHardwareAcceleration, enableHardwareKeyboard);
196+
yield (0, emulator_manager_1.launchEmulator)(apiLevel, target, arch, profile, cores, ramSize, heapSize, sdcardPathOrSize, diskSize, avdName, forceAvdCreation, emulatorBootTimeout, emulatorOptions, disableAnimations, disableSpellchecker, disableLinuxHardwareAcceleration, enableHardwareKeyboard);
195197
// execute the custom script
196198
try {
197199
// move to custom working directory if set

lib/sdk-installer.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@ const exec = __importStar(require("@actions/exec"));
3838
const io = __importStar(require("@actions/io"));
3939
const tc = __importStar(require("@actions/tool-cache"));
4040
const fs = __importStar(require("fs"));
41-
const BUILD_TOOLS_VERSION = '33.0.0';
42-
const CMDLINE_TOOLS_URL_MAC = 'https://dl.google.com/android/repository/commandlinetools-mac-8512546_latest.zip';
43-
const CMDLINE_TOOLS_URL_LINUX = 'https://dl.google.com/android/repository/commandlinetools-linux-8512546_latest.zip';
41+
const BUILD_TOOLS_VERSION = '33.0.2';
42+
// SDK command-line tools 9.0
43+
const CMDLINE_TOOLS_URL_MAC = 'https://dl.google.com/android/repository/commandlinetools-mac-9477386_latest.zip';
44+
const CMDLINE_TOOLS_URL_LINUX = 'https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip';
4445
/**
4546
* Installs & updates the Android SDK for the macOS platform, including SDK platform for the chosen API level, latest build tools, platform tools, Android Emulator,
4647
* and the system image for the chosen API level, CPU arch, and target.
@@ -51,9 +52,9 @@ function installAndroidSdk(apiLevel, target, arch, channelId, emulatorBuild, ndk
5152
console.log(`::group::Install Android SDK`);
5253
const isOnMac = process.platform === 'darwin';
5354
if (!isOnMac) {
54-
yield exec.exec(`sh -c \\"sudo chown $USER:$USER ${process.env.ANDROID_SDK_ROOT} -R`);
55+
yield exec.exec(`sh -c \\"sudo chown $USER:$USER ${process.env.ANDROID_HOME} -R`);
5556
}
56-
const cmdlineToolsPath = `${process.env.ANDROID_SDK_ROOT}/cmdline-tools`;
57+
const cmdlineToolsPath = `${process.env.ANDROID_HOME}/cmdline-tools`;
5758
if (!fs.existsSync(cmdlineToolsPath)) {
5859
console.log('Installing new cmdline-tools.');
5960
const sdkUrl = isOnMac ? CMDLINE_TOOLS_URL_MAC : CMDLINE_TOOLS_URL_LINUX;
@@ -62,21 +63,21 @@ function installAndroidSdk(apiLevel, target, arch, channelId, emulatorBuild, ndk
6263
yield io.mv(`${cmdlineToolsPath}/cmdline-tools`, `${cmdlineToolsPath}/latest`);
6364
}
6465
// add paths for commandline-tools and platform-tools
65-
core.addPath(`${cmdlineToolsPath}/latest:${cmdlineToolsPath}/latest/bin:${process.env.ANDROID_SDK_ROOT}/platform-tools`);
66+
core.addPath(`${cmdlineToolsPath}/latest:${cmdlineToolsPath}/latest/bin:${process.env.ANDROID_HOME}/platform-tools`);
6667
// set standard AVD path
6768
core.exportVariable('ANDROID_AVD_HOME', `${process.env.HOME}/.android/avd`);
6869
// accept all Android SDK licenses
6970
yield exec.exec(`sh -c \\"yes | sdkmanager --licenses > /dev/null"`);
7071
console.log('Installing latest build tools, platform tools, and platform.');
71-
yield exec.exec(`sh -c \\"sdkmanager --install 'build-tools;${BUILD_TOOLS_VERSION}' platform-tools 'platforms;android-${apiLevel}' > /dev/null"`);
72+
yield exec.exec(`sh -c \\"sdkmanager --install 'build-tools;${BUILD_TOOLS_VERSION}' platform-tools > /dev/null"`);
7273
console.log('Installing latest emulator.');
7374
yield exec.exec(`sh -c \\"sdkmanager --install emulator --channel=${channelId} > /dev/null"`);
7475
if (emulatorBuild) {
7576
console.log(`Installing emulator build ${emulatorBuild}.`);
7677
// TODO find out the correct download URLs for all build ids
7778
const downloadUrlSuffix = Number(emulatorBuild.charAt(0)) > 6 ? `_x64-${emulatorBuild}` : `-${emulatorBuild}`;
7879
yield exec.exec(`curl -fo emulator.zip https://dl.google.com/android/repository/emulator-${isOnMac ? 'darwin' : 'linux'}${downloadUrlSuffix}.zip`);
79-
yield exec.exec(`unzip -o -q emulator.zip -d ${process.env.ANDROID_SDK_ROOT}`);
80+
yield exec.exec(`unzip -o -q emulator.zip -d ${process.env.ANDROID_HOME}`);
8081
yield io.rmRF('emulator.zip');
8182
}
8283
console.log('Installing system images.');

package-lock.json

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

renovate.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
3+
"extends": [
4+
"config:base"
5+
]
6+
}

0 commit comments

Comments
 (0)