From 2a310ff7283b07806a7edc2bcf1177b8e333e85c Mon Sep 17 00:00:00 2001 From: jcesarmobile Date: Wed, 25 Oct 2023 13:25:01 +0200 Subject: [PATCH] feat(android)!: Remove AVD creation on list (#349) BREAKING CHANGE: removal of AVD creation feature --- src/android/data/avds/Nexus_5X_API_24.json | 50 ---- src/android/data/avds/Pixel_2_API_26.json | 40 --- src/android/data/avds/Pixel_2_API_27.json | 40 --- src/android/data/avds/Pixel_2_API_28.json | 40 --- src/android/data/avds/Pixel_3_API_29.json | 40 --- src/android/data/avds/Pixel_3_API_30.json | 40 --- src/android/data/avds/Pixel_3_API_31.json | 40 --- src/android/data/avds/Pixel_3_API_32.json | 40 --- src/android/data/avds/Pixel_4_API_33.json | 40 --- src/android/data/avds/Pixel_API_25.json | 50 ---- src/android/list.ts | 1 - src/android/sdk-info.ts | 12 +- src/android/utils/avd.ts | 265 +---------------- src/android/utils/emulator.ts | 3 - src/android/utils/list.ts | 8 +- src/android/utils/run.ts | 14 +- src/android/utils/sdk/api.ts | 318 --------------------- src/errors.ts | 17 +- 18 files changed, 13 insertions(+), 1045 deletions(-) delete mode 100644 src/android/data/avds/Nexus_5X_API_24.json delete mode 100644 src/android/data/avds/Pixel_2_API_26.json delete mode 100644 src/android/data/avds/Pixel_2_API_27.json delete mode 100644 src/android/data/avds/Pixel_2_API_28.json delete mode 100644 src/android/data/avds/Pixel_3_API_29.json delete mode 100644 src/android/data/avds/Pixel_3_API_30.json delete mode 100644 src/android/data/avds/Pixel_3_API_31.json delete mode 100644 src/android/data/avds/Pixel_3_API_32.json delete mode 100644 src/android/data/avds/Pixel_4_API_33.json delete mode 100644 src/android/data/avds/Pixel_API_25.json diff --git a/src/android/data/avds/Nexus_5X_API_24.json b/src/android/data/avds/Nexus_5X_API_24.json deleted file mode 100644 index a507190..0000000 --- a/src/android/data/avds/Nexus_5X_API_24.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "id": "Nexus_5X_API_24", - "ini": { - "avd.ini.encoding": "UTF-8", - "target": "android-24" - }, - "configini": { - "AvdId": "Nexus_5X_API_24", - "PlayStore.enabled": "true", - "abi.type": "x86", - "avd.ini.displayname": "Nexus 5X API 24", - "avd.ini.encoding": "UTF-8", - "disk.dataPartition.size": "2G", - "fastboot.forceColdBoot": "no", - "hw.accelerometer": "yes", - "hw.arc": "false", - "hw.audioInput": "yes", - "hw.battery": "yes", - "hw.camera.back": "virtualscene", - "hw.camera.front": "emulated", - "hw.cpu.arch": "x86", - "hw.cpu.ncore": "4", - "hw.dPad": "no", - "hw.device.hash2": "MD5:bc5032b2a871da511332401af3ac6bb0", - "hw.device.manufacturer": "Google", - "hw.device.name": "Nexus 5X", - "hw.gps": "yes", - "hw.gpu.enabled": "yes", - "hw.gpu.mode": "auto", - "hw.initialOrientation": "Portrait", - "hw.keyboard": "yes", - "hw.lcd.density": "420", - "hw.lcd.height": "1920", - "hw.lcd.width": "1080", - "hw.mainKeys": "no", - "hw.ramSize": "1536", - "hw.sdCard": "yes", - "hw.sensors.orientation": "yes", - "hw.sensors.proximity": "yes", - "hw.trackBall": "no", - "runtime.network.latency": "none", - "runtime.network.speed": "full", - "sdcard.size": "100M", - "showDeviceFrame": "yes", - "skin.dynamic": "yes", - "skin.name": "nexus_5x", - "tag.display": "Google Play", - "vm.heapSize": "256" - } -} diff --git a/src/android/data/avds/Pixel_2_API_26.json b/src/android/data/avds/Pixel_2_API_26.json deleted file mode 100644 index 35bf8d7..0000000 --- a/src/android/data/avds/Pixel_2_API_26.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "id": "Pixel_2_API_26", - "ini": { - "avd.ini.encoding": "UTF-8", - "target": "android-26" - }, - "configini": { - "AvdId": "Pixel_2_API_28", - "abi.type": "x86", - "avd.ini.displayname": "Pixel 2 API 26", - "avd.ini.encoding": "UTF-8", - "hw.accelerometer": "yes", - "hw.audioInput": "yes", - "hw.battery": "yes", - "hw.camera.back": "virtualscene", - "hw.camera.front": "emulated", - "hw.cpu.arch": "x86", - "hw.cpu.ncore": "4", - "hw.device.hash2": "MD5:bc5032b2a871da511332401af3ac6bb0", - "hw.device.manufacturer": "Google", - "hw.device.name": "pixel_2", - "hw.gps": "yes", - "hw.gpu.enabled": "yes", - "hw.gpu.mode": "auto", - "hw.initialOrientation": "Portrait", - "hw.keyboard": "yes", - "hw.lcd.density": "420", - "hw.lcd.height": "1920", - "hw.lcd.width": "1080", - "hw.ramSize": "1536", - "hw.sdCard": "yes", - "hw.sensors.orientation": "yes", - "hw.sensors.proximity": "yes", - "sdcard.size": "100M", - "showDeviceFrame": "yes", - "skin.dynamic": "yes", - "skin.name": "pixel_2", - "tag.display": "Google APIs" - } -} diff --git a/src/android/data/avds/Pixel_2_API_27.json b/src/android/data/avds/Pixel_2_API_27.json deleted file mode 100644 index 1161259..0000000 --- a/src/android/data/avds/Pixel_2_API_27.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "id": "Pixel_2_API_27", - "ini": { - "avd.ini.encoding": "UTF-8", - "target": "android-27" - }, - "configini": { - "AvdId": "Pixel_2_API_28", - "abi.type": "x86", - "avd.ini.displayname": "Pixel 2 API 27", - "avd.ini.encoding": "UTF-8", - "hw.accelerometer": "yes", - "hw.audioInput": "yes", - "hw.battery": "yes", - "hw.camera.back": "virtualscene", - "hw.camera.front": "emulated", - "hw.cpu.arch": "x86", - "hw.cpu.ncore": "4", - "hw.device.hash2": "MD5:bc5032b2a871da511332401af3ac6bb0", - "hw.device.manufacturer": "Google", - "hw.device.name": "pixel_2", - "hw.gps": "yes", - "hw.gpu.enabled": "yes", - "hw.gpu.mode": "auto", - "hw.initialOrientation": "Portrait", - "hw.keyboard": "yes", - "hw.lcd.density": "420", - "hw.lcd.height": "1920", - "hw.lcd.width": "1080", - "hw.ramSize": "1536", - "hw.sdCard": "yes", - "hw.sensors.orientation": "yes", - "hw.sensors.proximity": "yes", - "sdcard.size": "100M", - "showDeviceFrame": "yes", - "skin.dynamic": "yes", - "skin.name": "pixel_2", - "tag.display": "Google APIs" - } -} diff --git a/src/android/data/avds/Pixel_2_API_28.json b/src/android/data/avds/Pixel_2_API_28.json deleted file mode 100644 index c93052e..0000000 --- a/src/android/data/avds/Pixel_2_API_28.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "id": "Pixel_2_API_28", - "ini": { - "avd.ini.encoding": "UTF-8", - "target": "android-28" - }, - "configini": { - "AvdId": "Pixel_2_API_28", - "abi.type": "x86", - "avd.ini.displayname": "Pixel 2 API 28", - "avd.ini.encoding": "UTF-8", - "hw.accelerometer": "yes", - "hw.audioInput": "yes", - "hw.battery": "yes", - "hw.camera.back": "virtualscene", - "hw.camera.front": "emulated", - "hw.cpu.arch": "x86", - "hw.cpu.ncore": "4", - "hw.device.hash2": "MD5:bc5032b2a871da511332401af3ac6bb0", - "hw.device.manufacturer": "Google", - "hw.device.name": "pixel_2", - "hw.gps": "yes", - "hw.gpu.enabled": "yes", - "hw.gpu.mode": "auto", - "hw.initialOrientation": "Portrait", - "hw.keyboard": "yes", - "hw.lcd.density": "420", - "hw.lcd.height": "1920", - "hw.lcd.width": "1080", - "hw.ramSize": "1536", - "hw.sdCard": "yes", - "hw.sensors.orientation": "yes", - "hw.sensors.proximity": "yes", - "sdcard.size": "100M", - "showDeviceFrame": "yes", - "skin.dynamic": "yes", - "skin.name": "pixel_2", - "tag.display": "Google APIs" - } -} diff --git a/src/android/data/avds/Pixel_3_API_29.json b/src/android/data/avds/Pixel_3_API_29.json deleted file mode 100644 index d2c6ca7..0000000 --- a/src/android/data/avds/Pixel_3_API_29.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "id": "Pixel_3_API_29", - "ini": { - "avd.ini.encoding": "UTF-8", - "target": "android-29" - }, - "configini": { - "AvdId": "Pixel_3_API_29", - "abi.type": "x86", - "avd.ini.displayname": "Pixel 3 API 29", - "avd.ini.encoding": "UTF-8", - "hw.accelerometer": "yes", - "hw.audioInput": "yes", - "hw.battery": "yes", - "hw.camera.back": "virtualscene", - "hw.camera.front": "emulated", - "hw.cpu.arch": "x86", - "hw.cpu.ncore": "4", - "hw.device.hash2": "MD5:8a60718609e0741c7c0cc225f49c5590", - "hw.device.manufacturer": "Google", - "hw.device.name": "pixel_3", - "hw.gps": "yes", - "hw.gpu.enabled": "yes", - "hw.gpu.mode": "auto", - "hw.initialOrientation": "Portrait", - "hw.keyboard": "yes", - "hw.lcd.density": "440", - "hw.lcd.height": "2160", - "hw.lcd.width": "1080", - "hw.ramSize": "1536", - "hw.sdCard": "yes", - "hw.sensors.orientation": "yes", - "hw.sensors.proximity": "yes", - "sdcard.size": "512M", - "showDeviceFrame": "yes", - "skin.dynamic": "yes", - "skin.name": "pixel_2", - "tag.display": "Google Play" - } -} diff --git a/src/android/data/avds/Pixel_3_API_30.json b/src/android/data/avds/Pixel_3_API_30.json deleted file mode 100644 index 075572a..0000000 --- a/src/android/data/avds/Pixel_3_API_30.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "id": "Pixel_3_API_30", - "ini": { - "avd.ini.encoding": "UTF-8", - "target": "android-30" - }, - "configini": { - "AvdId": "Pixel_3_API_30", - "abi.type": "x86", - "avd.ini.displayname": "Pixel 3 API 30", - "avd.ini.encoding": "UTF-8", - "hw.accelerometer": "yes", - "hw.audioInput": "yes", - "hw.battery": "yes", - "hw.camera.back": "virtualscene", - "hw.camera.front": "emulated", - "hw.cpu.arch": "x86", - "hw.cpu.ncore": "4", - "hw.device.hash2": "MD5:8a60718609e0741c7c0cc225f49c5590", - "hw.device.manufacturer": "Google", - "hw.device.name": "pixel_3", - "hw.gps": "yes", - "hw.gpu.enabled": "yes", - "hw.gpu.mode": "auto", - "hw.initialOrientation": "Portrait", - "hw.keyboard": "yes", - "hw.lcd.density": "440", - "hw.lcd.height": "2160", - "hw.lcd.width": "1080", - "hw.ramSize": "1536", - "hw.sdCard": "yes", - "hw.sensors.orientation": "yes", - "hw.sensors.proximity": "yes", - "sdcard.size": "512M", - "showDeviceFrame": "yes", - "skin.dynamic": "yes", - "skin.name": "pixel_2", - "tag.display": "Google Play" - } -} diff --git a/src/android/data/avds/Pixel_3_API_31.json b/src/android/data/avds/Pixel_3_API_31.json deleted file mode 100644 index f2d95ec..0000000 --- a/src/android/data/avds/Pixel_3_API_31.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "id": "Pixel_3_API_31", - "ini": { - "avd.ini.encoding": "UTF-8", - "target": "android-31" - }, - "configini": { - "AvdId": "Pixel_3_API_31", - "abi.type": "x86", - "avd.ini.displayname": "Pixel 3 API 31", - "avd.ini.encoding": "UTF-8", - "hw.accelerometer": "yes", - "hw.audioInput": "yes", - "hw.battery": "yes", - "hw.camera.back": "virtualscene", - "hw.camera.front": "emulated", - "hw.cpu.arch": "x86", - "hw.cpu.ncore": "4", - "hw.device.hash2": "MD5:8a60718609e0741c7c0cc225f49c5590", - "hw.device.manufacturer": "Google", - "hw.device.name": "pixel_3", - "hw.gps": "yes", - "hw.gpu.enabled": "yes", - "hw.gpu.mode": "auto", - "hw.initialOrientation": "Portrait", - "hw.keyboard": "yes", - "hw.lcd.density": "440", - "hw.lcd.height": "2160", - "hw.lcd.width": "1080", - "hw.ramSize": "1536", - "hw.sdCard": "yes", - "hw.sensors.orientation": "yes", - "hw.sensors.proximity": "yes", - "sdcard.size": "512M", - "showDeviceFrame": "yes", - "skin.dynamic": "yes", - "skin.name": "pixel_2", - "tag.display": "Google Play" - } -} diff --git a/src/android/data/avds/Pixel_3_API_32.json b/src/android/data/avds/Pixel_3_API_32.json deleted file mode 100644 index 7aefbee..0000000 --- a/src/android/data/avds/Pixel_3_API_32.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "id": "Pixel_3_API_32", - "ini": { - "avd.ini.encoding": "UTF-8", - "target": "android-32" - }, - "configini": { - "AvdId": "Pixel_3_API_32", - "abi.type": "x86", - "avd.ini.displayname": "Pixel 3 API 32", - "avd.ini.encoding": "UTF-8", - "hw.accelerometer": "yes", - "hw.audioInput": "yes", - "hw.battery": "yes", - "hw.camera.back": "virtualscene", - "hw.camera.front": "emulated", - "hw.cpu.arch": "x86", - "hw.cpu.ncore": "4", - "hw.device.hash2": "MD5:8a60718609e0741c7c0cc225f49c5590", - "hw.device.manufacturer": "Google", - "hw.device.name": "pixel_3", - "hw.gps": "yes", - "hw.gpu.enabled": "yes", - "hw.gpu.mode": "auto", - "hw.initialOrientation": "Portrait", - "hw.keyboard": "yes", - "hw.lcd.density": "440", - "hw.lcd.height": "2160", - "hw.lcd.width": "1080", - "hw.ramSize": "1536", - "hw.sdCard": "yes", - "hw.sensors.orientation": "yes", - "hw.sensors.proximity": "yes", - "sdcard.size": "512M", - "showDeviceFrame": "yes", - "skin.dynamic": "yes", - "skin.name": "pixel_2", - "tag.display": "Google Play" - } -} diff --git a/src/android/data/avds/Pixel_4_API_33.json b/src/android/data/avds/Pixel_4_API_33.json deleted file mode 100644 index aa275f1..0000000 --- a/src/android/data/avds/Pixel_4_API_33.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "id": "Pixel_4_API_33", - "ini": { - "avd.ini.encoding": "UTF-8", - "target": "android-33" - }, - "configini": { - "AvdId": "Pixel_4_API_33", - "abi.type": "x86", - "avd.ini.displayname": "Pixel 4 API 33", - "avd.ini.encoding": "UTF-8", - "hw.accelerometer": "yes", - "hw.audioInput": "yes", - "hw.battery": "yes", - "hw.camera.back": "virtualscene", - "hw.camera.front": "emulated", - "hw.cpu.arch": "x86", - "hw.cpu.ncore": "4", - "hw.device.hash2": "MD5:6b5943207fe196d842659d2e43022e20", - "hw.device.manufacturer": "Google", - "hw.device.name": "pixel_4", - "hw.gps": "yes", - "hw.gpu.enabled": "yes", - "hw.gpu.mode": "auto", - "hw.initialOrientation": "Portrait", - "hw.keyboard": "yes", - "hw.lcd.density": "440", - "hw.lcd.height": "2280", - "hw.lcd.width": "1080", - "hw.ramSize": "1536", - "hw.sdCard": "yes", - "hw.sensors.orientation": "yes", - "hw.sensors.proximity": "yes", - "sdcard.size": "512M", - "showDeviceFrame": "yes", - "skin.dynamic": "yes", - "skin.name": "pixel_4", - "tag.display": "Google Play" - } -} diff --git a/src/android/data/avds/Pixel_API_25.json b/src/android/data/avds/Pixel_API_25.json deleted file mode 100644 index 68321fd..0000000 --- a/src/android/data/avds/Pixel_API_25.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "id": "Pixel_API_25", - "ini": { - "avd.ini.encoding": "UTF-8", - "target": "android-25" - }, - "configini": { - "AvdId": "Pixel_API_25", - "PlayStore.enabled": "false", - "abi.type": "x86", - "avd.ini.displayname": "Pixel API 25", - "avd.ini.encoding": "UTF-8", - "disk.dataPartition.size": "800M", - "fastboot.forceColdBoot": "no", - "hw.accelerometer": "yes", - "hw.arc": "false", - "hw.audioInput": "yes", - "hw.battery": "yes", - "hw.camera.back": "virtualscene", - "hw.camera.front": "emulated", - "hw.cpu.arch": "x86", - "hw.cpu.ncore": "4", - "hw.dPad": "no", - "hw.device.hash2": "MD5:524882cfa9f421413193056700a29392", - "hw.device.manufacturer": "Google", - "hw.device.name": "pixel", - "hw.gps": "yes", - "hw.gpu.enabled": "yes", - "hw.gpu.mode": "auto", - "hw.initialOrientation": "Portrait", - "hw.keyboard": "yes", - "hw.lcd.density": "480", - "hw.lcd.height": "1920", - "hw.lcd.width": "1080", - "hw.mainKeys": "no", - "hw.ramSize": "1536", - "hw.sdCard": "yes", - "hw.sensors.orientation": "yes", - "hw.sensors.proximity": "yes", - "hw.trackBall": "no", - "runtime.network.latency": "none", - "runtime.network.speed": "full", - "sdcard.size": "100M", - "showDeviceFrame": "yes", - "skin.dynamic": "yes", - "skin.name": "pixel", - "tag.display": "Google APIs", - "vm.heapSize": "256" - } -} diff --git a/src/android/list.ts b/src/android/list.ts index 68011df..5808ecd 100644 --- a/src/android/list.ts +++ b/src/android/list.ts @@ -12,7 +12,6 @@ export async function run(args: readonly string[]): Promise { export async function list(args: readonly string[]): Promise { const sdk = await getSDK(); - const errors: Exception[] = []; const [devices, virtualDevices] = await Promise.all([ (async () => { diff --git a/src/android/sdk-info.ts b/src/android/sdk-info.ts index 86b2f74..5e25f56 100644 --- a/src/android/sdk-info.ts +++ b/src/android/sdk-info.ts @@ -3,7 +3,7 @@ import { stringify } from '../utils/json'; import type { SDKPackage } from './utils/sdk'; import { findAllSDKPackages, getSDK } from './utils/sdk'; import type { APILevel } from './utils/sdk/api'; -import { API_LEVEL_SCHEMAS, getAPILevels } from './utils/sdk/api'; +import { getAPILevels } from './utils/sdk/api'; type Platform = Required; @@ -19,8 +19,7 @@ export async function run(args: readonly string[]): Promise { const packages = await findAllSDKPackages(sdk); const apis = await getAPILevels(packages); const platforms = apis.map(api => { - const schema = API_LEVEL_SCHEMAS.find(s => s.apiLevel === api.apiLevel); - return { ...api, missingPackages: schema ? schema.validate(packages) : [] }; + return { ...api }; }); const sdkinfo: SDKInfo = { @@ -58,13 +57,6 @@ API Level: ${platform.apiLevel} Packages: ${platform.packages .map(p => formatPackage(p)) .join('\n' + ' '.repeat(22))} -${ - platform.missingPackages.length > 0 - ? `(!) Missing Packages: ${platform.missingPackages - .map(p => formatPackage(p)) - .join('\n' + ' '.repeat(22))}` - : '' -} `.trim(); } diff --git a/src/android/utils/avd.ts b/src/android/utils/avd.ts index 9c9a05d..1293dc8 100644 --- a/src/android/utils/avd.ts +++ b/src/android/utils/avd.ts @@ -1,29 +1,10 @@ -import { copy, mkdirp, readdir, statSafe } from '@ionic/utils-fs'; +import { readdir } from '@ionic/utils-fs'; import * as Debug from 'debug'; -import * as os from 'os'; import * as pathlib from 'path'; -import { ASSETS_PATH } from '../../constants'; -import { - AVDException, - ERR_INVALID_SKIN, - ERR_INVALID_SYSTEM_IMAGE, - ERR_MISSING_SYSTEM_IMAGE, - ERR_SDK_UNSATISFIED_PACKAGES, - ERR_UNSUITABLE_API_INSTALLATION, - ERR_UNSUPPORTED_API_LEVEL, -} from '../../errors'; -import { readINI, writeINI } from '../../utils/ini'; -import { sort } from '../../utils/object'; +import { readINI } from '../../utils/ini'; -import type { SDK, SDKPackage } from './sdk'; -import { findAllSDKPackages } from './sdk'; -import type { APILevel, PartialAVDSchematic } from './sdk/api'; -import { - API_LEVEL_SCHEMAS, - findPackageBySchemaPath, - getAPILevels, -} from './sdk/api'; +import type { SDK } from './sdk'; const modulePrefix = 'native-run:android:utils:avd'; @@ -197,243 +178,3 @@ export async function getInstalledAVDs(sdk: SDK): Promise { return avds; } - -export async function getDefaultAVDSchematic(sdk: SDK): Promise { - const debug = Debug(`${modulePrefix}:${getDefaultAVDSchematic.name}`); - const packages = await findAllSDKPackages(sdk); - const apis = await getAPILevels(packages); - const errors: AVDException[] = []; - - for (const api of apis) { - try { - const schematic = await getAVDSchematicFromAPILevel(sdk, packages, api); - debug('Using schematic %s for default AVD', schematic.id); - - return schematic; - } catch (e) { - if (!(e instanceof AVDException)) { - throw e; - } - errors.push(e); - debug('Issue with API %s: %s', api.apiLevel, e.message); - } - } - if (errors.length > 0) { - const unsupportedError = errors.find( - e => e.code === ERR_UNSUPPORTED_API_LEVEL, - ); - if (unsupportedError) { - throw unsupportedError; - } - } - - throw new AVDException( - 'No suitable API installation found. Use --sdk-info to reveal missing packages and other issues.', - ERR_UNSUITABLE_API_INSTALLATION, - 1, - ); -} - -export async function getAVDSchematicFromAPILevel( - sdk: SDK, - packages: readonly SDKPackage[], - api: APILevel, -): Promise { - const schema = API_LEVEL_SCHEMAS.find(s => s.apiLevel === api.apiLevel); - - if (!schema) { - throw new AVDException( - `Unsupported API level: ${api.apiLevel}`, - ERR_UNSUPPORTED_API_LEVEL, - ); - } - - const missingPackages = schema.validate(packages); - - if (missingPackages.length > 0) { - throw new AVDException( - `Unsatisfied packages within API ${api.apiLevel}: ${missingPackages - .map(pkg => pkg.path) - .join(', ')}`, - ERR_SDK_UNSATISFIED_PACKAGES, - 1, - ); - } - - return createAVDSchematic(sdk, await schema.loadPartialAVDSchematic()); -} - -export async function getDefaultAVD( - sdk: SDK, - avds: readonly AVD[], -): Promise { - const defaultAvdSchematic = await getDefaultAVDSchematic(sdk); - const defaultAvd = avds.find(avd => avd.id === defaultAvdSchematic.id); - - if (defaultAvd) { - return defaultAvd; - } - - return createAVD(sdk, defaultAvdSchematic); -} - -export async function createAVD( - sdk: SDK, - schematic: AVDSchematic, -): Promise { - const { id, ini, configini } = schematic; - - await mkdirp(pathlib.join(sdk.avdHome, `${id}.avd`)); - - await Promise.all([ - writeINI(pathlib.join(sdk.avdHome, `${id}.ini`), ini), - writeINI(pathlib.join(sdk.avdHome, `${id}.avd`, 'config.ini'), configini), - ]); - - return getAVDFromConfigINI( - pathlib.join(sdk.avdHome, `${id}.ini`), - ini, - configini, - ); -} - -export async function createAVDSchematic( - sdk: SDK, - partialSchematic: PartialAVDSchematic, -): Promise { - const sysimage = findPackageBySchemaPath( - sdk.packages || [], - new RegExp(`^system-images;${partialSchematic.ini.target}`), - ); - - if (!sysimage) { - throw new AVDException( - `Cannot create AVD schematic for ${partialSchematic.id}: missing system image.`, - ERR_MISSING_SYSTEM_IMAGE, - ); - } - - const avdpath = pathlib.join(sdk.avdHome, `${partialSchematic.id}.avd`); - const skinpath = getSkinPathByName( - sdk, - partialSchematic.configini['skin.name'], - ); - const sysdir = pathlib.relative(sdk.root, sysimage.location); - const [, , tagid] = sysimage.path.split(';'); - const arch = - os.arch() === 'arm64' ? 'arm64' : partialSchematic.configini['abi.type']; - const schematic: AVDSchematic = { - id: partialSchematic.id, - ini: sort({ - ...partialSchematic.ini, - 'path': avdpath, - 'path.rel': `avd/${partialSchematic.id}.avd`, - }), - configini: sort({ - ...partialSchematic.configini, - 'abi.type': arch, - 'hw.cpu.arch': arch, - 'skin.path': skinpath, - 'image.sysdir.1': sysdir, - 'tag.id': tagid, - }), - }; - - await validateAVDSchematic(sdk, schematic); - - return schematic; -} - -export async function validateAVDSchematic( - sdk: SDK, - schematic: AVDSchematic, -): Promise { - const { configini } = schematic; - const skin = configini['skin.name']; - const skinpath = configini['skin.path']; - const sysdir = configini['image.sysdir.1']; - - if (!skinpath) { - throw new AVDException( - `${schematic.id} does not have a skin defined.`, - ERR_INVALID_SKIN, - ); - } - - if (!sysdir) { - throw new AVDException( - `${schematic.id} does not have a system image defined.`, - ERR_INVALID_SYSTEM_IMAGE, - ); - } - - await validateSkin(sdk, skin, skinpath); - await validateSystemImagePath(sdk, sysdir); -} - -export async function validateSkin( - sdk: SDK, - skin: string, - skinpath: string, -): Promise { - const debug = Debug(`${modulePrefix}:${validateSkin.name}`); - const p = pathlib.join(skinpath, 'layout'); - - debug('Checking skin layout file: %s', p); - - const stat = await statSafe(p); - - if (stat?.isFile()) { - return; - } - - await copySkin(sdk, skin, skinpath); -} - -export async function copySkin( - sdk: SDK, - skin: string, - skinpath: string, -): Promise { - const debug = Debug(`${modulePrefix}:${copySkin.name}`); - const skinsrc = pathlib.resolve(ASSETS_PATH, 'android', 'skins', skin); - - const stat = await statSafe(skinsrc); - - if (stat?.isDirectory()) { - debug('Copying skin from %s to %s', skinsrc, skinpath); - - try { - return await copy(skinsrc, skinpath); - } catch (e) { - debug('Error while copying skin: %O', e); - } - } - - throw new AVDException(`${skinpath} is an invalid skin.`, ERR_INVALID_SKIN); -} - -export async function validateSystemImagePath( - sdk: SDK, - sysdir: string, -): Promise { - const debug = Debug(`${modulePrefix}:${validateSystemImagePath.name}`); - const p = pathlib.join(sdk.root, sysdir, 'package.xml'); - - debug('Checking package.xml file: %s', p); - - const stat = await statSafe(p); - - if (!stat || !stat.isFile()) { - throw new AVDException( - `${p} is an invalid system image package.`, - ERR_INVALID_SYSTEM_IMAGE, - ); - } -} - -export function getSkinPathByName(sdk: SDK, name: string): string { - const path = pathlib.join(sdk.root, 'skins', name); - - return path; -} diff --git a/src/android/utils/emulator.ts b/src/android/utils/emulator.ts index 71420fb..3ad1d9f 100644 --- a/src/android/utils/emulator.ts +++ b/src/android/utils/emulator.ts @@ -61,14 +61,12 @@ export async function spawnEmulator( const emulatorBin = path.join(emulator.location, 'emulator'); const args = ['-avd', avd.id, '-port', port.toString(), '-verbose']; debug('Invoking emulator: %O %O', emulatorBin, args); - const p = spawn(emulatorBin, args, { detached: true, stdio: ['ignore', 'pipe', 'pipe'], env: supplementProcessEnv(sdk), }); p.unref(); - return new Promise((_resolve, _reject) => { const resolve: typeof _resolve = once(() => { _resolve(); @@ -89,7 +87,6 @@ export async function spawnEmulator( debug('Android Emulator: %O', line); const event = parseEmulatorOutput(line); - if (event === EmulatorEvent.AlreadyRunning) { reject( new EmulatorException( diff --git a/src/android/utils/list.ts b/src/android/utils/list.ts index d5e5558..17b0deb 100644 --- a/src/android/utils/list.ts +++ b/src/android/utils/list.ts @@ -3,7 +3,7 @@ import type { Target } from '../../utils/list'; import type { Device } from './adb'; import { getDevices } from './adb'; import type { AVD } from './avd'; -import { getDefaultAVD, getInstalledAVDs } from './avd'; +import { getInstalledAVDs } from './avd'; import type { SDK } from './sdk'; export async function getDeviceTargets(sdk: SDK): Promise { @@ -14,12 +14,6 @@ export async function getDeviceTargets(sdk: SDK): Promise { export async function getVirtualTargets(sdk: SDK): Promise { const avds = await getInstalledAVDs(sdk); - const defaultAvd = await getDefaultAVD(sdk, avds); - - if (!avds.includes(defaultAvd)) { - avds.push(defaultAvd); - } - return avds.map(avdToTarget); } diff --git a/src/android/utils/run.ts b/src/android/utils/run.ts index ed75a81..d82778b 100644 --- a/src/android/utils/run.ts +++ b/src/android/utils/run.ts @@ -2,7 +2,9 @@ import * as Debug from 'debug'; import { ADBException, + AndroidRunException, ERR_INCOMPATIBLE_UPDATE, + ERR_NO_TARGET, ERR_VERSION_DOWNGRADE, } from '../../errors'; import { log } from '../../utils/log'; @@ -10,7 +12,6 @@ import { log } from '../../utils/log'; import type { Device } from './adb'; import { installApk, uninstallApp } from './adb'; import type { AVD } from './avd'; -import { getDefaultAVD } from './avd'; import { getAVDFromEmulator, runEmulator } from './emulator'; import type { SDK } from './sdk'; @@ -106,13 +107,10 @@ export async function selectVirtualDevice( debug('Found running emulator: %s', emulator.serial); return emulator; } - - // Spin up an emulator using the AVD we ship with. - const defaultAvd = await getDefaultAVD(sdk, avds); - const device = await runEmulator(sdk, defaultAvd, 5554); // TODO: will 5554 always be available at this point? - debug('Emulator ready, running avd: %s on %s', defaultAvd.id, device.serial); - - return device; + throw new AndroidRunException( + 'No target devices/emulators available.', + ERR_NO_TARGET, + ); } export async function installApkToDevice( diff --git a/src/android/utils/sdk/api.ts b/src/android/utils/sdk/api.ts index d89d0cc..cae9525 100644 --- a/src/android/utils/sdk/api.ts +++ b/src/android/utils/sdk/api.ts @@ -1,16 +1,5 @@ import * as Debug from 'debug'; -import type * as Nexus_5X_API_24 from '../../data/avds/Nexus_5X_API_24.json'; -import type * as Pixel_2_API_26 from '../../data/avds/Pixel_2_API_26.json'; -import type * as Pixel_2_API_27 from '../../data/avds/Pixel_2_API_27.json'; -import type * as Pixel_2_API_28 from '../../data/avds/Pixel_2_API_28.json'; -import type * as Pixel_3_API_29 from '../../data/avds/Pixel_3_API_29.json'; -import type * as Pixel_3_API_30 from '../../data/avds/Pixel_3_API_30.json'; -import type * as Pixel_3_API_31 from '../../data/avds/Pixel_3_API_31.json'; -import type * as Pixel_3_API_32 from '../../data/avds/Pixel_3_API_32.json'; -import type * as Pixel_4_API_33 from '../../data/avds/Pixel_4_API_33.json'; -import type * as Pixel_API_25 from '../../data/avds/Pixel_API_25.json'; - import type { SDKPackage } from './'; const modulePrefix = 'native-run:android:utils:sdk:api'; @@ -18,7 +7,6 @@ const modulePrefix = 'native-run:android:utils:sdk:api'; export interface APILevel { readonly apiLevel: string; readonly packages: SDKPackage[]; - readonly missingPackages?: APISchemaPackage[]; } export async function getAPILevels( @@ -87,18 +75,6 @@ export function findPackageBySchemaPath( }); } -export type PartialAVDSchematic = - | typeof Pixel_4_API_33 - | typeof Pixel_3_API_32 - | typeof Pixel_3_API_31 - | typeof Pixel_3_API_30 - | typeof Pixel_3_API_29 - | typeof Pixel_2_API_28 - | typeof Pixel_2_API_27 - | typeof Pixel_2_API_26 - | typeof Pixel_API_25 - | typeof Nexus_5X_API_24; - export interface APISchemaPackage { readonly name: string; readonly path: string; @@ -108,298 +84,4 @@ export interface APISchemaPackage { export interface APISchema { readonly apiLevel: string; readonly validate: (packages: readonly SDKPackage[]) => APISchemaPackage[]; - readonly loadPartialAVDSchematic: () => Promise; } - -export const API_LEVEL_33: APISchema = Object.freeze({ - apiLevel: '33', - validate: (packages: readonly SDKPackage[]) => { - const schemas: APISchemaPackage[] = [ - { name: 'Android Emulator', path: 'emulator', version: /.+/ }, - { - name: 'Android SDK Platform 33', - path: 'platforms;android-33', - version: /.+/, - }, - ]; - - const missingPackages = findUnsatisfiedPackages(packages, schemas); - - if (!findPackageBySchemaPath(packages, /^system-images;android-33;/)) { - missingPackages.push({ - name: 'Google Play Intel x86 Atom System Image', - path: 'system-images;android-33;google_apis_playstore;x86', - version: '/.+/', - }); - } - - return missingPackages; - }, - loadPartialAVDSchematic: async () => - import('../../data/avds/Pixel_4_API_33.json'), -}); - -export const API_LEVEL_32: APISchema = Object.freeze({ - apiLevel: '32', - validate: (packages: readonly SDKPackage[]) => { - const schemas: APISchemaPackage[] = [ - { name: 'Android Emulator', path: 'emulator', version: /.+/ }, - { - name: 'Android SDK Platform 32', - path: 'platforms;android-32', - version: /.+/, - }, - ]; - - const missingPackages = findUnsatisfiedPackages(packages, schemas); - - if (!findPackageBySchemaPath(packages, /^system-images;android-32;/)) { - missingPackages.push({ - name: 'Google Play Intel x86 Atom System Image', - path: 'system-images;android-32;google_apis_playstore;x86', - version: '/.+/', - }); - } - - return missingPackages; - }, - loadPartialAVDSchematic: async () => - import('../../data/avds/Pixel_3_API_32.json'), -}); - -export const API_LEVEL_31: APISchema = Object.freeze({ - apiLevel: '31', - validate: (packages: readonly SDKPackage[]) => { - const schemas: APISchemaPackage[] = [ - { name: 'Android Emulator', path: 'emulator', version: /.+/ }, - { - name: 'Android SDK Platform 31', - path: 'platforms;android-31', - version: /.+/, - }, - ]; - - const missingPackages = findUnsatisfiedPackages(packages, schemas); - - if (!findPackageBySchemaPath(packages, /^system-images;android-31;/)) { - missingPackages.push({ - name: 'Google Play Intel x86 Atom System Image', - path: 'system-images;android-31;google_apis_playstore;x86', - version: '/.+/', - }); - } - - return missingPackages; - }, - loadPartialAVDSchematic: async () => - import('../../data/avds/Pixel_3_API_31.json'), -}); - -export const API_LEVEL_30: APISchema = Object.freeze({ - apiLevel: '30', - validate: (packages: readonly SDKPackage[]) => { - const schemas: APISchemaPackage[] = [ - { name: 'Android Emulator', path: 'emulator', version: /.+/ }, - { - name: 'Android SDK Platform 30', - path: 'platforms;android-30', - version: /.+/, - }, - ]; - - const missingPackages = findUnsatisfiedPackages(packages, schemas); - - if (!findPackageBySchemaPath(packages, /^system-images;android-30;/)) { - missingPackages.push({ - name: 'Google Play Intel x86 Atom System Image', - path: 'system-images;android-30;google_apis_playstore;x86', - version: '/.+/', - }); - } - - return missingPackages; - }, - loadPartialAVDSchematic: async () => - import('../../data/avds/Pixel_3_API_30.json'), -}); - -export const API_LEVEL_29: APISchema = Object.freeze({ - apiLevel: '29', - validate: (packages: readonly SDKPackage[]) => { - const schemas: APISchemaPackage[] = [ - { name: 'Android Emulator', path: 'emulator', version: /.+/ }, - { - name: 'Android SDK Platform 29', - path: 'platforms;android-29', - version: /.+/, - }, - ]; - - const missingPackages = findUnsatisfiedPackages(packages, schemas); - - if (!findPackageBySchemaPath(packages, /^system-images;android-29;/)) { - missingPackages.push({ - name: 'Google Play Intel x86 Atom System Image', - path: 'system-images;android-29;google_apis_playstore;x86', - version: '/.+/', - }); - } - - return missingPackages; - }, - loadPartialAVDSchematic: async () => - import('../../data/avds/Pixel_3_API_29.json'), -}); - -export const API_LEVEL_28: APISchema = Object.freeze({ - apiLevel: '28', - validate: (packages: readonly SDKPackage[]) => { - const schemas: APISchemaPackage[] = [ - { name: 'Android Emulator', path: 'emulator', version: /.+/ }, - { - name: 'Android SDK Platform 28', - path: 'platforms;android-28', - version: /.+/, - }, - ]; - - const missingPackages = findUnsatisfiedPackages(packages, schemas); - - if (!findPackageBySchemaPath(packages, /^system-images;android-28;/)) { - missingPackages.push({ - name: 'Google Play Intel x86 Atom System Image', - path: 'system-images;android-28;google_apis_playstore;x86', - version: '/.+/', - }); - } - - return missingPackages; - }, - loadPartialAVDSchematic: async () => - import('../../data/avds/Pixel_2_API_28.json'), -}); - -export const API_LEVEL_27: APISchema = Object.freeze({ - apiLevel: '27', - validate: (packages: readonly SDKPackage[]) => { - const schemas: APISchemaPackage[] = [ - { name: 'Android Emulator', path: 'emulator', version: /.+/ }, - { - name: 'Android SDK Platform 27', - path: 'platforms;android-27', - version: /.+/, - }, - ]; - - const missingPackages = findUnsatisfiedPackages(packages, schemas); - - if (!findPackageBySchemaPath(packages, /^system-images;android-27;/)) { - missingPackages.push({ - name: 'Google Play Intel x86 Atom System Image', - path: 'system-images;android-27;google_apis_playstore;x86', - version: '/.+/', - }); - } - - return missingPackages; - }, - loadPartialAVDSchematic: async () => - import('../../data/avds/Pixel_2_API_27.json'), -}); - -export const API_LEVEL_26: APISchema = Object.freeze({ - apiLevel: '26', - validate: (packages: readonly SDKPackage[]) => { - const schemas: APISchemaPackage[] = [ - { name: 'Android Emulator', path: 'emulator', version: /.+/ }, - { - name: 'Android SDK Platform 26', - path: 'platforms;android-26', - version: /.+/, - }, - ]; - - const missingPackages = findUnsatisfiedPackages(packages, schemas); - - if (!findPackageBySchemaPath(packages, /^system-images;android-26;/)) { - missingPackages.push({ - name: 'Google Play Intel x86 Atom System Image', - path: 'system-images;android-26;google_apis_playstore;x86', - version: '/.+/', - }); - } - - return missingPackages; - }, - loadPartialAVDSchematic: async () => - import('../../data/avds/Pixel_2_API_26.json'), -}); - -export const API_LEVEL_25: APISchema = Object.freeze({ - apiLevel: '25', - validate: (packages: readonly SDKPackage[]) => { - const schemas: APISchemaPackage[] = [ - { name: 'Android Emulator', path: 'emulator', version: /.+/ }, - { - name: 'Android SDK Platform 25', - path: 'platforms;android-25', - version: /.+/, - }, - ]; - - const missingPackages = findUnsatisfiedPackages(packages, schemas); - - if (!findPackageBySchemaPath(packages, /^system-images;android-25;/)) { - missingPackages.push({ - name: 'Google Play Intel x86 Atom System Image', - path: 'system-images;android-25;google_apis_playstore;x86', - version: '/.+/', - }); - } - - return missingPackages; - }, - loadPartialAVDSchematic: async () => - import('../../data/avds/Pixel_API_25.json'), -}); - -export const API_LEVEL_24: APISchema = Object.freeze({ - apiLevel: '24', - validate: (packages: readonly SDKPackage[]) => { - const schemas: APISchemaPackage[] = [ - { name: 'Android Emulator', path: 'emulator', version: /.+/ }, - { - name: 'Android SDK Platform 24', - path: 'platforms;android-24', - version: /.+/, - }, - ]; - - const missingPackages = findUnsatisfiedPackages(packages, schemas); - - if (!findPackageBySchemaPath(packages, /^system-images;android-24;/)) { - missingPackages.push({ - name: 'Google Play Intel x86 Atom System Image', - path: 'system-images;android-24;google_apis_playstore;x86', - version: '/.+/', - }); - } - - return missingPackages; - }, - loadPartialAVDSchematic: async () => - import('../../data/avds/Nexus_5X_API_24.json'), -}); - -export const API_LEVEL_SCHEMAS: readonly APISchema[] = [ - API_LEVEL_33, - API_LEVEL_32, - API_LEVEL_31, - API_LEVEL_30, - API_LEVEL_29, - API_LEVEL_28, - API_LEVEL_27, - API_LEVEL_26, - API_LEVEL_25, - API_LEVEL_24, -]; diff --git a/src/errors.ts b/src/errors.ts index 508611a..90c7856 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -54,23 +54,16 @@ export const ERR_NO_CERTIFICATES = 'ERR_NO_CERTIFICATES'; export const ERR_NOT_ENOUGH_SPACE = 'ERR_NOT_ENOUGH_SPACE'; export const ERR_DEVICE_OFFLINE = 'ERR_DEVICE_OFFLINE'; export const ERR_INVALID_SDK_PACKAGE = 'ERR_INVALID_SDK_PACKAGE'; -export const ERR_INVALID_SERIAL = 'ERR_INVALID_SERIAL'; -export const ERR_INVALID_SKIN = 'ERR_INVALID_SKIN'; -export const ERR_INVALID_SYSTEM_IMAGE = 'ERR_INVALID_SYSTEM_IMAGE'; export const ERR_NON_ZERO_EXIT = 'ERR_NON_ZERO_EXIT'; -export const ERR_NO_AVDS_FOUND = 'ERR_NO_AVDS_FOUND'; -export const ERR_MISSING_SYSTEM_IMAGE = 'ERR_MISSING_SYSTEM_IMAGE'; export const ERR_UNSUITABLE_API_INSTALLATION = 'ERR_UNSUITABLE_API_INSTALLATION'; export const ERR_SDK_NOT_FOUND = 'ERR_SDK_NOT_FOUND'; export const ERR_SDK_PACKAGE_NOT_FOUND = 'ERR_SDK_PACKAGE_NOT_FOUND'; -export const ERR_SDK_UNSATISFIED_PACKAGES = 'ERR_SDK_UNSATISFIED_PACKAGES'; export const ERR_TARGET_NOT_FOUND = 'ERR_TARGET_NOT_FOUND'; export const ERR_NO_DEVICE = 'ERR_NO_DEVICE'; export const ERR_NO_TARGET = 'ERR_NO_TARGET'; export const ERR_DEVICE_LOCKED = 'ERR_DEVICE_LOCKED'; export const ERR_UNKNOWN_AVD = 'ERR_UNKNOWN_AVD'; -export const ERR_UNSUPPORTED_API_LEVEL = 'ERR_UNSUPPORTED_API_LEVEL'; export type CLIExceptionCode = typeof ERR_BAD_INPUT; @@ -87,27 +80,19 @@ export type ADBExceptionCode = export class ADBException extends AndroidException {} -export type AVDExceptionCode = - | typeof ERR_INVALID_SKIN - | typeof ERR_INVALID_SYSTEM_IMAGE - | typeof ERR_UNSUITABLE_API_INSTALLATION - | typeof ERR_UNSUPPORTED_API_LEVEL - | typeof ERR_SDK_UNSATISFIED_PACKAGES - | typeof ERR_MISSING_SYSTEM_IMAGE; +export type AVDExceptionCode = typeof ERR_UNSUITABLE_API_INSTALLATION; export class AVDException extends AndroidException {} export type EmulatorExceptionCode = | typeof ERR_ALREADY_RUNNING | typeof ERR_AVD_HOME_NOT_FOUND - | typeof ERR_INVALID_SERIAL | typeof ERR_NON_ZERO_EXIT | typeof ERR_UNKNOWN_AVD; export class EmulatorException extends AndroidException {} export type AndroidRunExceptionCode = - | typeof ERR_NO_AVDS_FOUND | typeof ERR_TARGET_NOT_FOUND | typeof ERR_NO_DEVICE | typeof ERR_NO_TARGET;