mirror of
https://github.com/reactivecircus/android-emulator-runner.git
synced 2026-08-31 17:49:33 +00:00
Support API levels for SDK extensions and add missing targets for automotive and desktop. (#428)
This commit is contained in:
@@ -39,6 +39,11 @@ jobs:
|
|||||||
api-level: 35
|
api-level: 35
|
||||||
target: google_apis
|
target: google_apis
|
||||||
arch: x86_64
|
arch: x86_64
|
||||||
|
- os: ubuntu-latest
|
||||||
|
api-level: 34-ext10
|
||||||
|
target: android-automotive
|
||||||
|
arch: x86_64
|
||||||
|
system-image-api-level: 34-ext9
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
@@ -85,6 +90,7 @@ jobs:
|
|||||||
api-level: ${{ matrix.api-level }}
|
api-level: ${{ matrix.api-level }}
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
arch: ${{ matrix.arch }}
|
arch: ${{ matrix.arch }}
|
||||||
|
system-image-api-level: ${{ matrix.system-image-api-level }}
|
||||||
profile: Galaxy Nexus
|
profile: Galaxy Nexus
|
||||||
cores: 2
|
cores: 2
|
||||||
sdcard-path-or-size: 100M
|
sdcard-path-or-size: 100M
|
||||||
@@ -102,6 +108,7 @@ jobs:
|
|||||||
api-level: ${{ matrix.api-level }}
|
api-level: ${{ matrix.api-level }}
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
arch: ${{ matrix.arch }}
|
arch: ${{ matrix.arch }}
|
||||||
|
system-image-api-level: ${{ matrix.system-image-api-level }}
|
||||||
profile: Galaxy Nexus
|
profile: Galaxy Nexus
|
||||||
cores: 2
|
cores: 2
|
||||||
ram-size: 2048M
|
ram-size: 2048M
|
||||||
|
|||||||
@@ -7,11 +7,13 @@ on:
|
|||||||
required: true
|
required: true
|
||||||
default: 'ubuntu-latest'
|
default: 'ubuntu-latest'
|
||||||
api-level:
|
api-level:
|
||||||
description: 'API level of the platform and system image'
|
description: 'API level of the platform and system image (if not overridden with system-image-api-level input) - e.g. 33, 35-ext15, Baklava'
|
||||||
required: true
|
required: true
|
||||||
default: '34'
|
default: '34'
|
||||||
|
system-image-api-level:
|
||||||
|
description: 'API level of the system image - e.g. 34-ext10, 35-ext15'
|
||||||
target:
|
target:
|
||||||
description: 'target of the system image - default, google_apis, google_apis_playstore, aosp_atd, google_atd, android-wear, android-wear-cn, android-tv or google-tv'
|
description: 'target of the system image - default, google_apis, google_apis_playstore, aosp_atd, google_atd, android-wear, android-wear-cn, android-tv, google-tv, android-automotive, android-automotive-playstore or android-desktop'
|
||||||
required: true
|
required: true
|
||||||
default: 'default'
|
default: 'default'
|
||||||
arch:
|
arch:
|
||||||
@@ -68,6 +70,7 @@ jobs:
|
|||||||
api-level: ${{ github.event.inputs.api-level }}
|
api-level: ${{ github.event.inputs.api-level }}
|
||||||
target: ${{ github.event.inputs.target }}
|
target: ${{ github.event.inputs.target }}
|
||||||
arch: ${{ github.event.inputs.arch }}
|
arch: ${{ github.event.inputs.arch }}
|
||||||
|
system-image-api-level: ${{ github.event.inputs.system-image-api-level }}
|
||||||
profile: Galaxy Nexus
|
profile: Galaxy Nexus
|
||||||
emulator-options: ${{ github.event.inputs.emulator-options }}
|
emulator-options: ${{ github.event.inputs.emulator-options }}
|
||||||
emulator-build: ${{ github.event.inputs.emulator-build }}
|
emulator-build: ${{ github.event.inputs.emulator-build }}
|
||||||
|
|||||||
@@ -119,6 +119,31 @@ jobs:
|
|||||||
script: ./gradlew connectedCheck
|
script: ./gradlew connectedCheck
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you need a specific [SDKExtension](https://developer.android.com/guide/sdk-extensions) for the system image but not the platform
|
||||||
|
|
||||||
|
```yml
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Enable KVM
|
||||||
|
run: |
|
||||||
|
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
|
||||||
|
sudo udevadm control --reload-rules
|
||||||
|
sudo udevadm trigger --name-match=kvm
|
||||||
|
|
||||||
|
- name: run tests
|
||||||
|
uses: reactivecircus/android-emulator-runner@v2
|
||||||
|
with:
|
||||||
|
api-level: 34
|
||||||
|
system-image-api-level: 34-ext9
|
||||||
|
target: android-automotive
|
||||||
|
script: ./gradlew connectedCheck
|
||||||
|
```
|
||||||
|
|
||||||
We can significantly reduce emulator startup time by setting up AVD snapshot caching:
|
We can significantly reduce emulator startup time by setting up AVD snapshot caching:
|
||||||
|
|
||||||
1. add a `gradle/actions/setup-gradle@v4` step for caching Gradle, more details see [#229](https://github.com/ReactiveCircus/android-emulator-runner/issues/229)
|
1. add a `gradle/actions/setup-gradle@v4` step for caching Gradle, more details see [#229](https://github.com/ReactiveCircus/android-emulator-runner/issues/229)
|
||||||
@@ -180,7 +205,8 @@ jobs:
|
|||||||
| **Input** | **Required** | **Default** | **Description** |
|
| **Input** | **Required** | **Default** | **Description** |
|
||||||
|-|-|-|-|
|
|-|-|-|-|
|
||||||
| `api-level` | Required | N/A | API level of the platform system image - e.g. 23 for Android Marshmallow, 29 for Android 10. **Minimum API level supported is 15**. |
|
| `api-level` | Required | N/A | API level of the platform system image - e.g. 23 for Android Marshmallow, 29 for Android 10. **Minimum API level supported is 15**. |
|
||||||
| `target` | Optional | `default` | Target of the system image - `default`, `google_apis`, `playstore`, `android-wear`, `android-wear-cn`, `android-tv`, `google-tv`, `aosp_atd` or `google_atd`. Note that `aosp_atd` and `google_atd` currently require the following: `api-level: 30`, `arch: x86` or `arch: arm64-v8` and `channel: canary`. |
|
| `system-image-api-level` | Optional | `ap-level` | API level of the system image - e.g. 23 for Android Marshmallow, 29 for Android 10. |
|
||||||
|
| `target` | Optional | `default` | Target of the system image - `default`, `google_apis`, `playstore`, `android-wear`, `android-wear-cn`, `android-tv`, `google-tv`, `aosp_atd`, `google_atd`, `android-automotive`, `android-automotive-playstore` or `android-desktop`. Note that `aosp_atd` and `google_atd` currently require the following: `api-level: 30`, `arch: x86` or `arch: arm64-v8` and `channel: canary`. |
|
||||||
| `arch` | Optional | `x86` | CPU architecture of the system image - `x86`, `x86_64` or `arm64-v8a`. Note that `x86_64` image is only available for API 21+. `arm64-v8a` images require Android 4.2+ and are limited to fewer API levels (e.g. 30). |
|
| `arch` | Optional | `x86` | CPU architecture of the system image - `x86`, `x86_64` or `arm64-v8a`. Note that `x86_64` image is only available for API 21+. `arm64-v8a` images require Android 4.2+ and are limited to fewer API levels (e.g. 30). |
|
||||||
| `profile` | Optional | N/A | Hardware profile used for creating the AVD - e.g. `Nexus 6`. For a list of all profiles available, run `avdmanager list device`. |
|
| `profile` | Optional | N/A | Hardware profile used for creating the AVD - e.g. `Nexus 6`. For a list of all profiles available, run `avdmanager list device`. |
|
||||||
| `cores` | Optional | 2 | Number of cores to use for the emulator (`hw.cpu.ncore` in config.ini). |
|
| `cores` | Optional | 2 | Number of cores to use for the emulator (`hw.cpu.ncore` in config.ini). |
|
||||||
@@ -243,5 +269,6 @@ These are some of the open-source projects using (or used) **Android Emulator Ru
|
|||||||
- [ACRA/acra](https://github.com/ACRA/acra/blob/master/.github/workflows/test.yml)
|
- [ACRA/acra](https://github.com/ACRA/acra/blob/master/.github/workflows/test.yml)
|
||||||
- [bitfireAT/davx5-ose](https://github.com/bitfireAT/davx5-ose/blob/dev-ose/.github/workflows/test-dev.yml)
|
- [bitfireAT/davx5-ose](https://github.com/bitfireAT/davx5-ose/blob/dev-ose/.github/workflows/test-dev.yml)
|
||||||
- [robolectric/robolectric](https://github.com/robolectric/robolectric/blob/master/.github/workflows/tests.yml)
|
- [robolectric/robolectric](https://github.com/robolectric/robolectric/blob/master/.github/workflows/tests.yml)
|
||||||
|
- [home-assistant/android](https://github.com/home-assistant/android/blob/master/.github/workflows/pr.yml)
|
||||||
|
|
||||||
If you are using **Android Emulator Runner** and want your project included in the list, please feel free to open a pull request.
|
If you are using **Android Emulator Runner** and want your project included in the list, please feel free to open a pull request.
|
||||||
|
|||||||
@@ -1,49 +1,6 @@
|
|||||||
import * as validator from '../src/input-validator';
|
import * as validator from '../src/input-validator';
|
||||||
import { MAX_PORT, MIN_PORT } from '../src/input-validator';
|
import { MAX_PORT, MIN_PORT } from '../src/input-validator';
|
||||||
|
|
||||||
describe('api-level validator tests', () => {
|
|
||||||
it('Throws if api-level is not a number', () => {
|
|
||||||
const func = () => {
|
|
||||||
validator.checkApiLevel('api');
|
|
||||||
};
|
|
||||||
expect(func).toThrowError(`Unexpected API level: 'api'.`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Throws if api-level is not an integer', () => {
|
|
||||||
const func = () => {
|
|
||||||
validator.checkApiLevel('29.1');
|
|
||||||
};
|
|
||||||
expect(func).toThrowError(`Unexpected API level: '29.1'.`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Throws if api-level is lower than min API supported', () => {
|
|
||||||
const func = () => {
|
|
||||||
validator.checkApiLevel('14');
|
|
||||||
};
|
|
||||||
expect(func).toThrowError(`Minimum API level supported is ${validator.MIN_API_LEVEL}.`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Validates successfully with valid api-level', () => {
|
|
||||||
const func1 = () => {
|
|
||||||
validator.checkApiLevel('15');
|
|
||||||
};
|
|
||||||
expect(func1).not.toThrow();
|
|
||||||
|
|
||||||
const func2 = () => {
|
|
||||||
validator.checkApiLevel('29');
|
|
||||||
};
|
|
||||||
expect(func2).not.toThrow();
|
|
||||||
const func3 = () => {
|
|
||||||
validator.checkApiLevel('UpsideDownCake-ext5');
|
|
||||||
};
|
|
||||||
expect(func3).not.toThrow();
|
|
||||||
const func4 = () => {
|
|
||||||
validator.checkApiLevel('TiramisuPrivacySandbox');
|
|
||||||
};
|
|
||||||
expect(func4).not.toThrow();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('target validator tests', () => {
|
describe('target validator tests', () => {
|
||||||
it('Throws if target is unknown', () => {
|
it('Throws if target is unknown', () => {
|
||||||
const func = () => {
|
const func = () => {
|
||||||
@@ -97,6 +54,21 @@ describe('target validator tests', () => {
|
|||||||
validator.checkTarget('google-tv');
|
validator.checkTarget('google-tv');
|
||||||
};
|
};
|
||||||
expect(func9).not.toThrow();
|
expect(func9).not.toThrow();
|
||||||
|
|
||||||
|
const func10 = () => {
|
||||||
|
validator.checkTarget('android-automotive');
|
||||||
|
};
|
||||||
|
expect(func10).not.toThrow();
|
||||||
|
|
||||||
|
const func11 = () => {
|
||||||
|
validator.checkTarget('android-automotive-playstore');
|
||||||
|
};
|
||||||
|
expect(func11).not.toThrow();
|
||||||
|
|
||||||
|
const func12 = () => {
|
||||||
|
validator.checkTarget('android-desktop');
|
||||||
|
};
|
||||||
|
expect(func12).not.toThrow();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+6
-1
@@ -1,6 +1,8 @@
|
|||||||
inputs:
|
inputs:
|
||||||
api-level:
|
api-level:
|
||||||
type: integer
|
type: string
|
||||||
|
system-image-api-level:
|
||||||
|
type: string
|
||||||
target:
|
target:
|
||||||
type: enum
|
type: enum
|
||||||
allowed-values:
|
allowed-values:
|
||||||
@@ -13,6 +15,9 @@ inputs:
|
|||||||
- android-wear-cn
|
- android-wear-cn
|
||||||
- android-tv
|
- android-tv
|
||||||
- google-tv
|
- google-tv
|
||||||
|
- android-automotive
|
||||||
|
- android-automotive-playstore
|
||||||
|
- android-desktop
|
||||||
arch:
|
arch:
|
||||||
type: enum
|
type: enum
|
||||||
allowed-values:
|
allowed-values:
|
||||||
|
|||||||
+5
-2
@@ -6,10 +6,13 @@ branding:
|
|||||||
color: 'green'
|
color: 'green'
|
||||||
inputs:
|
inputs:
|
||||||
api-level:
|
api-level:
|
||||||
description: 'API level of the platform and system image - e.g. 23 for Android Marshmallow, 29 for Android 10'
|
description: 'API level of the platform and system image - e.g. 23, 33, 35-ext15, Baklava'
|
||||||
required: true
|
required: true
|
||||||
|
system-image-api-level:
|
||||||
|
description: 'API level of the system image - e.g. 34-ext10, 35-ext15. If not set the `api-level` input will be used.'
|
||||||
|
required: false
|
||||||
target:
|
target:
|
||||||
description: 'target of the system image - default, google_apis, google_apis_playstore, aosp_atd, google_atd, android-wear, android-wear-cn, android-tv or google-tv'
|
description: 'target of the system image - default, google_apis, google_apis_playstore, aosp_atd, google_atd, android-wear, android-wear-cn, android-tv, google-tv, android-automotive, android-automotive-playstore or android-desktop'
|
||||||
default: 'default'
|
default: 'default'
|
||||||
arch:
|
arch:
|
||||||
description: 'CPU architecture of the system image - x86, x86_64 or arm64-v8a'
|
description: 'CPU architecture of the system image - x86, x86_64 or arm64-v8a'
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ const fs = __importStar(require("fs"));
|
|||||||
/**
|
/**
|
||||||
* Creates and launches a new AVD instance with the specified configurations.
|
* Creates and launches a new AVD instance with the specified configurations.
|
||||||
*/
|
*/
|
||||||
function launchEmulator(apiLevel, target, arch, profile, cores, ramSize, heapSize, sdcardPathOrSize, diskSize, avdName, forceAvdCreation, emulatorBootTimeout, port, emulatorOptions, disableAnimations, disableSpellChecker, disableLinuxHardwareAcceleration, enableHardwareKeyboard) {
|
function launchEmulator(systemImageApiLevel, target, arch, profile, cores, ramSize, heapSize, sdcardPathOrSize, diskSize, avdName, forceAvdCreation, emulatorBootTimeout, port, emulatorOptions, disableAnimations, disableSpellChecker, disableLinuxHardwareAcceleration, enableHardwareKeyboard) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
try {
|
try {
|
||||||
console.log(`::group::Launch Emulator`);
|
console.log(`::group::Launch Emulator`);
|
||||||
@@ -48,7 +48,7 @@ function launchEmulator(apiLevel, target, arch, profile, cores, ramSize, heapSiz
|
|||||||
const profileOption = profile.trim() !== '' ? `--device '${profile}'` : '';
|
const profileOption = profile.trim() !== '' ? `--device '${profile}'` : '';
|
||||||
const sdcardPathOrSizeOption = sdcardPathOrSize.trim() !== '' ? `--sdcard '${sdcardPathOrSize}'` : '';
|
const sdcardPathOrSizeOption = sdcardPathOrSize.trim() !== '' ? `--sdcard '${sdcardPathOrSize}'` : '';
|
||||||
console.log(`Creating AVD.`);
|
console.log(`Creating AVD.`);
|
||||||
yield exec.exec(`sh -c \\"echo no | avdmanager create avd --force -n "${avdName}" --abi '${target}/${arch}' --package 'system-images;android-${apiLevel};${target};${arch}' ${profileOption} ${sdcardPathOrSizeOption}"`);
|
yield exec.exec(`sh -c \\"echo no | avdmanager create avd --force -n "${avdName}" --abi '${target}/${arch}' --package 'system-images;android-${systemImageApiLevel};${target};${arch}' ${profileOption} ${sdcardPathOrSizeOption}"`);
|
||||||
}
|
}
|
||||||
if (cores) {
|
if (cores) {
|
||||||
yield exec.exec(`sh -c \\"printf 'hw.cpu.ncore=${cores}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`);
|
yield exec.exec(`sh -c \\"printf 'hw.cpu.ncore=${cores}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`);
|
||||||
|
|||||||
+15
-14
@@ -1,24 +1,25 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.checkDiskSize = exports.checkEmulatorBuild = exports.checkEnableHardwareKeyboard = exports.checkDisableLinuxHardwareAcceleration = exports.checkDisableSpellchecker = exports.checkDisableAnimations = exports.checkPort = exports.checkForceAvdCreation = exports.checkChannel = exports.checkArch = exports.checkTarget = exports.checkApiLevel = exports.PREVIEW_API_LEVELS = exports.MAX_PORT = exports.MIN_PORT = exports.VALID_CHANNELS = exports.VALID_ARCHS = exports.VALID_TARGETS = exports.MIN_API_LEVEL = void 0;
|
exports.checkDiskSize = exports.checkEmulatorBuild = exports.checkEnableHardwareKeyboard = exports.checkDisableLinuxHardwareAcceleration = exports.checkDisableSpellchecker = exports.checkDisableAnimations = exports.checkPort = exports.checkForceAvdCreation = exports.checkChannel = exports.checkArch = exports.checkTarget = exports.MAX_PORT = exports.MIN_PORT = exports.VALID_CHANNELS = exports.VALID_ARCHS = exports.VALID_TARGETS = exports.MIN_API_LEVEL = void 0;
|
||||||
exports.MIN_API_LEVEL = 15;
|
exports.MIN_API_LEVEL = 15;
|
||||||
exports.VALID_TARGETS = ['default', 'google_apis', 'aosp_atd', 'google_atd', 'google_apis_playstore', 'android-wear', 'android-wear-cn', 'android-tv', 'google-tv'];
|
exports.VALID_TARGETS = [
|
||||||
|
'default',
|
||||||
|
'google_apis',
|
||||||
|
'aosp_atd',
|
||||||
|
'google_atd',
|
||||||
|
'google_apis_playstore',
|
||||||
|
'android-wear',
|
||||||
|
'android-wear-cn',
|
||||||
|
'android-tv',
|
||||||
|
'google-tv',
|
||||||
|
'android-automotive',
|
||||||
|
'android-automotive-playstore',
|
||||||
|
'android-desktop',
|
||||||
|
];
|
||||||
exports.VALID_ARCHS = ['x86', 'x86_64', 'arm64-v8a'];
|
exports.VALID_ARCHS = ['x86', 'x86_64', 'arm64-v8a'];
|
||||||
exports.VALID_CHANNELS = ['stable', 'beta', 'dev', 'canary'];
|
exports.VALID_CHANNELS = ['stable', 'beta', 'dev', 'canary'];
|
||||||
exports.MIN_PORT = 5554;
|
exports.MIN_PORT = 5554;
|
||||||
exports.MAX_PORT = 5584;
|
exports.MAX_PORT = 5584;
|
||||||
exports.PREVIEW_API_LEVELS = ['Tiramisu', 'UpsideDownCake', 'VanillaIceCream', 'Baklava'];
|
|
||||||
function checkApiLevel(apiLevel) {
|
|
||||||
if (exports.PREVIEW_API_LEVELS.some((previewLevel) => apiLevel.startsWith(previewLevel)))
|
|
||||||
return;
|
|
||||||
if (isNaN(Number(apiLevel)) || !Number.isInteger(Number(apiLevel))) {
|
|
||||||
throw new Error(`Unexpected API level: '${apiLevel}'.`);
|
|
||||||
}
|
|
||||||
if (Number(apiLevel) < exports.MIN_API_LEVEL) {
|
|
||||||
throw new Error(`Minimum API level supported is ${exports.MIN_API_LEVEL}.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.checkApiLevel = checkApiLevel;
|
|
||||||
function checkTarget(target) {
|
function checkTarget(target) {
|
||||||
if (!exports.VALID_TARGETS.includes(target)) {
|
if (!exports.VALID_TARGETS.includes(target)) {
|
||||||
throw new Error(`Value for input.target '${target}' is unknown. Supported options: ${exports.VALID_TARGETS}.`);
|
throw new Error(`Value for input.target '${target}' is unknown. Supported options: ${exports.VALID_TARGETS}.`);
|
||||||
|
|||||||
+7
-3
@@ -63,8 +63,12 @@ function run() {
|
|||||||
}
|
}
|
||||||
// API level of the platform and system image
|
// API level of the platform and system image
|
||||||
const apiLevel = core.getInput('api-level', { required: true });
|
const apiLevel = core.getInput('api-level', { required: true });
|
||||||
(0, input_validator_1.checkApiLevel)(apiLevel);
|
|
||||||
console.log(`API level: ${apiLevel}`);
|
console.log(`API level: ${apiLevel}`);
|
||||||
|
let systemImageApiLevel = core.getInput('system-image-api-level');
|
||||||
|
if (!systemImageApiLevel) {
|
||||||
|
systemImageApiLevel = apiLevel;
|
||||||
|
}
|
||||||
|
console.log(`System image API level: ${systemImageApiLevel}`);
|
||||||
// target of the system image
|
// target of the system image
|
||||||
const targetInput = core.getInput('target');
|
const targetInput = core.getInput('target');
|
||||||
const target = targetInput == 'playstore' ? 'google_apis_playstore' : targetInput;
|
const target = targetInput == 'playstore' ? 'google_apis_playstore' : targetInput;
|
||||||
@@ -179,7 +183,7 @@ function run() {
|
|||||||
}));
|
}));
|
||||||
console.log(`::endgroup::`);
|
console.log(`::endgroup::`);
|
||||||
// install SDK
|
// install SDK
|
||||||
yield (0, sdk_installer_1.installAndroidSdk)(apiLevel, target, arch, channelId, emulatorBuild, ndkVersion, cmakeVersion);
|
yield (0, sdk_installer_1.installAndroidSdk)(apiLevel, systemImageApiLevel, target, arch, channelId, emulatorBuild, ndkVersion, cmakeVersion);
|
||||||
// execute pre emulator launch script if set
|
// execute pre emulator launch script if set
|
||||||
if (preEmulatorLaunchScripts !== undefined) {
|
if (preEmulatorLaunchScripts !== undefined) {
|
||||||
console.log(`::group::Run pre emulator launch script`);
|
console.log(`::group::Run pre emulator launch script`);
|
||||||
@@ -198,7 +202,7 @@ function run() {
|
|||||||
console.log(`::endgroup::`);
|
console.log(`::endgroup::`);
|
||||||
}
|
}
|
||||||
// launch an emulator
|
// launch an emulator
|
||||||
yield (0, emulator_manager_1.launchEmulator)(apiLevel, target, arch, profile, cores, ramSize, heapSize, sdcardPathOrSize, diskSize, avdName, forceAvdCreation, emulatorBootTimeout, port, emulatorOptions, disableAnimations, disableSpellchecker, disableLinuxHardwareAcceleration, enableHardwareKeyboard);
|
yield (0, emulator_manager_1.launchEmulator)(systemImageApiLevel, target, arch, profile, cores, ramSize, heapSize, sdcardPathOrSize, diskSize, avdName, forceAvdCreation, emulatorBootTimeout, port, emulatorOptions, disableAnimations, disableSpellchecker, disableLinuxHardwareAcceleration, enableHardwareKeyboard);
|
||||||
// execute the custom script
|
// execute the custom script
|
||||||
try {
|
try {
|
||||||
// move to custom working directory if set
|
// move to custom working directory if set
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ const CMDLINE_TOOLS_URL_LINUX = 'https://dl.google.com/android/repository/comman
|
|||||||
* Installs & updates the Android SDK for the macOS platform, including SDK platform for the chosen API level, latest build tools, platform tools, Android Emulator,
|
* Installs & updates the Android SDK for the macOS platform, including SDK platform for the chosen API level, latest build tools, platform tools, Android Emulator,
|
||||||
* and the system image for the chosen API level, CPU arch, and target.
|
* and the system image for the chosen API level, CPU arch, and target.
|
||||||
*/
|
*/
|
||||||
function installAndroidSdk(apiLevel, target, arch, channelId, emulatorBuild, ndkVersion, cmakeVersion) {
|
function installAndroidSdk(apiLevel, systemImageApiLevel, target, arch, channelId, emulatorBuild, ndkVersion, cmakeVersion) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
try {
|
try {
|
||||||
console.log(`::group::Install Android SDK`);
|
console.log(`::group::Install Android SDK`);
|
||||||
@@ -95,7 +95,7 @@ function installAndroidSdk(apiLevel, target, arch, channelId, emulatorBuild, ndk
|
|||||||
yield io.rmRF('emulator.zip');
|
yield io.rmRF('emulator.zip');
|
||||||
}
|
}
|
||||||
console.log('Installing system images.');
|
console.log('Installing system images.');
|
||||||
yield exec.exec(`sh -c \\"sdkmanager --install 'system-images;android-${apiLevel};${target};${arch}' --channel=${channelId} > /dev/null"`);
|
yield exec.exec(`sh -c \\"sdkmanager --install 'system-images;android-${systemImageApiLevel};${target};${arch}' --channel=${channelId} > /dev/null"`);
|
||||||
if (ndkVersion) {
|
if (ndkVersion) {
|
||||||
console.log(`Installing NDK ${ndkVersion}.`);
|
console.log(`Installing NDK ${ndkVersion}.`);
|
||||||
yield exec.exec(`sh -c \\"sdkmanager --install 'ndk;${ndkVersion}' --channel=${channelId} > /dev/null"`);
|
yield exec.exec(`sh -c \\"sdkmanager --install 'ndk;${ndkVersion}' --channel=${channelId} > /dev/null"`);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import * as fs from 'fs';
|
|||||||
* Creates and launches a new AVD instance with the specified configurations.
|
* Creates and launches a new AVD instance with the specified configurations.
|
||||||
*/
|
*/
|
||||||
export async function launchEmulator(
|
export async function launchEmulator(
|
||||||
apiLevel: string,
|
systemImageApiLevel: string,
|
||||||
target: string,
|
target: string,
|
||||||
arch: string,
|
arch: string,
|
||||||
profile: string,
|
profile: string,
|
||||||
@@ -33,7 +33,7 @@ export async function launchEmulator(
|
|||||||
const sdcardPathOrSizeOption = sdcardPathOrSize.trim() !== '' ? `--sdcard '${sdcardPathOrSize}'` : '';
|
const sdcardPathOrSizeOption = sdcardPathOrSize.trim() !== '' ? `--sdcard '${sdcardPathOrSize}'` : '';
|
||||||
console.log(`Creating AVD.`);
|
console.log(`Creating AVD.`);
|
||||||
await exec.exec(
|
await exec.exec(
|
||||||
`sh -c \\"echo no | avdmanager create avd --force -n "${avdName}" --abi '${target}/${arch}' --package 'system-images;android-${apiLevel};${target};${arch}' ${profileOption} ${sdcardPathOrSizeOption}"`
|
`sh -c \\"echo no | avdmanager create avd --force -n "${avdName}" --abi '${target}/${arch}' --package 'system-images;android-${systemImageApiLevel};${target};${arch}' ${profileOption} ${sdcardPathOrSizeOption}"`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-12
@@ -1,20 +1,22 @@
|
|||||||
export const MIN_API_LEVEL = 15;
|
export const MIN_API_LEVEL = 15;
|
||||||
export const VALID_TARGETS: Array<string> = ['default', 'google_apis', 'aosp_atd', 'google_atd', 'google_apis_playstore', 'android-wear', 'android-wear-cn', 'android-tv', 'google-tv'];
|
export const VALID_TARGETS: Array<string> = [
|
||||||
|
'default',
|
||||||
|
'google_apis',
|
||||||
|
'aosp_atd',
|
||||||
|
'google_atd',
|
||||||
|
'google_apis_playstore',
|
||||||
|
'android-wear',
|
||||||
|
'android-wear-cn',
|
||||||
|
'android-tv',
|
||||||
|
'google-tv',
|
||||||
|
'android-automotive',
|
||||||
|
'android-automotive-playstore',
|
||||||
|
'android-desktop',
|
||||||
|
];
|
||||||
export const VALID_ARCHS: Array<string> = ['x86', 'x86_64', 'arm64-v8a'];
|
export const VALID_ARCHS: Array<string> = ['x86', 'x86_64', 'arm64-v8a'];
|
||||||
export const VALID_CHANNELS: Array<string> = ['stable', 'beta', 'dev', 'canary'];
|
export const VALID_CHANNELS: Array<string> = ['stable', 'beta', 'dev', 'canary'];
|
||||||
export const MIN_PORT = 5554;
|
export const MIN_PORT = 5554;
|
||||||
export const MAX_PORT = 5584;
|
export const MAX_PORT = 5584;
|
||||||
export const PREVIEW_API_LEVELS: Array<string> = ['Tiramisu', 'UpsideDownCake', 'VanillaIceCream', 'Baklava'];
|
|
||||||
|
|
||||||
export function checkApiLevel(apiLevel: string): void {
|
|
||||||
if (PREVIEW_API_LEVELS.some((previewLevel) => apiLevel.startsWith(previewLevel))) return;
|
|
||||||
if (isNaN(Number(apiLevel)) || !Number.isInteger(Number(apiLevel))) {
|
|
||||||
throw new Error(`Unexpected API level: '${apiLevel}'.`);
|
|
||||||
}
|
|
||||||
if (Number(apiLevel) < MIN_API_LEVEL) {
|
|
||||||
throw new Error(`Minimum API level supported is ${MIN_API_LEVEL}.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function checkTarget(target: string): void {
|
export function checkTarget(target: string): void {
|
||||||
if (!VALID_TARGETS.includes(target)) {
|
if (!VALID_TARGETS.includes(target)) {
|
||||||
|
|||||||
+8
-4
@@ -1,7 +1,6 @@
|
|||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import { installAndroidSdk } from './sdk-installer';
|
import { installAndroidSdk } from './sdk-installer';
|
||||||
import {
|
import {
|
||||||
checkApiLevel,
|
|
||||||
checkTarget,
|
checkTarget,
|
||||||
checkArch,
|
checkArch,
|
||||||
checkDisableAnimations,
|
checkDisableAnimations,
|
||||||
@@ -44,9 +43,14 @@ async function run() {
|
|||||||
|
|
||||||
// API level of the platform and system image
|
// API level of the platform and system image
|
||||||
const apiLevel = core.getInput('api-level', { required: true });
|
const apiLevel = core.getInput('api-level', { required: true });
|
||||||
checkApiLevel(apiLevel);
|
|
||||||
console.log(`API level: ${apiLevel}`);
|
console.log(`API level: ${apiLevel}`);
|
||||||
|
|
||||||
|
let systemImageApiLevel = core.getInput('system-image-api-level');
|
||||||
|
if (!systemImageApiLevel) {
|
||||||
|
systemImageApiLevel = apiLevel;
|
||||||
|
}
|
||||||
|
console.log(`System image API level: ${systemImageApiLevel}`);
|
||||||
|
|
||||||
// target of the system image
|
// target of the system image
|
||||||
const targetInput = core.getInput('target');
|
const targetInput = core.getInput('target');
|
||||||
const target = targetInput == 'playstore' ? 'google_apis_playstore' : targetInput;
|
const target = targetInput == 'playstore' ? 'google_apis_playstore' : targetInput;
|
||||||
@@ -185,7 +189,7 @@ async function run() {
|
|||||||
console.log(`::endgroup::`);
|
console.log(`::endgroup::`);
|
||||||
|
|
||||||
// install SDK
|
// install SDK
|
||||||
await installAndroidSdk(apiLevel, target, arch, channelId, emulatorBuild, ndkVersion, cmakeVersion);
|
await installAndroidSdk(apiLevel, systemImageApiLevel, target, arch, channelId, emulatorBuild, ndkVersion, cmakeVersion);
|
||||||
|
|
||||||
// execute pre emulator launch script if set
|
// execute pre emulator launch script if set
|
||||||
if (preEmulatorLaunchScripts !== undefined) {
|
if (preEmulatorLaunchScripts !== undefined) {
|
||||||
@@ -206,7 +210,7 @@ async function run() {
|
|||||||
|
|
||||||
// launch an emulator
|
// launch an emulator
|
||||||
await launchEmulator(
|
await launchEmulator(
|
||||||
apiLevel,
|
systemImageApiLevel,
|
||||||
target,
|
target,
|
||||||
arch,
|
arch,
|
||||||
profile,
|
profile,
|
||||||
|
|||||||
+11
-2
@@ -13,7 +13,16 @@ const CMDLINE_TOOLS_URL_LINUX = 'https://dl.google.com/android/repository/comman
|
|||||||
* Installs & updates the Android SDK for the macOS platform, including SDK platform for the chosen API level, latest build tools, platform tools, Android Emulator,
|
* Installs & updates the Android SDK for the macOS platform, including SDK platform for the chosen API level, latest build tools, platform tools, Android Emulator,
|
||||||
* and the system image for the chosen API level, CPU arch, and target.
|
* and the system image for the chosen API level, CPU arch, and target.
|
||||||
*/
|
*/
|
||||||
export async function installAndroidSdk(apiLevel: string, target: string, arch: string, channelId: number, emulatorBuild?: string, ndkVersion?: string, cmakeVersion?: string): Promise<void> {
|
export async function installAndroidSdk(
|
||||||
|
apiLevel: string,
|
||||||
|
systemImageApiLevel: String,
|
||||||
|
target: string,
|
||||||
|
arch: string,
|
||||||
|
channelId: number,
|
||||||
|
emulatorBuild?: string,
|
||||||
|
ndkVersion?: string,
|
||||||
|
cmakeVersion?: string
|
||||||
|
): Promise<void> {
|
||||||
try {
|
try {
|
||||||
console.log(`::group::Install Android SDK`);
|
console.log(`::group::Install Android SDK`);
|
||||||
const isOnMac = process.platform === 'darwin';
|
const isOnMac = process.platform === 'darwin';
|
||||||
@@ -66,7 +75,7 @@ export async function installAndroidSdk(apiLevel: string, target: string, arch:
|
|||||||
await io.rmRF('emulator.zip');
|
await io.rmRF('emulator.zip');
|
||||||
}
|
}
|
||||||
console.log('Installing system images.');
|
console.log('Installing system images.');
|
||||||
await exec.exec(`sh -c \\"sdkmanager --install 'system-images;android-${apiLevel};${target};${arch}' --channel=${channelId} > /dev/null"`);
|
await exec.exec(`sh -c \\"sdkmanager --install 'system-images;android-${systemImageApiLevel};${target};${arch}' --channel=${channelId} > /dev/null"`);
|
||||||
|
|
||||||
if (ndkVersion) {
|
if (ndkVersion) {
|
||||||
console.log(`Installing NDK ${ndkVersion}.`);
|
console.log(`Installing NDK ${ndkVersion}.`);
|
||||||
|
|||||||
Reference in New Issue
Block a user