@aiot-toolkit/emulator 2.0.5-beta.23 → 2.0.5-beta.24

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.
@@ -57,14 +57,14 @@ const VelaImageVersionList = exports.VelaImageVersionList = [{
57
57
  label: 'vela-miwear-watch-5.0',
58
58
  description: '适用于手表/手环的,带表盘的 vela 5.0 镜像,不可自定义模拟器尺寸',
59
59
  value: _Vvd.VelaImageType.VELA_MIWEAR_WATCH_5,
60
- time: '20250626',
60
+ time: '20250716',
61
61
  hide: false,
62
62
  icon: ''
63
63
  }, {
64
64
  label: 'vela-watch-5.0',
65
65
  description: '适用于手表/手环的,不带表盘的 vela 5.0 镜像,可自定义模拟器尺寸',
66
66
  value: _Vvd.VelaImageType.VELA_WATCH_5,
67
- time: '20250626',
67
+ time: '20250716',
68
68
  hide: false,
69
69
  icon: ''
70
70
  }, {
@@ -93,7 +93,7 @@ const EmulatorEnvVersion = exports.EmulatorEnvVersion = {
93
93
  name: '模拟器资源版本管理',
94
94
  [_Vvd.SDKParts.EMULATOR]: '0.1.0',
95
95
  [_Vvd.SDKParts.QA]: '0.0.1',
96
- [_Vvd.SDKParts.SKINS]: '0.0.9',
96
+ [_Vvd.SDKParts.SKINS]: '0.0.10',
97
97
  [_Vvd.SDKParts.SYSTEM_IMAGES]: VelaImageVersionList[0].time,
98
98
  [_Vvd.SDKParts.MODEM_SIMULATOR]: '0.0.3'
99
99
  };
@@ -26,7 +26,10 @@ declare abstract class CommonEmulatorInstance {
26
26
  logger: (log: string) => void;
27
27
  constructor(params: IEmulatorInstanceParams);
28
28
  /** 安装应用,留给子类实现 */
29
- abstract install(rpkPath: string, packageName: string): Promise<void>;
29
+ abstract install(rpkPath: string, options?: {
30
+ packageName?: string;
31
+ size?: number;
32
+ }): Promise<void>;
30
33
  /** 卸载应用,留给子类实现 */
31
34
  abstract uninstall(packageName: string): Promise<void>;
32
35
  /** 重启应用 */
@@ -12,6 +12,7 @@ var _utils = require("../utils");
12
12
  var _logcat = require("../vvd/logcat");
13
13
  var _emulatorutil = require("../emulatorutil");
14
14
  var _shared = require("../shared");
15
+ var _fs = _interopRequireDefault(require("fs"));
15
16
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
16
17
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
17
18
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -120,7 +121,10 @@ class CommonEmulatorInstance {
120
121
  async pushAndInstall(rpkPath, appName) {
121
122
  const targetPath = await this.pushRpk(rpkPath, appName);
122
123
  try {
123
- await this.install(targetPath, appName);
124
+ await this.install(targetPath, {
125
+ packageName: appName,
126
+ size: _fs.default.statSync(rpkPath).size
127
+ });
124
128
  } catch (error) {
125
129
  let timer;
126
130
  if (error === _shared.RpkInstallFailedReason.Busy) {
@@ -128,7 +132,7 @@ class CommonEmulatorInstance {
128
132
  await new Promise((resolve, rejcet) => {
129
133
  timer = setTimeout(() => {
130
134
  this.pushAndInstall(rpkPath, appName).then(resolve).catch(rejcet);
131
- }, 5000);
135
+ }, 3000);
132
136
  });
133
137
  } else {
134
138
  clearTimeout(timer);
@@ -9,7 +9,10 @@ declare class GoldfishInstance extends CommonEmulatorInstance {
9
9
  imageType: VelaImageType;
10
10
  static appDir: string;
11
11
  static emulatorStartedFlag: RegExp;
12
- install(rpkPath: string, appPackageName?: string): Promise<void>;
12
+ install(rpkPath: string, opt: {
13
+ packageName?: string;
14
+ size?: number;
15
+ }): Promise<void>;
13
16
  /**
14
17
  * 在模拟器中启动快应用
15
18
  * 通过vapp命令启动,调试时需额外配置--jsdebugger参数
@@ -23,10 +23,10 @@ class GoldfishInstance extends _common.default {
23
23
  imageType = (() => _Vvd.VelaImageType.DEV)();
24
24
  static appDir = '/data/app';
25
25
  static emulatorStartedFlag = /(NSH)/;
26
- async install(rpkPath, appPackageName) {
26
+ async install(rpkPath, opt) {
27
27
  // 基于 vapp 启动的应用只需要将 rpk 解压到指定的目录下
28
- rpkPath = rpkPath || `${this.appDir}/${appPackageName}.rpk`;
29
- const targetPath = `${this.appDir}/${appPackageName}`;
28
+ rpkPath = rpkPath || `${this.appDir}/${opt.packageName}.rpk`;
29
+ const targetPath = `${this.appDir}/${opt.packageName}`;
30
30
  const mkdirCmd = `adb -s ${this.sn} shell mkdir ${targetPath}`;
31
31
  this.logger(`Excuting: ${mkdirCmd}`);
32
32
  await adbMiwt.execAdbCmdAsync(mkdirCmd);
@@ -14,7 +14,10 @@ declare class MiwearInstance extends CommonEmulatorInstance {
14
14
  * 使用 pm 安装快应用
15
15
  * @param targeRpk 快应用的rpk文件路径
16
16
  */
17
- install(targeRpk: string): Promise<void>;
17
+ install(targeRpk: string, options?: {
18
+ packageName?: string;
19
+ size?: number;
20
+ }): Promise<void>;
18
21
  /**
19
22
  * 使用 pm 卸载快应用
20
23
  * @param packageName 快应用的包名
@@ -32,7 +32,7 @@ class MiwearInstance extends _common.default {
32
32
  * 使用 pm 安装快应用
33
33
  * @param targeRpk 快应用的rpk文件路径
34
34
  */
35
- async install(targeRpk) {
35
+ async install(targeRpk, options) {
36
36
  const installCmd = `adb -s ${this.sn} shell pm install ${targeRpk}`;
37
37
  this.logger(`Excuting: ${installCmd}`);
38
38
  adbMiwt.execAdbCmd(installCmd);
@@ -61,11 +61,17 @@ class MiwearInstance extends _common.default {
61
61
  reject(_shared.RpkInstallFailedReason.Busy);
62
62
  }
63
63
  };
64
+ function getTimeout(size) {
65
+ if (!size) return 10 * 1000;
66
+ const mu = size / 1024 / 1024;
67
+ return mu < 1 ? 10 * 1000 : mu < 4 ? 60 * 1000 : 2 * 60 * 1000;
68
+ }
69
+ const timeout = getTimeout(options?.size);
64
70
  let timer = setTimeout(() => {
65
71
  this.stdoutReadline.off('line', func);
66
72
  this.logger(`Install to ${this.vvdName} ${targeRpk} timeout`);
67
73
  reject(_shared.RpkInstallFailedReason.Timeout);
68
- }, 1 * 60 * 1000);
74
+ }, timeout);
69
75
  this.stdoutReadline.on('line', func);
70
76
  this.stdoutReadline.on('close', () => {
71
77
  this.stdoutReadline.off('line', func);
@@ -7,7 +7,10 @@ declare class PreInstance extends CommonEmulatorInstance {
7
7
  imageType: VelaImageType;
8
8
  appDir: string;
9
9
  static emulatorStartedFlag: RegExp;
10
- install(rpkPath: string, appPackageName?: string): Promise<void>;
10
+ install(rpkPath: string, opt: {
11
+ packageName: string;
12
+ size?: number;
13
+ }): Promise<void>;
11
14
  uninstall(packageName: string): Promise<void>;
12
15
  /**
13
16
  * 在模拟器中启动快应用
@@ -17,10 +17,10 @@ class PreInstance extends _common.default {
17
17
  imageType = (() => _Vvd.VelaImageType.PRE)();
18
18
  appDir = '/data/quickapp/app';
19
19
  static emulatorStartedFlag = /(NSH)/;
20
- async install(rpkPath, appPackageName) {
20
+ async install(rpkPath, opt) {
21
21
  // 基于 vapp 启动的应用只需要将 rpk 解压到指定的目录下
22
- rpkPath = rpkPath || `${this.appDir}/${appPackageName}.rpk`;
23
- const targetPath = `${this.appDir}/${appPackageName}`;
22
+ rpkPath = rpkPath || `${this.appDir}/${opt.packageName}.rpk`;
23
+ const targetPath = `${this.appDir}/${opt.packageName}`;
24
24
  const mkdirCmd = `adb -s ${this.sn} shell mkdir ${targetPath}`;
25
25
  this.logger(`Excuting: ${mkdirCmd}`);
26
26
  await adbMiwt.execAdbCmdAsync(mkdirCmd);
@@ -14,7 +14,7 @@ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return
14
14
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
15
15
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
16
16
  class Vela5Instance extends _miwear.default {
17
- static emulatorStartedFlag = /adb_register_service/;
17
+ static emulatorStartedFlag = /booting completed|Boot completed/;
18
18
  static appStartedFlag = /Start main loop/;
19
19
  imageType = (() => _Vvd.VelaImageType.VELA_WATCH_5)();
20
20
  appDir = '/data/app';
@@ -23,10 +23,9 @@
23
23
  "hw.lcd.height": 466,
24
24
  "hw.lcd.width": 466,
25
25
  "hw.mainKeys": "no",
26
- "hw.ramSize": 512,
26
+ "hw.ramSize": 1024,
27
27
  "hw.sdCard": "no",
28
28
  "hw.sensors.orientation": "yes",
29
- "hw.sensors.proximity": "yes",
30
29
  "hw.trackBall": "no",
31
30
  "image.sysdir.2": "",
32
31
  "runtime.network.latency": "none",
@@ -36,11 +35,11 @@
36
35
  "skin.name": "",
37
36
  "skin.path": "",
38
37
  "hw.accelerometer": "yes",
39
- "hw.gyroscope ": "yes",
40
- "hw.sensors.magnetic_field ": "yes",
41
- "hw.sensors.temperature ": "yes",
42
- "hw.sensors.proximity ": "yes",
43
- "hw.sensors.light ": "yes",
44
- "hw.sensors.humidity ": "yes",
45
- "hw.sensors.heart_rate ": "yes"
38
+ "hw.gyroscope": "yes",
39
+ "hw.sensors.proximity": "yes",
40
+ "hw.sensors.magnetic_field": "yes",
41
+ "hw.sensors.temperature": "yes",
42
+ "hw.sensors.light": "yes",
43
+ "hw.sensors.humidity": "yes",
44
+ "hw.sensors.heart_rate": "yes"
46
45
  }
@@ -4,8 +4,7 @@ export interface IVvdResourcePaths {
4
4
  imageHome?: string;
5
5
  }
6
6
  export declare enum IVvdArchType {
7
- arm = "arm",
8
- arm64 = "arm64"
7
+ arm = "arm"
9
8
  }
10
9
  export declare enum VelaImageType {
11
10
  VELA_MIWEAR_MINISOUND_5 = "vela-miwear-minisound-5.0",
@@ -37,6 +36,7 @@ export interface EmulatorPart {
37
36
  height: string;
38
37
  x: string;
39
38
  y: string;
39
+ corner_radius: string;
40
40
  shape?: string;
41
41
  flavor?: string;
42
42
  density?: string;
package/lib/typing/Vvd.js CHANGED
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.VelaImageType = exports.VELAHOME = exports.SDKParts = exports.IVvdArchType = void 0;
7
7
  let IVvdArchType = exports.IVvdArchType = /*#__PURE__*/function (IVvdArchType) {
8
8
  IVvdArchType["arm"] = "arm";
9
- IVvdArchType["arm64"] = "arm64";
10
9
  return IVvdArchType;
11
10
  }({});
12
11
  let VelaImageType = exports.VelaImageType = /*#__PURE__*/function (VelaImageType) {
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @param mode Optional modifiers that specify the behavior of the copy operation. It is possible to create a mask consisting of the bitwise OR of two or more values (e.g. fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE)
3
+ */
4
+ export declare function copyDir(source: string, target: string, mode?: number): Promise<void>;
5
+ /**
6
+ * @param mode Optional modifiers that specify the behavior of the copy operation. It is possible to create a mask consisting of the bitwise OR of two or more values (e.g. fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE)
7
+ */
8
+ export declare function copyDirSync(source: string, target: string, mode?: number): void;
package/lib/utils/file.js CHANGED
@@ -1 +1,48 @@
1
- "use strict";
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.copyDir = copyDir;
7
+ exports.copyDirSync = copyDirSync;
8
+ var _path = _interopRequireDefault(require("path"));
9
+ var _promises = _interopRequireDefault(require("fs/promises"));
10
+ var _fs = _interopRequireDefault(require("fs"));
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
+ /**
13
+ * @param mode Optional modifiers that specify the behavior of the copy operation. It is possible to create a mask consisting of the bitwise OR of two or more values (e.g. fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE)
14
+ */
15
+ async function copyDir(source, target, mode) {
16
+ const entries = await _promises.default.readdir(source, {
17
+ withFileTypes: true
18
+ });
19
+ await _promises.default.mkdir(target, {
20
+ recursive: true
21
+ });
22
+ await Promise.all(entries.map(entry => {
23
+ const srcPath = _path.default.join(source, entry.name);
24
+ const destPath = _path.default.join(target, entry.name);
25
+ return entry.isDirectory() ? copyDir(srcPath, destPath, mode) : _promises.default.copyFile(srcPath, destPath, mode);
26
+ }));
27
+ }
28
+
29
+ /**
30
+ * @param mode Optional modifiers that specify the behavior of the copy operation. It is possible to create a mask consisting of the bitwise OR of two or more values (e.g. fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE)
31
+ */
32
+ function copyDirSync(source, target, mode) {
33
+ _fs.default.mkdirSync(target, {
34
+ recursive: true
35
+ });
36
+ const entries = _fs.default.readdirSync(source, {
37
+ withFileTypes: true
38
+ });
39
+ for (const entry of entries) {
40
+ const srcPath = _path.default.join(source, entry.name);
41
+ const destPath = _path.default.join(target, entry.name);
42
+ if (entry.isDirectory()) {
43
+ copyDirSync(srcPath, destPath, mode);
44
+ } else {
45
+ _fs.default.copyFileSync(srcPath, destPath, mode);
46
+ }
47
+ }
48
+ }
@@ -4,6 +4,7 @@ import { EmulatorConfig } from '../emulatorutil';
4
4
  import { findInstance } from '../instance';
5
5
  import type { DownloadFileOptions } from 'ipull';
6
6
  import GrpcEmulator from './grpc';
7
+ export declare const isHeadlessEnvironment: () => boolean;
7
8
  export declare class VvdManager {
8
9
  private vvdHome;
9
10
  private sdkHome;
@@ -19,7 +20,7 @@ export declare class VvdManager {
19
20
  * @returns
20
21
  */
21
22
  createVvd(vvdParams: IVvdParams): boolean;
22
- getVvdDir(vvdName: string): string;
23
+ getVvdDir(vvdName: string): any;
23
24
  /** 根据AVD名字获取模拟器的详细信息 */
24
25
  getVvdInfo(vvdName: string): IVvdParams;
25
26
  /** 根据名字删除AVD */
@@ -50,6 +51,7 @@ export declare class VvdManager {
50
51
  /** 重置自定义的镜像目录 */
51
52
  resetImageDir(vvdName: string): void;
52
53
  getEmulatorBinPath(sdkHome: string): string;
54
+ oldEmulatorMigrate(vvdName: string): Promise<void>;
53
55
  getVvdStartCmd(options: IStartOptions | IStartWithSerialPort): Promise<string>;
54
56
  startVvd(options: IStartOptions | IStartWithSerialPort): Promise<{
55
57
  coldBoot: boolean;
package/lib/vvd/index.js CHANGED
@@ -3,8 +3,9 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.VvdManager = void 0;
6
+ exports.isHeadlessEnvironment = exports.VvdManager = void 0;
7
7
  var _ColorConsole = _interopRequireDefault(require("@aiot-toolkit/shared-utils/lib/ColorConsole"));
8
+ var _promises = _interopRequireDefault(require("fs/promises"));
8
9
  var _fs = _interopRequireDefault(require("fs"));
9
10
  var _os = _interopRequireDefault(require("os"));
10
11
  var _path = _interopRequireDefault(require("path"));
@@ -26,6 +27,7 @@ var _logcat = require("./logcat");
26
27
  var _sharedUtils = require("@aiot-toolkit/shared-utils");
27
28
  var _ILog = require("@aiot-toolkit/shared-utils/lib/interface/ILog");
28
29
  var _grpc = require("./grpc");
30
+ var _file = require("../utils/file");
29
31
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
30
32
  // TODO: 升级构建工具支持 esm @xujunjie
31
33
  const getPort = (async () => {
@@ -42,6 +44,21 @@ const EAvdParamsToIni = {
42
44
  abiType: 'arm64-v8a'
43
45
  }
44
46
  };
47
+ const isHeadlessEnvironment = () => {
48
+ // 检查是否在 Docker 容器中
49
+ if (_fs.default.existsSync('/.dockerenv')) return true;
50
+
51
+ // 检查是否在 WSL 环境中
52
+ if (process.env.WSL_DISTRO_NAME) return true;
53
+
54
+ // 检查是否设置了 DISPLAY 环境变量(Linux)
55
+ if (process.platform === 'linux' && !process.env.DISPLAY) return true;
56
+
57
+ // 检查是否在 CI 环境中
58
+ if (process.env.CI) return true;
59
+ return false;
60
+ };
61
+ exports.isHeadlessEnvironment = isHeadlessEnvironment;
45
62
  class VvdManager {
46
63
  // 需要复制的文件
47
64
  binFiles = ['system.img', 'data.img', 'coredump.core', 'vela_data.bin', 'vela_resource.bin', 'vela_system.bin'];
@@ -144,10 +161,13 @@ class VvdManager {
144
161
  }
145
162
  }
146
163
  getVvdDir(vvdName) {
147
- // 模拟器有可能在 .vvd .avd 目录下
148
- let res = _path.default.resolve(this.vvdHome, `${vvdName}.vvd`);
149
- if (!_fs.default.existsSync(res)) res = _path.default.resolve(this.vvdHome, `${vvdName}.avd`);
150
- return res;
164
+ const maybe = [_path.default.join(this.vvdHome, `${vvdName}.ini`), _path.default.join(_os.default.homedir(), '.android', 'avd', `${vvdName}.ini`), _path.default.join(_os.default.homedir(), '.android', 'vvd', `${vvdName}.ini`)];
165
+ for (const file of maybe) {
166
+ if (_fs.default.existsSync(file)) {
167
+ return (0, _ini.parse)(_fs.default.readFileSync(file, 'utf-8')).path;
168
+ }
169
+ }
170
+ throw new Error(`VVD directory for ${vvdName} not found`);
151
171
  }
152
172
 
153
173
  /** 根据AVD名字获取模拟器的详细信息 */
@@ -333,6 +353,54 @@ class VvdManager {
333
353
  const emulatorHome = _path.default.resolve(sdkHome, 'emulator');
334
354
  return _path.default.resolve(emulatorHome, `${platform}-${arch}`, 'emulator');
335
355
  }
356
+
357
+ // 旧的模拟器迁移
358
+ async oldEmulatorMigrate(vvdName) {
359
+ const configIni = _path.default.join(this.getVvdDir(vvdName), 'config.ini');
360
+ const contents = await _promises.default.readFile(configIni, 'utf-8');
361
+ const config = (0, _ini.parse)(contents);
362
+ let needUpdate = false;
363
+
364
+ // 检查 ramsize 调整为 1024
365
+ if (config['hw.ramSize'] < 1024) {
366
+ needUpdate = true;
367
+ config['hw.ramSize'] = 1024;
368
+ }
369
+ // 检查皮肤路径
370
+ if (config['skin.path']?.includes('.export_dev/skins')) {
371
+ if (config['skin.path'].includes('.export_dev/skins/user')) {
372
+ // 自定义的皮肤,将自定义皮肤迁移到新的 sdk 目录中
373
+ const oldUserSkinDir = _path.default.join(_os.default.homedir(), '.export_dev/skins/user');
374
+ const newUserSkinDir = _path.default.join(this.sdkHome, 'skins', 'user');
375
+ const userSkins = await _promises.default.readdir(oldUserSkinDir, {
376
+ withFileTypes: true
377
+ });
378
+ for (const skin of userSkins) {
379
+ if (!skin.isDirectory()) continue;
380
+ const oldSkinPath = _path.default.join(oldUserSkinDir, skin.name);
381
+ const newSkinPath = _path.default.join(newUserSkinDir, skin.name);
382
+ if (!_fs.default.existsSync(newSkinPath)) {
383
+ await _promises.default.mkdir(newSkinPath, {
384
+ recursive: true
385
+ });
386
+ }
387
+ await (0, _file.copyDir)(oldSkinPath, newSkinPath);
388
+ }
389
+ }
390
+ needUpdate = true;
391
+ config['skin.path'] = config['skin.path'].replace('.export_dev/skins', '.vela/sdk/skins');
392
+ }
393
+
394
+ // 检查镜像路径
395
+ if (config['image.sysdir.2']?.includes('.export_dev/system-images')) {
396
+ needUpdate = true;
397
+ config['image.sysdir.2'] = config['image.sysdir.2'].replace('.export_dev/system-images', '.vela/sdk/system-images');
398
+ }
399
+ if (needUpdate) {
400
+ await _promises.default.writeFile(configIni, (0, _ini.stringify)(config));
401
+ _ColorConsole.default.log(`update ${vvdName} config.ini`);
402
+ }
403
+ }
336
404
  async getVvdStartCmd(options) {
337
405
  const vvdName = options.vvdName;
338
406
 
@@ -365,7 +433,11 @@ class VvdManager {
365
433
  const qemuOption = `-device virtio-snd,bus=virtio-mmio-bus.2 -allow-host-audio -semihosting`;
366
434
 
367
435
  // qt windows 配置
368
- const windowOption = options.qtHideWindow ? `-no-window` : '';
436
+ // docker,wls,等无界面平台上用 -no-window ,否则用 -qt-hide-window
437
+ // 使用 -no-window 时 extended control 不可用
438
+ // 在无界面平台上必须使用 -no-window 否则会报错 qt `Could not load the Qt platform plugin \"xcb\"
439
+ const noWindowOption = isHeadlessEnvironment() ? `-no-window` : '-qt-hide-window';
440
+ const windowOption = options.qtHideWindow ? noWindowOption : '';
369
441
  let grpcStr = options.grpcPort ? `-grpc ${options.grpcPort}` : '';
370
442
  let serialStr = ``;
371
443
  if (options.serialPort) {
@@ -379,6 +451,7 @@ class VvdManager {
379
451
  // 启动模拟器的命令和参数
380
452
  const cmd = `${emulatorBin} -vela -avd ${options.vvdName} ${serialStr} -show-kernel ${portMappingStr} ${windowOption} ${grpcStr} ${verboseOption} -qemu ${qemuOption}`;
381
453
  const vvdInfo = this.getVvdInfo(vvdName);
454
+ await this.oldEmulatorMigrate(vvdName);
382
455
  if (!vvdInfo.imageDir) {
383
456
  const errMsg = `${vvdName} is not supported`;
384
457
  _ColorConsole.default.throw(errMsg);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiot-toolkit/emulator",
3
- "version": "2.0.5-beta.23",
3
+ "version": "2.0.5-beta.24",
4
4
  "description": "vela emulator tool.",
5
5
  "homepage": "",
6
6
  "license": "ISC",
@@ -36,7 +36,7 @@
36
36
  "emulator"
37
37
  ],
38
38
  "dependencies": {
39
- "@aiot-toolkit/shared-utils": "2.0.5-beta.23",
39
+ "@aiot-toolkit/shared-utils": "2.0.5-beta.24",
40
40
  "@grpc/grpc-js": "^1.13.3",
41
41
  "@grpc/proto-loader": "^0.7.13",
42
42
  "@miwt/adb": "0.10.1",
@@ -53,5 +53,5 @@
53
53
  "@types/adm-zip": "^0.5.5",
54
54
  "@types/ini": "^4.1.1"
55
55
  },
56
- "gitHead": "f4991bcb0dcaab6853597ca07d21a7999649a1cc"
56
+ "gitHead": "9db5595088ce88b2530a20f9edae156e9026718e"
57
57
  }