@aiot-toolkit/emulator 2.0.3-beta.7 → 2.0.3-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +133 -8
  2. package/lib/emulatorutil/EmulatorLog.js +22 -18
  3. package/lib/emulatorutil/constants.d.ts +18 -5
  4. package/lib/emulatorutil/constants.js +94 -53
  5. package/lib/emulatorutil/index.d.ts +3 -2
  6. package/lib/emulatorutil/index.js +38 -8
  7. package/lib/emulatorutil/running.d.ts +24 -0
  8. package/lib/emulatorutil/running.js +108 -0
  9. package/lib/emulatorutil/skinLayoutParser.d.ts +14 -0
  10. package/lib/emulatorutil/skinLayoutParser.js +111 -0
  11. package/lib/index.d.ts +5 -5
  12. package/lib/index.js +76 -26
  13. package/lib/instance/common.d.ts +38 -39
  14. package/lib/instance/common.js +141 -223
  15. package/lib/instance/dev.d.ts +7 -42
  16. package/lib/instance/dev.js +54 -235
  17. package/lib/instance/index.d.ts +6 -5
  18. package/lib/instance/index.js +51 -35
  19. package/lib/instance/miwear.d.ts +14 -75
  20. package/lib/instance/miwear.js +93 -370
  21. package/lib/instance/pre.d.ts +11 -3
  22. package/lib/instance/pre.js +55 -93
  23. package/lib/instance/pre5.d.ts +11 -0
  24. package/lib/instance/pre5.js +38 -0
  25. package/lib/static/avdConfigIni.json +5 -5
  26. package/lib/typing/Instance.d.ts +30 -15
  27. package/lib/typing/Instance.js +13 -6
  28. package/lib/typing/Vvd.d.ts +105 -0
  29. package/lib/typing/Vvd.js +31 -0
  30. package/lib/utils/file.d.ts +0 -0
  31. package/lib/utils/file.js +1 -0
  32. package/lib/utils/index.js +86 -100
  33. package/lib/vvd/index.d.ts +107 -0
  34. package/lib/vvd/index.js +698 -0
  35. package/lib/vvd/logcat.d.ts +16 -0
  36. package/lib/vvd/logcat.js +67 -0
  37. package/package.json +9 -8
  38. package/lib/avd/index.d.ts +0 -28
  39. package/lib/avd/index.js +0 -173
  40. package/lib/emulatorutil/EmulatorCmd.d.ts +0 -9
  41. package/lib/emulatorutil/EmulatorCmd.js +0 -226
  42. package/lib/instance/preDev.d.ts +0 -53
  43. package/lib/instance/preDev.js +0 -249
  44. package/lib/typing/Avd.d.ts +0 -23
  45. package/lib/typing/Avd.js +0 -8
