diff --git a/emulator-run-cmd/src/sdk.ts b/emulator-run-cmd/src/sdk.ts index ed4f1d9c..f9e40810 100644 --- a/emulator-run-cmd/src/sdk.ts +++ b/emulator-run-cmd/src/sdk.ts @@ -76,16 +76,7 @@ export abstract class BaseAndroidSdk implements AndroidSDK { } async acceptLicense(): Promise { - await execWithResult(`mkdir -p ${this.androidHome()}/licenses`) - - await writeLicenseFile(`${this.androidHome()}/licenses/android-sdk-license`, "8933bad161af4178b1185d1a37fbf41ea5269c55\n" + - "d56f5187479451eabf01fb78af6dfcb131a6481e\n" + - "24333f8a63b6825ea9c5514f83c2829b004d1fee") - await writeLicenseFile(`${this.androidHome()}/licenses/android-sdk-preview-license`, "84831b9409646a918e30573bab4c9c91346d8abd\n") - await writeLicenseFile(`${this.androidHome()}/licenses/intel-android-extra-license`, "d975f751698a77b662f1254ddbeed3901e976f5a\n") - await writeLicenseFile(`${this.androidHome()}/licenses/mips-android-sysimage-license`, "e9acab5b5fbb560a72cfaecce8946896ff6aab9d\n") - await writeLicenseFile(`${this.androidHome()}/licenses/google-gdk-license`, "33b6a2b64607f11b759f320ef9dff4ae5c47d97a\n") - await writeLicenseFile(`${this.androidHome()}/licenses/android-googletv-license`, "601085b94cd77f0b54ff86406957099ebe79c4d6\n") + await execWithResult(`bash -c \\\"yes | ${this.androidHome()}/tools/bin/sdkmanager --licenses"`); } async installEmulatorPackage(api: string, tag: string, abi: string, verbose: boolean): Promise { @@ -173,7 +164,3 @@ export class SdkFactory { } } } - -async function writeLicenseFile(file: string, content: string) { - await writeFileAsync(file, content) -} diff --git a/emulator-start/src/sdk.ts b/emulator-start/src/sdk.ts index ed4f1d9c..6c9749f4 100644 --- a/emulator-start/src/sdk.ts +++ b/emulator-start/src/sdk.ts @@ -1,179 +1,70 @@ -import * as core from "@actions/core"; import execWithResult from "./exec-with-result"; -import * as fs from "fs"; -import {writeFile} from "fs"; -import * as util from "util"; -import {exec} from "@actions/exec/lib/exec"; -import {Emulator} from "./emulator"; - -const ANDROID_TMP_PATH = "/tmp/android-sdk.zip" - -let writeFileAsync = util.promisify(writeFile) - -export interface AndroidSDK { - defaultSdkUrl: string - - install(url: string): Promise; - - androidHome(): string - - acceptLicense(): Promise - - installEmulatorPackage(api: string, tag: string, abi: string, verbose: boolean): Promise - - installPlatform(api: string, verbose: boolean): Promise - - createEmulator(name: string, api: string, tag: string, abi: string): Promise - - listEmulators(): Promise - - listRunningEmulators(): Promise> - - startAdbServer(): Promise - - verifyHardwareAcceleration(): Promise -} - -export abstract class BaseAndroidSdk implements AndroidSDK { - abstract defaultSdkUrl: string - - portCounter: number = 5554 - - async install(url: string): Promise { - const ANDROID_HOME = this.androidHome() - - let sdkUrl: string = url - if (sdkUrl == null || sdkUrl == "") { - sdkUrl = this.defaultSdkUrl - } - - if (fs.existsSync(`${process.env.HOME}/.android`)) { - await execWithResult(`mv ${process.env.HOME}/.android ${process.env.HOME}/.android.backup`) - } - - await execWithResult(`curl -L ${sdkUrl} -o ${ANDROID_TMP_PATH} -s`) - await execWithResult(`unzip -q ${ANDROID_TMP_PATH} -d ${ANDROID_HOME}`) - await execWithResult(`rm ${ANDROID_TMP_PATH}`) - await execWithResult(`mkdir -p ${ANDROID_HOME}/sdk_home`) - - core.exportVariable('ANDROID_HOME', `${ANDROID_HOME}`); - core.exportVariable('ANDROID_SDK_ROOT', `${ANDROID_HOME}`); - core.exportVariable('ANDROID_SDK_HOME', `${ANDROID_HOME}/sdk_home`); - - const PATH = process.env.PATH!! - let extraPaths = `${ANDROID_HOME}/bin:${ANDROID_HOME}/tools:${PATH}/tools/bin:${PATH}/platform-tools/bin` - - let PATH_WITHOUT_ANDROID = PATH.split(':').filter(entry => { - !entry.includes("Android") - }) - - core.exportVariable('PATH', `${PATH_WITHOUT_ANDROID}:${extraPaths}`) - return true - } - - androidHome(): string { - return `${process.env.HOME}/android-sdk` +import {AndroidSDK} from "./sdk"; + +export class Emulator { + private sdk: AndroidSDK; + private readonly name: string; + private api: string; + private abi: string; + private tag: string; + private adbPort: number; + private telnetPort: number; + + public constructor(sdk: AndroidSDK, + name: string, + api: string, + abi: string, + tag: string, + adbPort: number, + telnetPort: number) { + this.sdk = sdk + this.name = name; + this.api = api; + this.abi = abi; + this.tag = tag; + this.adbPort = adbPort; + this.telnetPort = telnetPort; } - async acceptLicense(): Promise { - await execWithResult(`mkdir -p ${this.androidHome()}/licenses`) - - await writeLicenseFile(`${this.androidHome()}/licenses/android-sdk-license`, "8933bad161af4178b1185d1a37fbf41ea5269c55\n" + - "d56f5187479451eabf01fb78af6dfcb131a6481e\n" + - "24333f8a63b6825ea9c5514f83c2829b004d1fee") - await writeLicenseFile(`${this.androidHome()}/licenses/android-sdk-preview-license`, "84831b9409646a918e30573bab4c9c91346d8abd\n") - await writeLicenseFile(`${this.androidHome()}/licenses/intel-android-extra-license`, "d975f751698a77b662f1254ddbeed3901e976f5a\n") - await writeLicenseFile(`${this.androidHome()}/licenses/mips-android-sysimage-license`, "e9acab5b5fbb560a72cfaecce8946896ff6aab9d\n") - await writeLicenseFile(`${this.androidHome()}/licenses/google-gdk-license`, "33b6a2b64607f11b759f320ef9dff4ae5c47d97a\n") - await writeLicenseFile(`${this.androidHome()}/licenses/android-googletv-license`, "601085b94cd77f0b54ff86406957099ebe79c4d6\n") - } - - async installEmulatorPackage(api: string, tag: string, abi: string, verbose: boolean): Promise { - let args = "" - if (!verbose) { - args += " > /dev/null" - } - - await execWithResult(`bash -c \\\"${this.androidHome()}/tools/bin/sdkmanager emulator tools platform-tools 'system-images;android-${api};${tag};${abi}'${args}"`); - } - - async installPlatform(api: string, verbose: boolean): Promise { - let args = "" - if (!verbose) { - args += " > /dev/null" - } - - await execWithResult(`bash -c \\\"${this.androidHome()}/tools/bin/sdkmanager 'platforms;android-${api}'${args}"`) - } - - async createEmulator(name: string, api: string, tag: string, abi: string): Promise { - await execWithResult(`bash -c \\\"echo -n no | ${this.androidHome()}/tools/bin/avdmanager create avd -n ${name} --package \\\"system-images;android-${api};${tag};${abi}\\\" --tag ${tag}\"`) - return new Emulator(this, name, api, abi, tag, this.portCounter++, this.portCounter++) - } - - async verifyHardwareAcceleration(): Promise { - try { - let exitCode = await exec(`${this.androidHome()}/tools/emulator -accel-check`); - return exitCode == 0 - } catch (e) { - return false - } + async start(): Promise { + await execWithResult(`bash -c \\\"${this.sdk.emulatorCmd()} @${this.name} -no-snapshot-save &\"`) + let booted = await this.waitForBoot(); + console.log(`booted=${booted}`) + return } - async listEmulators(): Promise { - await execWithResult(`${this.androidHome()}/tools/emulator -list-avds`) + async stop(): Promise { + await execWithResult(`bash -c \\\"${this.sdk.androidHome()}/platform-tools/adb -s emulator-${this.adbPort} emu kill\"`) + console.log("emu kill finished") + return } - async listRunningEmulators(): Promise> { - let output = await execWithResult(`${this.androidHome()}/platform-tools/adb devices`) - return await this.parseDevicesOutput(output); - } - - async parseDevicesOutput(output: string): Promise> { - let result = new Array() - - let lines = output.split(/\r?\n/); - for (let line in lines) { - if (line.startsWith("emulator")) { - let split = line.split(" "); - let serial = split[0]; - let port = serial.split("-")[1] - let nameOutput = await execWithResult(`${this.androidHome()}/platform-tools/adb adb -s ${serial} emu avd name`) - let nameLines = nameOutput.split(/\r?\n/); - let name = nameLines[0]; - - result.fill(new Emulator(this, name, "", "", "", parseInt(port), parseInt(port) + 1)) + async waitForBoot(): Promise { + for (let countdown = 120; countdown > 0; countdown--) { + if (countdown == 0) { + console.error("Timeout waiting for the emulator") + return false + } + try { + let output = await execWithResult(`${this.sdk.androidHome()}/platform-tools/adb shell getprop sys.boot_completed`) + if (output.trim() == '1') { + countdown = 0 + console.log("Emulator booted") + return true + } + } catch (e) { + console.error(e.message) } - } - return result; - } - - async startAdbServer(): Promise { - await execWithResult(`${this.androidHome()}/platform-tools/adb start-server`) - } -} - -class LinuxAndroidSdk extends BaseAndroidSdk { - defaultSdkUrl = "https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip" -} - -class MacOSAndroidSdk extends BaseAndroidSdk { - defaultSdkUrl = "https://dl.google.com/android/repository/sdk-tools-darwin-4333796.zip" -} -export class SdkFactory { - getAndroidSdk(): AndroidSDK { - switch (process.platform) { - case "linux": - return new LinuxAndroidSdk() - case "darwin": - return new MacOSAndroidSdk() - default: - throw new Error("Unsupported OS") + console.log("Sleeping for 1s") + await sleep(1000) + countdown-- } + console.log("Timeout waiting for emulator to boot. Exiting") + return false } } -async function writeLicenseFile(file: string, content: string) { - await writeFileAsync(file, content) +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); } diff --git a/emulator-stop/src/sdk.ts b/emulator-stop/src/sdk.ts index ed4f1d9c..6c9749f4 100644 --- a/emulator-stop/src/sdk.ts +++ b/emulator-stop/src/sdk.ts @@ -1,179 +1,70 @@ -import * as core from "@actions/core"; import execWithResult from "./exec-with-result"; -import * as fs from "fs"; -import {writeFile} from "fs"; -import * as util from "util"; -import {exec} from "@actions/exec/lib/exec"; -import {Emulator} from "./emulator"; - -const ANDROID_TMP_PATH = "/tmp/android-sdk.zip" - -let writeFileAsync = util.promisify(writeFile) - -export interface AndroidSDK { - defaultSdkUrl: string - - install(url: string): Promise; - - androidHome(): string - - acceptLicense(): Promise - - installEmulatorPackage(api: string, tag: string, abi: string, verbose: boolean): Promise - - installPlatform(api: string, verbose: boolean): Promise - - createEmulator(name: string, api: string, tag: string, abi: string): Promise - - listEmulators(): Promise - - listRunningEmulators(): Promise> - - startAdbServer(): Promise - - verifyHardwareAcceleration(): Promise -} - -export abstract class BaseAndroidSdk implements AndroidSDK { - abstract defaultSdkUrl: string - - portCounter: number = 5554 - - async install(url: string): Promise { - const ANDROID_HOME = this.androidHome() - - let sdkUrl: string = url - if (sdkUrl == null || sdkUrl == "") { - sdkUrl = this.defaultSdkUrl - } - - if (fs.existsSync(`${process.env.HOME}/.android`)) { - await execWithResult(`mv ${process.env.HOME}/.android ${process.env.HOME}/.android.backup`) - } - - await execWithResult(`curl -L ${sdkUrl} -o ${ANDROID_TMP_PATH} -s`) - await execWithResult(`unzip -q ${ANDROID_TMP_PATH} -d ${ANDROID_HOME}`) - await execWithResult(`rm ${ANDROID_TMP_PATH}`) - await execWithResult(`mkdir -p ${ANDROID_HOME}/sdk_home`) - - core.exportVariable('ANDROID_HOME', `${ANDROID_HOME}`); - core.exportVariable('ANDROID_SDK_ROOT', `${ANDROID_HOME}`); - core.exportVariable('ANDROID_SDK_HOME', `${ANDROID_HOME}/sdk_home`); - - const PATH = process.env.PATH!! - let extraPaths = `${ANDROID_HOME}/bin:${ANDROID_HOME}/tools:${PATH}/tools/bin:${PATH}/platform-tools/bin` - - let PATH_WITHOUT_ANDROID = PATH.split(':').filter(entry => { - !entry.includes("Android") - }) - - core.exportVariable('PATH', `${PATH_WITHOUT_ANDROID}:${extraPaths}`) - return true - } - - androidHome(): string { - return `${process.env.HOME}/android-sdk` +import {AndroidSDK} from "./sdk"; + +export class Emulator { + private sdk: AndroidSDK; + private readonly name: string; + private api: string; + private abi: string; + private tag: string; + private adbPort: number; + private telnetPort: number; + + public constructor(sdk: AndroidSDK, + name: string, + api: string, + abi: string, + tag: string, + adbPort: number, + telnetPort: number) { + this.sdk = sdk + this.name = name; + this.api = api; + this.abi = abi; + this.tag = tag; + this.adbPort = adbPort; + this.telnetPort = telnetPort; } - async acceptLicense(): Promise { - await execWithResult(`mkdir -p ${this.androidHome()}/licenses`) - - await writeLicenseFile(`${this.androidHome()}/licenses/android-sdk-license`, "8933bad161af4178b1185d1a37fbf41ea5269c55\n" + - "d56f5187479451eabf01fb78af6dfcb131a6481e\n" + - "24333f8a63b6825ea9c5514f83c2829b004d1fee") - await writeLicenseFile(`${this.androidHome()}/licenses/android-sdk-preview-license`, "84831b9409646a918e30573bab4c9c91346d8abd\n") - await writeLicenseFile(`${this.androidHome()}/licenses/intel-android-extra-license`, "d975f751698a77b662f1254ddbeed3901e976f5a\n") - await writeLicenseFile(`${this.androidHome()}/licenses/mips-android-sysimage-license`, "e9acab5b5fbb560a72cfaecce8946896ff6aab9d\n") - await writeLicenseFile(`${this.androidHome()}/licenses/google-gdk-license`, "33b6a2b64607f11b759f320ef9dff4ae5c47d97a\n") - await writeLicenseFile(`${this.androidHome()}/licenses/android-googletv-license`, "601085b94cd77f0b54ff86406957099ebe79c4d6\n") - } - - async installEmulatorPackage(api: string, tag: string, abi: string, verbose: boolean): Promise { - let args = "" - if (!verbose) { - args += " > /dev/null" - } - - await execWithResult(`bash -c \\\"${this.androidHome()}/tools/bin/sdkmanager emulator tools platform-tools 'system-images;android-${api};${tag};${abi}'${args}"`); - } - - async installPlatform(api: string, verbose: boolean): Promise { - let args = "" - if (!verbose) { - args += " > /dev/null" - } - - await execWithResult(`bash -c \\\"${this.androidHome()}/tools/bin/sdkmanager 'platforms;android-${api}'${args}"`) - } - - async createEmulator(name: string, api: string, tag: string, abi: string): Promise { - await execWithResult(`bash -c \\\"echo -n no | ${this.androidHome()}/tools/bin/avdmanager create avd -n ${name} --package \\\"system-images;android-${api};${tag};${abi}\\\" --tag ${tag}\"`) - return new Emulator(this, name, api, abi, tag, this.portCounter++, this.portCounter++) - } - - async verifyHardwareAcceleration(): Promise { - try { - let exitCode = await exec(`${this.androidHome()}/tools/emulator -accel-check`); - return exitCode == 0 - } catch (e) { - return false - } + async start(): Promise { + await execWithResult(`bash -c \\\"${this.sdk.emulatorCmd()} @${this.name} -no-snapshot-save &\"`) + let booted = await this.waitForBoot(); + console.log(`booted=${booted}`) + return } - async listEmulators(): Promise { - await execWithResult(`${this.androidHome()}/tools/emulator -list-avds`) + async stop(): Promise { + await execWithResult(`bash -c \\\"${this.sdk.androidHome()}/platform-tools/adb -s emulator-${this.adbPort} emu kill\"`) + console.log("emu kill finished") + return } - async listRunningEmulators(): Promise> { - let output = await execWithResult(`${this.androidHome()}/platform-tools/adb devices`) - return await this.parseDevicesOutput(output); - } - - async parseDevicesOutput(output: string): Promise> { - let result = new Array() - - let lines = output.split(/\r?\n/); - for (let line in lines) { - if (line.startsWith("emulator")) { - let split = line.split(" "); - let serial = split[0]; - let port = serial.split("-")[1] - let nameOutput = await execWithResult(`${this.androidHome()}/platform-tools/adb adb -s ${serial} emu avd name`) - let nameLines = nameOutput.split(/\r?\n/); - let name = nameLines[0]; - - result.fill(new Emulator(this, name, "", "", "", parseInt(port), parseInt(port) + 1)) + async waitForBoot(): Promise { + for (let countdown = 120; countdown > 0; countdown--) { + if (countdown == 0) { + console.error("Timeout waiting for the emulator") + return false + } + try { + let output = await execWithResult(`${this.sdk.androidHome()}/platform-tools/adb shell getprop sys.boot_completed`) + if (output.trim() == '1') { + countdown = 0 + console.log("Emulator booted") + return true + } + } catch (e) { + console.error(e.message) } - } - return result; - } - - async startAdbServer(): Promise { - await execWithResult(`${this.androidHome()}/platform-tools/adb start-server`) - } -} - -class LinuxAndroidSdk extends BaseAndroidSdk { - defaultSdkUrl = "https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip" -} - -class MacOSAndroidSdk extends BaseAndroidSdk { - defaultSdkUrl = "https://dl.google.com/android/repository/sdk-tools-darwin-4333796.zip" -} -export class SdkFactory { - getAndroidSdk(): AndroidSDK { - switch (process.platform) { - case "linux": - return new LinuxAndroidSdk() - case "darwin": - return new MacOSAndroidSdk() - default: - throw new Error("Unsupported OS") + console.log("Sleeping for 1s") + await sleep(1000) + countdown-- } + console.log("Timeout waiting for emulator to boot. Exiting") + return false } } -async function writeLicenseFile(file: string, content: string) { - await writeFileAsync(file, content) +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); } diff --git a/install-sdk/src/sdk.ts b/install-sdk/src/sdk.ts index ed4f1d9c..6c9749f4 100644 --- a/install-sdk/src/sdk.ts +++ b/install-sdk/src/sdk.ts @@ -1,179 +1,70 @@ -import * as core from "@actions/core"; import execWithResult from "./exec-with-result"; -import * as fs from "fs"; -import {writeFile} from "fs"; -import * as util from "util"; -import {exec} from "@actions/exec/lib/exec"; -import {Emulator} from "./emulator"; - -const ANDROID_TMP_PATH = "/tmp/android-sdk.zip" - -let writeFileAsync = util.promisify(writeFile) - -export interface AndroidSDK { - defaultSdkUrl: string - - install(url: string): Promise; - - androidHome(): string - - acceptLicense(): Promise - - installEmulatorPackage(api: string, tag: string, abi: string, verbose: boolean): Promise - - installPlatform(api: string, verbose: boolean): Promise - - createEmulator(name: string, api: string, tag: string, abi: string): Promise - - listEmulators(): Promise - - listRunningEmulators(): Promise> - - startAdbServer(): Promise - - verifyHardwareAcceleration(): Promise -} - -export abstract class BaseAndroidSdk implements AndroidSDK { - abstract defaultSdkUrl: string - - portCounter: number = 5554 - - async install(url: string): Promise { - const ANDROID_HOME = this.androidHome() - - let sdkUrl: string = url - if (sdkUrl == null || sdkUrl == "") { - sdkUrl = this.defaultSdkUrl - } - - if (fs.existsSync(`${process.env.HOME}/.android`)) { - await execWithResult(`mv ${process.env.HOME}/.android ${process.env.HOME}/.android.backup`) - } - - await execWithResult(`curl -L ${sdkUrl} -o ${ANDROID_TMP_PATH} -s`) - await execWithResult(`unzip -q ${ANDROID_TMP_PATH} -d ${ANDROID_HOME}`) - await execWithResult(`rm ${ANDROID_TMP_PATH}`) - await execWithResult(`mkdir -p ${ANDROID_HOME}/sdk_home`) - - core.exportVariable('ANDROID_HOME', `${ANDROID_HOME}`); - core.exportVariable('ANDROID_SDK_ROOT', `${ANDROID_HOME}`); - core.exportVariable('ANDROID_SDK_HOME', `${ANDROID_HOME}/sdk_home`); - - const PATH = process.env.PATH!! - let extraPaths = `${ANDROID_HOME}/bin:${ANDROID_HOME}/tools:${PATH}/tools/bin:${PATH}/platform-tools/bin` - - let PATH_WITHOUT_ANDROID = PATH.split(':').filter(entry => { - !entry.includes("Android") - }) - - core.exportVariable('PATH', `${PATH_WITHOUT_ANDROID}:${extraPaths}`) - return true - } - - androidHome(): string { - return `${process.env.HOME}/android-sdk` +import {AndroidSDK} from "./sdk"; + +export class Emulator { + private sdk: AndroidSDK; + private readonly name: string; + private api: string; + private abi: string; + private tag: string; + private adbPort: number; + private telnetPort: number; + + public constructor(sdk: AndroidSDK, + name: string, + api: string, + abi: string, + tag: string, + adbPort: number, + telnetPort: number) { + this.sdk = sdk + this.name = name; + this.api = api; + this.abi = abi; + this.tag = tag; + this.adbPort = adbPort; + this.telnetPort = telnetPort; } - async acceptLicense(): Promise { - await execWithResult(`mkdir -p ${this.androidHome()}/licenses`) - - await writeLicenseFile(`${this.androidHome()}/licenses/android-sdk-license`, "8933bad161af4178b1185d1a37fbf41ea5269c55\n" + - "d56f5187479451eabf01fb78af6dfcb131a6481e\n" + - "24333f8a63b6825ea9c5514f83c2829b004d1fee") - await writeLicenseFile(`${this.androidHome()}/licenses/android-sdk-preview-license`, "84831b9409646a918e30573bab4c9c91346d8abd\n") - await writeLicenseFile(`${this.androidHome()}/licenses/intel-android-extra-license`, "d975f751698a77b662f1254ddbeed3901e976f5a\n") - await writeLicenseFile(`${this.androidHome()}/licenses/mips-android-sysimage-license`, "e9acab5b5fbb560a72cfaecce8946896ff6aab9d\n") - await writeLicenseFile(`${this.androidHome()}/licenses/google-gdk-license`, "33b6a2b64607f11b759f320ef9dff4ae5c47d97a\n") - await writeLicenseFile(`${this.androidHome()}/licenses/android-googletv-license`, "601085b94cd77f0b54ff86406957099ebe79c4d6\n") - } - - async installEmulatorPackage(api: string, tag: string, abi: string, verbose: boolean): Promise { - let args = "" - if (!verbose) { - args += " > /dev/null" - } - - await execWithResult(`bash -c \\\"${this.androidHome()}/tools/bin/sdkmanager emulator tools platform-tools 'system-images;android-${api};${tag};${abi}'${args}"`); - } - - async installPlatform(api: string, verbose: boolean): Promise { - let args = "" - if (!verbose) { - args += " > /dev/null" - } - - await execWithResult(`bash -c \\\"${this.androidHome()}/tools/bin/sdkmanager 'platforms;android-${api}'${args}"`) - } - - async createEmulator(name: string, api: string, tag: string, abi: string): Promise { - await execWithResult(`bash -c \\\"echo -n no | ${this.androidHome()}/tools/bin/avdmanager create avd -n ${name} --package \\\"system-images;android-${api};${tag};${abi}\\\" --tag ${tag}\"`) - return new Emulator(this, name, api, abi, tag, this.portCounter++, this.portCounter++) - } - - async verifyHardwareAcceleration(): Promise { - try { - let exitCode = await exec(`${this.androidHome()}/tools/emulator -accel-check`); - return exitCode == 0 - } catch (e) { - return false - } + async start(): Promise { + await execWithResult(`bash -c \\\"${this.sdk.emulatorCmd()} @${this.name} -no-snapshot-save &\"`) + let booted = await this.waitForBoot(); + console.log(`booted=${booted}`) + return } - async listEmulators(): Promise { - await execWithResult(`${this.androidHome()}/tools/emulator -list-avds`) + async stop(): Promise { + await execWithResult(`bash -c \\\"${this.sdk.androidHome()}/platform-tools/adb -s emulator-${this.adbPort} emu kill\"`) + console.log("emu kill finished") + return } - async listRunningEmulators(): Promise> { - let output = await execWithResult(`${this.androidHome()}/platform-tools/adb devices`) - return await this.parseDevicesOutput(output); - } - - async parseDevicesOutput(output: string): Promise> { - let result = new Array() - - let lines = output.split(/\r?\n/); - for (let line in lines) { - if (line.startsWith("emulator")) { - let split = line.split(" "); - let serial = split[0]; - let port = serial.split("-")[1] - let nameOutput = await execWithResult(`${this.androidHome()}/platform-tools/adb adb -s ${serial} emu avd name`) - let nameLines = nameOutput.split(/\r?\n/); - let name = nameLines[0]; - - result.fill(new Emulator(this, name, "", "", "", parseInt(port), parseInt(port) + 1)) + async waitForBoot(): Promise { + for (let countdown = 120; countdown > 0; countdown--) { + if (countdown == 0) { + console.error("Timeout waiting for the emulator") + return false + } + try { + let output = await execWithResult(`${this.sdk.androidHome()}/platform-tools/adb shell getprop sys.boot_completed`) + if (output.trim() == '1') { + countdown = 0 + console.log("Emulator booted") + return true + } + } catch (e) { + console.error(e.message) } - } - return result; - } - - async startAdbServer(): Promise { - await execWithResult(`${this.androidHome()}/platform-tools/adb start-server`) - } -} - -class LinuxAndroidSdk extends BaseAndroidSdk { - defaultSdkUrl = "https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip" -} - -class MacOSAndroidSdk extends BaseAndroidSdk { - defaultSdkUrl = "https://dl.google.com/android/repository/sdk-tools-darwin-4333796.zip" -} -export class SdkFactory { - getAndroidSdk(): AndroidSDK { - switch (process.platform) { - case "linux": - return new LinuxAndroidSdk() - case "darwin": - return new MacOSAndroidSdk() - default: - throw new Error("Unsupported OS") + console.log("Sleeping for 1s") + await sleep(1000) + countdown-- } + console.log("Timeout waiting for emulator to boot. Exiting") + return false } } -async function writeLicenseFile(file: string, content: string) { - await writeFileAsync(file, content) +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); }