Support customizing emulator port (#383)

* Add port parameter

* Fix a typo in test description

* Fix avd not being started with correct port

* Fix wrong port being used to kill an emulator if there was an exception
This commit is contained in:
Kamil Bąk
2024-07-02 14:42:44 +02:00
committed by GitHub
parent ca77a1081f
commit 4b0628e9f8
10 changed files with 115 additions and 32 deletions
+17 -12
View File
@@ -17,6 +17,7 @@ export async function launchEmulator(
avdName: string,
forceAvdCreation: boolean,
emulatorBootTimeout: number,
port: number,
emulatorOptions: string,
disableAnimations: boolean,
disableSpellChecker: boolean,
@@ -65,7 +66,7 @@ export async function launchEmulator(
// start emulator
console.log('Starting emulator.');
await exec.exec(`sh -c \\"${process.env.ANDROID_HOME}/emulator/emulator -avd "${avdName}" ${emulatorOptions} &"`, [], {
await exec.exec(`sh -c \\"${process.env.ANDROID_HOME}/emulator/emulator -port ${port} -avd "${avdName}" ${emulatorOptions} &"`, [], {
listeners: {
stderr: (data: Buffer) => {
if (data.toString().includes('invalid command-line parameter')) {
@@ -76,20 +77,20 @@ export async function launchEmulator(
});
// wait for emulator to complete booting
await waitForDevice(emulatorBootTimeout);
await exec.exec(`adb shell input keyevent 82`);
await waitForDevice(port, emulatorBootTimeout);
await adb(port, `shell input keyevent 82`);
if (disableAnimations) {
console.log('Disabling animations.');
await exec.exec(`adb shell settings put global window_animation_scale 0.0`);
await exec.exec(`adb shell settings put global transition_animation_scale 0.0`);
await exec.exec(`adb shell settings put global animator_duration_scale 0.0`);
await adb(port, `shell settings put global window_animation_scale 0.0`);
await adb(port, `shell settings put global transition_animation_scale 0.0`);
await adb(port, `shell settings put global animator_duration_scale 0.0`);
}
if (disableSpellChecker) {
await exec.exec(`adb shell settings put secure spell_checker_enabled 0`);
await adb(port, `shell settings put secure spell_checker_enabled 0`);
}
if (enableHardwareKeyboard) {
await exec.exec(`adb shell settings put secure show_ime_with_hard_keyboard 0`);
await adb(port, `shell settings put secure show_ime_with_hard_keyboard 0`);
}
} finally {
console.log(`::endgroup::`);
@@ -99,10 +100,10 @@ export async function launchEmulator(
/**
* Kills the running emulator on the default port.
*/
export async function killEmulator(): Promise<void> {
export async function killEmulator(port: number): Promise<void> {
try {
console.log(`::group::Terminate Emulator`);
await exec.exec(`adb -s emulator-5554 emu kill`);
await adb(port, `emu kill`);
} catch (error) {
console.log(error instanceof Error ? error.message : error);
} finally {
@@ -110,10 +111,14 @@ export async function killEmulator(): Promise<void> {
}
}
async function adb(port: number, command: string): Promise<number> {
return await exec.exec(`adb -s emulator-${port} ${command}`);
}
/**
* Wait for emulator to boot.
*/
async function waitForDevice(emulatorBootTimeout: number): Promise<void> {
async function waitForDevice(port: number, emulatorBootTimeout: number): Promise<void> {
let booted = false;
let attempts = 0;
const retryInterval = 2; // retry every 2 seconds
@@ -121,7 +126,7 @@ async function waitForDevice(emulatorBootTimeout: number): Promise<void> {
while (!booted) {
try {
let result = '';
await exec.exec(`adb shell getprop sys.boot_completed`, [], {
await exec.exec(`adb -s emulator-${port} shell getprop sys.boot_completed`, [], {
listeners: {
stdout: (data: Buffer) => {
result += data.toString();
+11
View File
@@ -2,6 +2,8 @@ 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_ARCHS: Array<string> = ['x86', 'x86_64', 'arm64-v8a'];
export const VALID_CHANNELS: Array<string> = ['stable', 'beta', 'dev', 'canary'];
export const MIN_PORT = 5554;
export const MAX_PORT = 5584;
export const PREVIEW_API_LEVELS: Array<string> = ['Tiramisu', 'UpsideDownCake', 'VanillaIceCream'];
export function checkApiLevel(apiLevel: string): void {
@@ -38,6 +40,15 @@ export function checkForceAvdCreation(forceAvdCreation: string): void {
}
}
export function checkPort(port: number): void {
if (port < MIN_PORT || port > MAX_PORT) {
throw new Error(`Emulator port is outside of the supported port range [${MIN_PORT}, ${MAX_PORT}], was ${port}`);
}
if (port % 2 == 1) {
throw new Error(`Emulator port has to be even, was ${port}`);
}
}
export function checkDisableAnimations(disableAnimations: string): void {
if (!isValidBoolean(disableAnimations)) {
throw new Error(`Input for input.disable-animations should be either 'true' or 'false'.`);
+14 -3
View File
@@ -12,6 +12,8 @@ import {
checkChannel,
checkEnableHardwareKeyboard,
checkDiskSize,
checkPort,
MIN_PORT,
} from './input-validator';
import { launchEmulator, killEmulator } from './emulator-manager';
import * as exec from '@actions/exec';
@@ -20,6 +22,7 @@ import { getChannelId } from './channel-id-mapper';
import { accessSync, constants } from 'fs';
async function run() {
let port: number = MIN_PORT;
try {
console.log(`::group::Configure emulator`);
let linuxSupportKVM = false;
@@ -93,6 +96,11 @@ async function run() {
const emulatorBootTimeout = parseInt(core.getInput('emulator-boot-timeout'), 10);
console.log(`Emulator boot timeout: ${emulatorBootTimeout}`);
// Emulator port to use
port = parseInt(core.getInput('emulator-port'), 10);
checkPort(port);
console.log(`emulator port: ${port}`);
// emulator options
const emulatorOptions = core.getInput('emulator-options').trim();
console.log(`emulator options: ${emulatorOptions}`);
@@ -210,6 +218,7 @@ async function run() {
avdName,
forceAvdCreation,
emulatorBootTimeout,
port,
emulatorOptions,
disableAnimations,
disableSpellchecker,
@@ -226,17 +235,19 @@ async function run() {
for (const script of scripts) {
// use array form to avoid various quote escaping problems
// caused by exec(`sh -c "${script}"`)
await exec.exec('sh', ['-c', script]);
await exec.exec('sh', ['-c', script], {
env: { ...process.env, EMULATOR_PORT: `${port}`, ANDROID_SERIAL: `emulator-${port}` },
});
}
} catch (error) {
core.setFailed(error instanceof Error ? error.message : (error as string));
}
// finally kill the emulator
await killEmulator();
await killEmulator(port);
} catch (error) {
// kill the emulator so the action can exit
await killEmulator();
await killEmulator(port);
core.setFailed(error instanceof Error ? error.message : (error as string));
}
}