From fd1164f355a2edc27411ab206da8269a2ac0bf57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AE=80=E9=9D=99=E5=87=A1?= <30424139+wtto00@users.noreply.github.com> Date: Sat, 23 Sep 2023 01:18:09 +0800 Subject: [PATCH] fix: Refactor the parameters of createAVD. --- .eslintrc.json | 3 +- .github/workflows/test.yml | 13 ++++++- README-ZH_CN.md | 21 ++++++----- README.md | 21 ++++++----- spec/afterStart.test.ts | 8 +++-- src/emulator.ts | 21 +++++++++++ src/index.ts | 71 ++++++++++++-------------------------- 7 files changed, 83 insertions(+), 75 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index befe3fc..90ec3d5 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -20,6 +20,7 @@ "linebreak-style": ["error", "unix"], "quotes": ["error", "single"], "semi": ["error", "always"], - "@typescript-eslint/ban-types": "off" + "@typescript-eslint/ban-types": "off", + "@typescript-eslint/prefer-nullish-coalescing": "off" } } diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4c6c0a2..c7a2ac2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,7 +31,7 @@ jobs: # runs-on: macos-latest Test: - runs-on: windows-latest + runs-on: ubuntu-latest needs: Lint strategy: matrix: @@ -66,5 +66,16 @@ jobs: - name: Setup Android SDK uses: amyu/setup-android@v3.1 + - name: Run some command + run: | + ls "$ANDROID_HOME" + ls "$ANDROID_HOME"/emulator + + - name: Enable KVM group perms + 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 👩🏽‍💻 run: npm run test diff --git a/README-ZH_CN.md b/README-ZH_CN.md index 6be6188..a92e168 100644 --- a/README-ZH_CN.md +++ b/README-ZH_CN.md @@ -134,17 +134,16 @@ android }); ``` -| field | type | required | default | note | -| ------- | ------- | -------- | ------- | --------------------------------------------------------------------------------------- | -| sdcard | string | false | - | 共享 SD 卡镜像的路径,或者为新模拟器选择一个新的 SD 卡大小。 | -| tag | string | false | - | 用于模拟器的 sys-img 标签。默认情况下,如果平台只有一个标签用于其系统镜像,则自动选择。 | -| path | string | false | - | 新的模拟器将创建在哪个目录位置。 | -| package | string | true | - | 此模拟器的系统镜像的路径(例如 'system-images;android-19;google_apis;x86')。 | -| name | string | false | - | 新模拟器的名称。 | -| skin | string | false | - | 此设备可选择使用的皮肤名称。 | -| force | boolean | false | - | 创建虚拟设备(覆盖现有的模拟器)。 | -| abi | string | false | - | 如果平台的系统镜像只有一个 ABI,则默认为自动选择 ABI 来使用模拟器。 | -| device | string | false | - | 可选的要使用的设备定义。可以是设备索引或 id。 | +| field | type | required | default | note | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -------- | --------- | ----------------------------------------------------------------------------------- | +| apiLevel | number | false | - | 平台系统镜像的API级别 - 例如,Android Marshmallow的级别为23,Android 10的级别为29。 | +| target | 'default'
'google_apis'
'playstore'
'android-wear'
'android-wear-cn'
'android-tv'
'google-tv'
'aosp_atd '
'google_atd' | false | 'default' | 系统镜像的目标。 | +| arch | 'x86_64'
'x86'
'arm64-v8a'
'armeabi-v7a' | false | 'x86_64' | 系统镜像的CPU架构 | +| package | string | true | - | 此模拟器的系统镜像的路径(例如 'system-images;android-19;google_apis;x86')。 | +| name | string | false | - | 新模拟器的名称。 | +| force | boolean | false | - | 创建虚拟设备(覆盖现有的模拟器)。 | + +- 如果你传了`package`,则参数`apiLevel`,`target`,`arch`将被会略。如果你没有传参`package`,则`apiLevel`参数是必须的。 ### hasAVD diff --git a/README.md b/README.md index d0c3d8a..1be71c5 100644 --- a/README.md +++ b/README.md @@ -134,17 +134,16 @@ android }); ``` -| field | type | required | default | note | -| ------- | ------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------- | -| sdcard | string | false | - | Path to a shared SD card image, or size of a new sdcard for the new AVD. | -| tag | string | false | - | The sys-img tag to use for the AVD. The default is to auto-select if the platform has only one tag for its system images. | -| path | string | false | - | Directory where the new AVD will be created. | -| package | string | true | - | Package path of the system image for this AVD (e.g. 'system-images;android-19;google_apis;x86'). | -| name | string | false | - | Name of the new AVD. | -| skin | string | false | - | The optional name of a skin to use with this device. | -| force | boolean | false | - | Forces creation (overwrites an existing AVD) | -| abi | string | false | - | The ABI to use for the AVD. The default is to auto-select the ABI if the platform has only one ABI for its system images. | -| device | string | false | - | The optional device definition to use. Can be a device index or id. | +| field | type | required | default | note | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -------- | --------- | ------------------------------------------------------------------------------------------------ | +| apiLevel | number | false | - | API level of the platform system image - e.g. 23 for Android Marshmallow, 29 for Android 10. | +| target | 'default'
'google_apis'
'playstore'
'android-wear'
'android-wear-cn'
'android-tv'
'google-tv'
'aosp_atd '
'google_atd' | false | 'default' | Target of the system image . | +| arch | 'x86_64'
'x86'
'arm64-v8a'
'armeabi-v7a' | false | 'x86_64' | CPU architecture of the system image | +| package | string | false | - | Package path of the system image for this AVD (e.g. 'system-images;android-19;google_apis;x86'). | +| name | string | false | - | Name of the new AVD. | +| force | boolean | false | - | Forces creation (overwrites an existing AVD) | + +- If you pass a `package`, the parameters `apiLevel`, `target`, and `arch` will be ignored. If you don't pass a `package`, the `apiLevel` parameter is required. ### hasAVD diff --git a/spec/afterStart.test.ts b/spec/afterStart.test.ts index 313748d..d0a5b87 100644 --- a/spec/afterStart.test.ts +++ b/spec/afterStart.test.ts @@ -1,5 +1,6 @@ import path from 'path'; import Android from '../src/index.js'; +import { EmulatorGpu } from '../src/emulator.js'; const android = new Android(); @@ -11,8 +12,7 @@ beforeAll(async () => { avdName = `TestCreate_${Math.random().toString().substring(2)}`; const images = (await android.listImages()).filter((item) => item.vendor === 'default' && item.arch === 'x86_64'); if (images.length === 0) return; - const image = images[images.length - 1].name; - await android.createAVD({ name: avdName, package: image, force: false }); + await android.createAVD({ name: avdName, apiLevel: 31, force: false }); } else { avdName = avds[0].Name; } @@ -22,7 +22,9 @@ beforeAll(async () => { noaudio: true, noBootAnim: true, noSnapshot: true, - noWindow: true + noSnapshotSave: true, + noWindow: true, + gpu: EmulatorGpu.SWIFTSHADER_INDIRECT }); emulatorId = res.id; if (emulatorId) { diff --git a/src/emulator.ts b/src/emulator.ts index 2d04c1d..0bbe84d 100644 --- a/src/emulator.ts +++ b/src/emulator.ts @@ -41,6 +41,27 @@ export interface EmulatorOptions { wipeData?: boolean; /** disable passive gps updates */ noPassiveGps?: boolean; + /** Disables acceleration entirely. Mostly useful for debugging. */ + noAccel?: boolean; +} + +export enum SystemImageTarget { + DEFAULT = 'default', + GOOGLE_APIS = 'google_apis', + PLAYSTORE = 'playstore', + ANDROID_WEAR = 'android-wear', + android_wear_cn = 'android-wear-cn', + android_tv = 'android-tv', + google_tv = 'google-tv', + AOSP_ATD = 'aosp_atd', + GOOGLE_ATD = 'google_atd' +} + +export enum Arch { + X86 = 'x86', + X86_64 = 'x86_64', + ARM64_V8A = 'arm64-v8a', + ARMEABI_V7A = 'armeabi-v7a' } /** diff --git a/src/index.ts b/src/index.ts index b1d8dc5..f1ecc8f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,7 @@ import { spawnExec, spawnWaitFor } from './util.js'; -import { EmulatorOptions } from './emulator.js'; +import { Arch, EmulatorOptions, SystemImageTarget } from './emulator.js'; export interface AndroidOptions { /** The location of the `adb` executable file relative to `ANDROID_HOME` */ @@ -23,43 +23,18 @@ export interface AndroidOptions { export type AndroidExecBin = 'adbBin' | 'avdmanagerBin' | 'sdkmanagerBin' | 'emulatorBin'; export interface CreateAVDOptions { - /** Path to a shared SD card image, or size of a new sdcard for the new AVD. */ - sdcard?: string; - /** - * The sys-img tag to use for the AVD. The default is to - * auto-select if the platform has only one tag for its system - * images. - */ - tag?: string; - /** Directory where the new AVD will be created. */ - path?: string; - /** - * Package path of the system image for this AVD (e.g. - * 'system-images;android-19;google_apis;x86'). - */ - package: string; - /** - * Name of the new AVD. [required] - */ + /** API level of the platform system image */ + apiLevel?: number; + /** Target of the system image */ + target?: SystemImageTarget; + /** CPU architecture of the system image */ + arch?: Arch; + /** Name of AVD */ name: string; - /** - * The optional name of a skin to use with this device. - */ - skin?: string; - /** - * Forces creation (overwrites an existing AVD) - */ + /** Forces creation (overwrites an existing AVD) */ force?: boolean; - /** - * The ABI to use for the AVD. The default is to auto-select the - * ABI if the platform has only one ABI for its system images. - */ - abi?: string; - /** - * The optional device definition to use. Can be a device index - * or id. - */ - device?: string; + /** Package path of the system image for this AVD (e.g. 'system-images;android-19;google_apis;x86'). */ + package?: string; } export interface Device { @@ -240,18 +215,18 @@ class Android { * @param name name of AVD */ async createAVD(options: CreateAVDOptions) { - if (options.package) { - // Downloading the SDK takes a lot of time, so it's best to download it in advance. - await this.sdkmanager(`--install ${options.package}`, 600000); - } - const cmdParams = Object.keys(options).reduce((prev, curr) => { - const val = options[curr as keyof CreateAVDOptions]; - if (typeof val === 'boolean') { - if (val) return `${prev} --${curr}`; - else return prev; - } - return `${prev} --${curr} ${val}`; - }, ''); + if (!options.name) return Promise.reject(Error('Missing name parameter.')); + if (!options.package && !options.apiLevel) + return Promise.reject(Error('Either the parameter "package" or "apiLevel" must be present.')); + const systemImage = + options.package || + `system-images;android-${options.apiLevel};${options.target || SystemImageTarget.DEFAULT};${ + options.arch || Arch.X86_64 + }`; + // Downloading the SDK takes a lot of time, so it's best to download it in advance. + await this.sdkmanager(`--install ${systemImage}`, 600000); + let cmdParams = `-n ${options.name} -k ${systemImage}`; + if (options.force) cmdParams += ' -f'; return await this.avdmanager(`-s create avd ${cmdParams}`); }