@@ -0,0 +1,16 @@
1
+ import readline from 'readline';
2
+ import { ChildProcessWithoutNullStreams } from 'child_process';
3
+ import { EmulatorReadlines } from '../typing/Instance';
4
+ export declare function creatLogcat(sn: string, onStdout?: (msg: string) => void, onErrout?: (msg: string) => void, p?: ChildProcessWithoutNullStreams, rls?: EmulatorReadlines): {
5
+ logcatProcess: ChildProcessWithoutNullStreams;
6
+ onStdout: (msg: string) => void;
7
+ onErrout: (msg: string) => void;
8
+ stdoutReadline: readline.Interface;
9
+ stderrReadline: readline.Interface;
10
+ dispose(): void;
11
+ };
12
+ export declare function attachReadline(p: ChildProcessWithoutNullStreams, onStdout: any, onErrout: any): {
13
+ stdoutReadline: readline.Interface;
14
+ stderrReadline: readline.Interface;
15
+ dispose: () => void;
16
+ };
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.attachReadline = attachReadline;
7
+ exports.creatLogcat = creatLogcat;
8
+ var _readline = _interopRequireDefault(require("readline"));
9
+ var _adb = require("@miwt/adb");
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ function creatLogcat(sn) {
12
+ let onStdout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : console.log;
13
+ let onErrout = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : console.log;
14
+ let p = arguments.length > 3 ? arguments[3] : undefined;
15
+ let rls = arguments.length > 4 ? arguments[4] : undefined;
16
+ const logcatProcess = p || (0, _adb.spawnAdbCmd)('adb', ['-s', sn, 'logcat']);
17
+ const readlines = rls || attachReadline(logcatProcess, onStdout, onErrout);
18
+ return {
19
+ ...readlines,
20
+ logcatProcess,
21
+ onStdout,
22
+ onErrout
23
+ };
24
+ }
25
+ function attachReadline(p, onStdout, onErrout) {
26
+ let stdoutReadline;
27
+ let stderrReadline;
28
+
29
+ // 利用 readline 接口可解决子进程日志换行的问题
30
+ if (p.stdout) {
31
+ stdoutReadline = _readline.default.createInterface({
32
+ input: p.stdout
33
+ });
34
+ stdoutReadline.on('line', str => {
35
+ onStdout(str);
36
+ });
37
+ p.stdout.on('close', () => {
38
+ stdoutReadline?.close();
39
+ stdoutReadline = undefined;
40
+ });
41
+ }
42
+ if (p.stderr) {
43
+ stderrReadline = _readline.default.createInterface({
44
+ input: p.stderr
45
+ });
46
+ stderrReadline.on('line', str => {
47
+ onErrout(str);
48
+ });
49
+ p.stderr.on('close', () => {
50
+ stderrReadline?.close();
51
+ });
52
+ }
53
+ function dispose() {
54
+ stdoutReadline?.close();
55
+ stderrReadline?.close();
56
+ stdoutReadline = undefined;
57
+ stderrReadline = undefined;
58
+ }
59
+ p.on('exit', () => {
60
+ dispose();
61
+ });
62
+ return {
63
+ stdoutReadline,
64
+ stderrReadline,
65
+ dispose
66
+ };
67
+ }
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@aiot-toolkit/emulator",
3
- "version": "2.0.3-beta.7",
3
+ "version": "2.0.3-beta.8",
4
4
  "description": "vela emulator tool.",
5
5
  "homepage": "",
6
6
  "license": "ISC",
7
7
  "main": "lib/index.js",
8
+ "types": "lib/index.d.ts",
8
9
  "directories": {
9
10
  "lib": "lib",
10
11
  "test": "__tests__"
@@ -35,20 +36,20 @@
35
36
  "emulator"
36
37
  ],
37
38
  "dependencies": {
38
- "@aiot-toolkit/aiotpack": "2.0.3-beta.7",
39
- "@aiot-toolkit/shared-utils": "2.0.3-beta.7",
39
+ "@aiot-toolkit/shared-utils": "2.0.3-beta.8",
40
40
  "@miwt/adb": "^0.9.0",
41
+ "adm-zip": "^0.5.16",
41
42
  "dayjs": "^1.11.12",
42
43
  "find-process": "^1.4.7",
43
- "fs-extra": "^11.2.0",
44
+ "get-port": "^7.1.0",
44
45
  "ini": "^4.1.3",
46
+ "ipull": "^3.6.2",
45
47
  "portfinder": "^1.0.32",
46
- "semver": "^7.6.3",
47
- "ws": "^8.18.0"
48
+ "semver": "^7.6.3"
48
49
  },
49
50
  "devDependencies": {
50
- "@types/fs-extra": "^11.0.4",
51
+ "@types/adm-zip": "^0.5.5",
51
52
  "@types/ini": "^4.1.1"
52
53
  },
53
- "gitHead": "9621c52866d7bb1dc23110c4c9cc772b6169b682"
54
+ "gitHead": "1b1be0a8f4e40978a221fd7dbab4c9a2c168be1e"
54
55
  }
@@ -1,28 +0,0 @@
1
- import { IAvdParams, IAvdResourcePaths } from '../typing/Avd';
2
- declare class VelaAvdCls {
3
- private avdHome;
4
- private sdkHome;
5
- constructor(avdResourcePaths: IAvdResourcePaths);
6
- /**
7
- * 创建Vela端的AVD,统一保存在.android目录下
8
- * 1. 创建.android/advancedFeatures.ini文件
9
- * 2. 创建.android/${avdName}.ini文件
10
- * 3. 创建.android/${avdName}.avd/config.ini文件
11
- * @param avdParams AVD参数,宽高、绑定的镜像路径等
12
- * @returns
13
- */
14
- createVelaAvd(avdParams: IAvdParams): boolean;
15
- /** 根据AVD名字获取模拟器的详细信息 */
16
- getVelaAvdInfo(avdName: string): IAvdParams;
17
- /** 根据名字删除AVD */
18
- deleteVelaAvd(avdName: string): boolean;
19
- /** 获取已经创建的模拟器列表 */
20
- getVelaAvdList(): IAvdParams[];
21
- /** 获取模拟器皮肤列表 */
22
- getVelaSkinList(): string[];
23
- /** 自定义模拟器的镜像目录 */
24
- customImageDir(avdName: string, target: string): void;
25
- /** 重置自定义的镜像目录 */
26
- resetImageDir(avdName: string): void;
27
- }
28
- export default VelaAvdCls;
package/lib/avd/index.js DELETED
@@ -1,173 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const ColorConsole_1 = __importDefault(require("@aiot-toolkit/shared-utils/lib/ColorConsole"));
7
- const fs_1 = __importDefault(require("fs"));
8
- const os_1 = __importDefault(require("os"));
9
- const path_1 = __importDefault(require("path"));
10
- const ini_1 = require("ini");
11
- const constants_1 = require("../emulatorutil/constants");
12
- const Avd_1 = require("../typing/Avd");
13
- const EAvdParamsToIni = {
14
- arm: {
15
- abiType: 'armeabi-v7a'
16
- },
17
- arm64: {
18
- abiType: 'arm64-v8a'
19
- }
20
- };
21
- class VelaAvdCls {
22
- constructor(avdResourcePaths) {
23
- const { avdHome, sdkHome } = avdResourcePaths;
24
- this.avdHome = avdHome || constants_1.defaultAvdHome;
25
- this.sdkHome = sdkHome || constants_1.defaultSDKHome;
26
- if (!fs_1.default.existsSync(this.avdHome)) {
27
- fs_1.default.mkdirSync(this.avdHome, { recursive: true });
28
- }
29
- }
30
- /**
31
- * 创建Vela端的AVD,统一保存在.android目录下
32
- * 1. 创建.android/advancedFeatures.ini文件
33
- * 2. 创建.android/${avdName}.ini文件
34
- * 3. 创建.android/${avdName}.avd/config.ini文件
35
- * @param avdParams AVD参数,宽高、绑定的镜像路径等
36
- * @returns
37
- */
38
- createVelaAvd(avdParams) {
39
- // 在.android下创建advancedFeatures.ini文件
40
- const advancedFeaturesIni = path_1.default.resolve(os_1.default.homedir(), '.android/advancedFeatures.ini');
41
- if (!fs_1.default.existsSync(advancedFeaturesIni)) {
42
- const iniSourcePath = path_1.default.join(__dirname, '../static/advancedFeatures.ini');
43
- fs_1.default.copyFileSync(iniSourcePath, advancedFeaturesIni);
44
- }
45
- const { avdName, avdArch, avdWidth, avdHeight, avdSkin, avdImagePath = constants_1.defaultImageHome } = avdParams;
46
- const avdDir = path_1.default.resolve(this.avdHome, `${avdName}.avd`);
47
- const avdIni = path_1.default.resolve(this.avdHome, `${avdName}.ini`);
48
- const avdConfigIni = path_1.default.resolve(avdDir, 'config.ini');
49
- const nuttxAvdIniContent = `path=${avdDir}\npath.rel=avd${path_1.default.sep}${avdName}.avd`;
50
- const abiType = EAvdParamsToIni[avdArch]['abiType'];
51
- const configIniJson = JSON.parse(fs_1.default.readFileSync(path_1.default.join(__dirname, '../static/avdConfigIni.json'), 'utf-8'));
52
- configIniJson['AvdId'] = avdName;
53
- configIniJson['abi.type'] = abiType;
54
- configIniJson['avd.ini.displayname'] = avdName;
55
- configIniJson['hw.cpu.arch'] = avdArch;
56
- if (avdSkin) {
57
- delete configIniJson['hw.lcd.height'];
58
- delete configIniJson['hw.lcd.width'];
59
- configIniJson['skin.dynamic'] = 'yes';
60
- configIniJson['skin.name'] = avdSkin;
61
- configIniJson['skin.path'] = path_1.default.resolve(this.sdkHome, 'skins', avdSkin);
62
- }
63
- else {
64
- configIniJson['hw.lcd.height'] = avdHeight;
65
- configIniJson['hw.lcd.width'] = avdWidth;
66
- configIniJson['skin.dynamic'] = 'no';
67
- delete configIniJson['skin.name'];
68
- delete configIniJson['skin.path'];
69
- }
70
- configIniJson['image.sysdir.1'] = avdImagePath;
71
- try {
72
- fs_1.default.mkdirSync(avdDir, { recursive: true });
73
- // 写入Vela_Virtual_Device.ini文件
74
- fs_1.default.writeFileSync(avdIni, nuttxAvdIniContent);
75
- // 写入Vela_Virtual_Device.avd/config.ini文件
76
- fs_1.default.writeFileSync(avdConfigIni, (0, ini_1.stringify)(configIniJson));
77
- return true;
78
- }
79
- catch (e) {
80
- throw `createVelaAvd: ${e.message}`;
81
- }
82
- }
83
- /** 根据AVD名字获取模拟器的详细信息 */
84
- getVelaAvdInfo(avdName) {
85
- const avdInfo = {
86
- avdName,
87
- avdArch: Avd_1.IAvdArchType.arm,
88
- avdHeight: '',
89
- avdWidth: '',
90
- avdSkin: '',
91
- avdImagePath: ''
92
- };
93
- const currAvdDir = path_1.default.resolve(this.avdHome, `${avdName}.avd`);
94
- const configIni = path_1.default.resolve(currAvdDir, 'config.ini');
95
- try {
96
- const contents = fs_1.default.readFileSync(configIni, 'utf-8');
97
- const config = (0, ini_1.parse)(contents);
98
- avdInfo.avdArch = config['hw.cpu.arch'];
99
- avdInfo.avdHeight = config['hw.lcd.height'];
100
- avdInfo.avdWidth = config['hw.lcd.width'];
101
- avdInfo.avdSkin = config['skin.name'];
102
- avdInfo.avdImagePath = config['image.sysdir.1'];
103
- avdInfo.customImagePath = config['image.sysdir.2'];
104
- return avdInfo;
105
- }
106
- catch (err) {
107
- ColorConsole_1.default.log(`getVelaAvdInfo: ${err.message}`);
108
- return avdInfo;
109
- }
110
- }
111
- /** 根据名字删除AVD */
112
- deleteVelaAvd(avdName) {
113
- const avdDir = path_1.default.resolve(this.avdHome, `${avdName}.avd`);
114
- const avdIni = path_1.default.resolve(this.avdHome, `${avdName}.ini`);
115
- try {
116
- fs_1.default.rmSync(avdDir, { recursive: true, force: true });
117
- fs_1.default.rmSync(avdIni, { force: true });
118
- return true;
119
- }
120
- catch (e) {
121
- return false;
122
- }
123
- }
124
- /** 获取已经创建的模拟器列表 */
125
- getVelaAvdList() {
126
- const avdList = [];
127
- const files = fs_1.default.readdirSync(this.avdHome);
128
- const regex = /^(Vela[\d\D]*)\.avd$/;
129
- for (const fileName of files) {
130
- const matcher = fileName.match(regex);
131
- if (matcher) {
132
- const avdName = matcher[1];
133
- const avdInfo = this.getVelaAvdInfo(avdName);
134
- avdList.push(avdInfo);
135
- }
136
- }
137
- return avdList;
138
- }
139
- /** 获取模拟器皮肤列表 */
140
- getVelaSkinList() {
141
- try {
142
- const skinList = [];
143
- const skinHome = path_1.default.resolve(this.sdkHome, 'skins');
144
- let files = fs_1.default.readdirSync(skinHome);
145
- for (const fileName of files) {
146
- !fileName.startsWith('.') && skinList.push(fileName);
147
- }
148
- return skinList;
149
- }
150
- catch (e) {
151
- return [];
152
- }
153
- }
154
- /** 自定义模拟器的镜像目录 */
155
- customImageDir(avdName, target) {
156
- const currAvdDir = path_1.default.resolve(this.avdHome, `${avdName}.avd`);
157
- const configIni = path_1.default.resolve(currAvdDir, 'config.ini');
158
- const contents = fs_1.default.readFileSync(configIni, 'utf-8');
159
- const config = (0, ini_1.parse)(contents);
160
- config['image.sysdir.2'] = target;
161
- fs_1.default.writeFileSync(configIni, (0, ini_1.stringify)(config));
162
- }
163
- /** 重置自定义的镜像目录 */
164
- resetImageDir(avdName) {
165
- const currAvdDir = path_1.default.resolve(this.avdHome, `${avdName}.avd`);
166
- const configIni = path_1.default.resolve(currAvdDir, 'config.ini');
167
- const contents = fs_1.default.readFileSync(configIni, 'utf-8');
168
- const config = (0, ini_1.parse)(contents);
169
- delete config['image.sysdir.2'];
170
- fs_1.default.writeFileSync(configIni, (0, ini_1.stringify)(config));
171
- }
172
- }
173
- exports.default = VelaAvdCls;
@@ -1,9 +0,0 @@
1
- import { IStartOptions } from '../typing/Instance';
2
- declare class EmulatorCmd {
3
- static startOptions: IStartOptions | undefined;
4
- static createMiwerCmd(options: IStartOptions, sdkHome: string, avdHome: string): string | undefined;
5
- static createDevCmd(options: IStartOptions, sdkHome: string, avdHome: string): string | undefined;
6
- static createPreCmd(options: IStartOptions, sdkHome: string, avdHome: string): string[] | undefined;
7
- static getEmulatorBinPath(sdkHome: string): string;
8
- }
9
- export default EmulatorCmd;
@@ -1,226 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const ColorConsole_1 = __importDefault(require("@aiot-toolkit/shared-utils/lib/ColorConsole"));
7
- const fs_extra_1 = __importDefault(require("fs-extra"));
8
- const path_1 = __importDefault(require("path"));
9
- const avd_1 = __importDefault(require("../avd"));
10
- const utils_1 = require("../utils");
11
- const os_1 = __importDefault(require("os"));
12
- const dayjs_1 = __importDefault(require("dayjs"));
13
- const constants_1 = require("./constants");
14
- class EmulatorCmd {
15
- static createMiwerCmd(options, sdkHome, avdHome) {
16
- var _a;
17
- this.startOptions = options;
18
- const { avdName, devtool } = options;
19
- // 获取emulator bin的绝对路径
20
- const emulatorBin = this.getEmulatorBinPath(sdkHome);
21
- ColorConsole_1.default.log(`### Emulator ### emulator path: ${emulatorBin}`);
22
- // 获取vela镜像的绝对路径
23
- const velaAvdCls = new avd_1.default({
24
- sdkHome: sdkHome,
25
- avdHome: avdHome
26
- });
27
- const avdInfo = velaAvdCls.getVelaAvdInfo(avdName);
28
- const { avdArch, avdImagePath, customImagePath } = avdInfo;
29
- ColorConsole_1.default.log(`### Emulator ### adb port: ${options.adbPort}`);
30
- if (!avdImagePath) {
31
- ColorConsole_1.default.throw(`### Emulator ### Unable to find vela image via avd`);
32
- return undefined;
33
- }
34
- const nuttxBinPath = path_1.default.resolve(customImagePath || avdImagePath, 'nuttx');
35
- ColorConsole_1.default.log(`### Emulator ### nuttx path: ${nuttxBinPath}`);
36
- // 端口映射
37
- let portMappingStr = ``;
38
- if (devtool) {
39
- portMappingStr += `-network-user-mode-options hostfwd=tcp:127.0.0.1:${options.debugPort}-10.0.2.15:101`;
40
- }
41
- // 设备挂载节点
42
- const systemImageBin = path_1.default.resolve(avdImagePath, 'vela_resource.bin'); // 只读
43
- const dataImageBin = path_1.default.resolve(avdImagePath, 'vela_data.bin'); // 可读可写
44
- const coreBin = path_1.default.resolve(avdImagePath, 'coredump.core'); // 只读
45
- // 复制可写文件到AVD目录下(多模拟器实例时需要)
46
- const dataImageBinInAvd = path_1.default.join(avdHome, `${avdName}.avd`, 'vela_data.bin');
47
- if (!fs_extra_1.default.existsSync(dataImageBinInAvd)) {
48
- // vela_data.bin不存在时直接copy
49
- fs_extra_1.default.copyFileSync(dataImageBin, dataImageBinInAvd);
50
- }
51
- else {
52
- // vela_data.bin存在时,如果.export里的时间晚于avd里的时候,说明更新了镜像,需要重新copy
53
- const statsInAvd = fs_extra_1.default.statSync(dataImageBinInAvd);
54
- const stats = fs_extra_1.default.statSync(dataImageBin);
55
- if ((0, dayjs_1.default)(stats.mtime).isAfter(statsInAvd.mtime)) {
56
- fs_extra_1.default.copyFileSync(dataImageBin, dataImageBinInAvd);
57
- }
58
- }
59
- // 挂载节点配置,只读文件加入read-only标识
60
- const imageMountStr = `-drive index=0,id=system,if=none,format=raw,file=${systemImageBin},read-only \
61
- -device virtio-blk-device,bus=virtio-mmio-bus.0,drive=system \
62
- -drive index=1,id=userdata,if=none,format=raw,file=${dataImageBinInAvd} \
63
- -device virtio-blk-device,bus=virtio-mmio-bus.1,drive=userdata \
64
- -drive index=2,id=vendor,if=none,format=raw,file=${coreBin},read-only \
65
- -device virtio-blk-device,bus=virtio-mmio-bus.4,drive=vendor \
66
- -device virtio-snd,bus=virtio-mmio-bus.2 -allow-host-audio -semihosting`;
67
- // grpc配置
68
- let windowStr = '';
69
- let grpcStr = '';
70
- if ((_a = this.startOptions) === null || _a === void 0 ? void 0 : _a.grpcPort) {
71
- windowStr = '-qt-hide-window';
72
- grpcStr = ` -idle-grpc-timeout 300 -grpc ${this.startOptions.grpcPort}`;
73
- }
74
- // 启动模拟器的命令和参数
75
- const cmd = `${emulatorBin} -nuttx -avd ${avdName} -port ${options.adbPort} -avd-arch ${avdArch} -show-kernel -kernel ${nuttxBinPath} ${portMappingStr} ${windowStr} ${grpcStr} -qemu ${imageMountStr}`;
76
- return cmd;
77
- }
78
- static createDevCmd(options, sdkHome, avdHome) {
79
- var _a;
80
- this.startOptions = options;
81
- const { avdName, devtool } = options;
82
- const emulatorBin = this.getEmulatorBinPath(sdkHome);
83
- ColorConsole_1.default.log(`### Emulator ### emulator path: ${emulatorBin}`);
84
- const velaAvdCls = new avd_1.default({
85
- sdkHome: sdkHome,
86
- avdHome: avdHome
87
- });
88
- const avdInfo = velaAvdCls.getVelaAvdInfo(avdName);
89
- const { avdArch, avdImagePath, customImagePath } = avdInfo;
90
- ColorConsole_1.default.log(`### Emulator ### adb port: ${options.adbPort}`);
91
- if (!avdImagePath) {
92
- ColorConsole_1.default.throw(`### Emulator ### Unable to find vela image via avd`);
93
- return undefined;
94
- }
95
- const nuttxBinPath = path_1.default.resolve(customImagePath || avdImagePath, 'nuttx');
96
- ColorConsole_1.default.log(`### Emulator ### nuttx path: ${nuttxBinPath}`);
97
- // 端口映射
98
- let portMappingStr = ``;
99
- if (devtool) {
100
- portMappingStr += `-network-user-mode-options hostfwd=tcp:127.0.0.1:${options.debugPort}-10.0.2.15:101`;
101
- }
102
- // 文件系统配置,第一次使用fatfs镜像挂载,后续使用adb push更新应用
103
- const systemImageBin = path_1.default.join(avdImagePath, 'system.img');
104
- const dataImageBin = path_1.default.join(avdImagePath, 'data.img');
105
- // 复制可写文件到AVD目录下(多模拟器实例时需要)
106
- const dataImageBinInAvd = path_1.default.join(avdHome, `${avdName}.avd`, 'data.img');
107
- if (!fs_extra_1.default.existsSync(dataImageBinInAvd)) {
108
- // data.img不存在时直接copy
109
- fs_extra_1.default.copyFileSync(dataImageBin, dataImageBinInAvd);
110
- }
111
- else {
112
- // data.img存在时,如果.export里的时间晚于avd里的时候,说明更新了镜像,需要重新copy
113
- const statsInAvd = fs_extra_1.default.statSync(dataImageBinInAvd);
114
- const stats = fs_extra_1.default.statSync(dataImageBin);
115
- if ((0, dayjs_1.default)(stats.mtime).isAfter(statsInAvd.mtime)) {
116
- fs_extra_1.default.copyFileSync(dataImageBin, dataImageBinInAvd);
117
- }
118
- }
119
- // 复制可写文件到AVD目录下(多模拟器实例时需要)
120
- const systemImageBinInAvd = path_1.default.join(avdHome, `${avdName}.avd`, 'system.img');
121
- if (!fs_extra_1.default.existsSync(systemImageBinInAvd)) {
122
- // data.img不存在时直接copy
123
- fs_extra_1.default.copyFileSync(systemImageBin, systemImageBinInAvd);
124
- }
125
- else {
126
- // data.img存在时,如果.export里的时间晚于avd里的时候,说明更新了镜像,需要重新copy
127
- const statsInAvd = fs_extra_1.default.statSync(systemImageBinInAvd);
128
- const stats = fs_extra_1.default.statSync(systemImageBin);
129
- if ((0, dayjs_1.default)(stats.mtime).isAfter(statsInAvd.mtime)) {
130
- fs_extra_1.default.copyFileSync(systemImageBin, systemImageBinInAvd);
131
- }
132
- }
133
- // 复制可写文件到AVD目录下(多模拟器实例时需要)
134
- // const nuttxBinInAvd = path.join(this.avdHome, `${avdName}.avd`, 'nuttx')
135
- // if (!fs.existsSync(nuttxBinInAvd)) {
136
- // // data.img不存在时直接copy
137
- // fs.copyFileSync(nuttxBinPath, nuttxBinInAvd)
138
- // } else {
139
- // // data.img存在时,如果.export里的时间晚于avd里的时候,说明更新了镜像,需要重新copy
140
- // const statsInAvd = fs.statSync(nuttxBinInAvd)
141
- // const stats = fs.statSync(nuttxBinPath)
142
- // if (dayjs(stats.mtime).isAfter(statsInAvd.mtime)) {
143
- // fs.copyFileSync(nuttxBinPath, nuttxBinInAvd)
144
- // }
145
- // }
146
- const imageMountStr = `-drive index=0,id=system,if=none,format=raw,file=${systemImageBinInAvd} \
147
- -device virtio-blk-device,bus=virtio-mmio-bus.0,drive=system \
148
- -drive index=1,id=userdata,if=none,format=raw,file=${dataImageBinInAvd} \
149
- -device virtio-blk-device,bus=virtio-mmio-bus.1,drive=userdata \
150
- -device virtio-snd,bus=virtio-mmio-bus.2 -allow-host-audio -semihosting`;
151
- // grpc配置
152
- let windowStr = '';
153
- let grpcStr = '';
154
- if ((_a = this.startOptions) === null || _a === void 0 ? void 0 : _a.grpcPort) {
155
- windowStr = '-qt-hide-window';
156
- grpcStr = ` -idle-grpc-timeout 300 -grpc ${this.startOptions.grpcPort}`;
157
- }
158
- // 启动模拟器的命令和参数
159
- const cmd = `${emulatorBin} -nuttx -avd ${avdName} -port ${options.adbPort} -avd-arch ${avdArch} -show-kernel -kernel ${nuttxBinPath} ${portMappingStr} ${windowStr} ${grpcStr} -qemu ${imageMountStr}`;
160
- return cmd;
161
- }
162
- static createPreCmd(options, sdkHome, avdHome) {
163
- this.startOptions = options;
164
- const { avdName, devtool } = options;
165
- // 获取emulator bin的绝对路径
166
- const emulatorBin = this.getEmulatorBinPath(sdkHome);
167
- ColorConsole_1.default.log(`### Emulator ### emulator path: ${emulatorBin}`);
168
- // 获取vela镜像的绝对路径
169
- const velaAvdCls = new avd_1.default({
170
- sdkHome: sdkHome,
171
- avdHome: avdHome
172
- });
173
- const avdInfo = velaAvdCls.getVelaAvdInfo(avdName);
174
- const { avdArch, avdImagePath, customImagePath } = avdInfo;
175
- ColorConsole_1.default.log(`### Emulator ### adb port: ${options.adbPort}`);
176
- if (!avdImagePath) {
177
- ColorConsole_1.default.throw(`### Emulator ### Unable to find vela image via avd`);
178
- return undefined;
179
- }
180
- const nuttxBinPath = path_1.default.resolve(customImagePath || avdImagePath, 'nuttx');
181
- ColorConsole_1.default.log(`### Emulator ### nuttx path: ${nuttxBinPath}`);
182
- // 端口映射,adb端口和debug端口
183
- let portMappingStr = `user,id=u1,hostfwd=tcp:127.0.0.1:${options.adbPort}-10.0.2.15:5555`;
184
- if (devtool) {
185
- ColorConsole_1.default.log(`### Emulator ### debug port: ${options.debugPort}`);
186
- portMappingStr += `,hostfwd=tcp:127.0.0.1:${options.debugPort}-10.0.2.15:101`;
187
- }
188
- ColorConsole_1.default.log(`### Emulator ### Start qemu with TCP: ${portMappingStr}`);
189
- // vnc配置
190
- let noWindow = false;
191
- let vncStr = '';
192
- if (options.grpcPort) {
193
- noWindow = true;
194
- const portSuffix = options.grpcPort - constants_1.defaultVncPort;
195
- vncStr = `-vnc :${portSuffix}`;
196
- }
197
- // 启动goldfish的命令和参数
198
- const spawnArgs = [
199
- emulatorBin,
200
- '-nuttx',
201
- '-avd',
202
- avdName,
203
- '-avd-arch',
204
- avdArch,
205
- '-show-kernel',
206
- '-kernel',
207
- nuttxBinPath,
208
- noWindow ? '-no-window' : '',
209
- '-qemu',
210
- vncStr,
211
- '-netdev',
212
- portMappingStr,
213
- '-device',
214
- 'virtio-net-device,netdev=u1,bus=virtio-mmio-bus.3'
215
- ];
216
- return spawnArgs;
217
- }
218
- static getEmulatorBinPath(sdkHome) {
219
- const osPlatform = os_1.default.platform();
220
- const arch = (0, utils_1.getSystemArch)();
221
- const platform = osPlatform === 'win32' ? 'windows' : osPlatform;
222
- const emulatorHome = path_1.default.resolve(sdkHome, 'emulator');
223
- return path_1.default.resolve(emulatorHome, `${platform}-${arch}`, 'emulator');
224
- }
225
- }
226
- exports.default = EmulatorCmd;
@@ -1,53 +0,0 @@
1
- import { ChildProcess } from 'child_process';
2
- import readline from 'readline';
3
- import { INewGoldfishInstanceParams, IStartOptions } from '../typing/Instance';
4
- import CommonInstance from './common';
5
- /**
6
- * OldGoldfishInstance
7
- * 针对 Vela开发版(dev, 0.0.2)的镜像
8
- */
9
- declare class OldGoldfishInstance extends CommonInstance {
10
- private host9pPort;
11
- v9fsProcess: ChildProcess | undefined;
12
- stdoutReadline: readline.Interface;
13
- stderrReadline: readline.Interface;
14
- constructor(params: INewGoldfishInstanceParams);
15
- /**
16
- * 1. 启动9p server
17
- * 2. 将打包好的rpk推到host的挂载目录
18
- * 3. 启动模拟器
19
- * 4. 模拟器启动成功后,adb连接模拟器
20
- * 5. 连接成功后,在模拟器中启动快应用
21
- */
22
- start(options: IStartOptions): Promise<void>;
23
- /**
24
- * 在模拟器中启动快应用(快应用都在模拟器的/data/app目录下)
25
- * 1. 是否为调试模式
26
- * 若是,在模拟器终端执行vapp app/${packageName} &
27
- * 若否,在模拟器终端执行vapp --jsdebugger=10.0.2.15:101 app/${packageName} &
28
- */
29
- startupQuickApp(options: IStartOptions): void;
30
- /** host启动9pServer
31
- * 作用是将本地的quickappMountDir目录挂载到模拟器的/data目录
32
- */
33
- ensure9pServerRunnning(): Promise<void>;
34
- /**
35
- * 启动模拟器
36
- * 1. 通过options生成模拟器的启动命令
37
- * 2. 执行启动命令
38
- * 3. 判断模拟器是否启动成功
39
- * 3.1 若disableNSH=true,输出流中匹配到/quickapp_rpk_installer_init|rpk installer init done/,认为模拟器启动成功了
40
- * 3.2 若disableNSH=false,认为8s过后模拟器启动成功了
41
- * @param options
42
- * @returns
43
- */
44
- startGoldfish(options: IStartOptions): Promise<void>;
45
- /**
46
- * 推送文件到本地的${sdkHome}/qa/app/${packageName}目录
47
- * @param sourceRoot 源目录
48
- */
49
- pushRpk(sourceRoot: string): Promise<void>;
50
- /** 停止模拟器并释放相关资源 */
51
- stop(): Promise<void>;
52
- }
53
- export default OldGoldfishInstance;