@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.
- package/lib/emulatorutil/constants.js +3 -3
- package/lib/instance/common.d.ts +4 -1
- package/lib/instance/common.js +6 -2
- package/lib/instance/dev.d.ts +4 -1
- package/lib/instance/dev.js +3 -3
- package/lib/instance/miwear.d.ts +4 -1
- package/lib/instance/miwear.js +8 -2
- package/lib/instance/pre.d.ts +4 -1
- package/lib/instance/pre.js +3 -3
- package/lib/instance/vela5.js +1 -1
- package/lib/static/avdConfigIni.json +8 -9
- package/lib/typing/Vvd.d.ts +2 -2
- package/lib/typing/Vvd.js +0 -1
- package/lib/utils/file.d.ts +8 -0
- package/lib/utils/file.js +48 -1
- package/lib/vvd/index.d.ts +3 -1
- package/lib/vvd/index.js +79 -6
- package/package.json +3 -3
|
@@ -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: '
|
|
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: '
|
|
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.
|
|
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
|
};
|
package/lib/instance/common.d.ts
CHANGED
|
@@ -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,
|
|
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
|
/** 重启应用 */
|
package/lib/instance/common.js
CHANGED
|
@@ -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,
|
|
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
|
-
},
|
|
135
|
+
}, 3000);
|
|
132
136
|
});
|
|
133
137
|
} else {
|
|
134
138
|
clearTimeout(timer);
|
package/lib/instance/dev.d.ts
CHANGED
|
@@ -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,
|
|
12
|
+
install(rpkPath: string, opt: {
|
|
13
|
+
packageName?: string;
|
|
14
|
+
size?: number;
|
|
15
|
+
}): Promise<void>;
|
|
13
16
|
/**
|
|
14
17
|
* 在模拟器中启动快应用
|
|
15
18
|
* 通过vapp命令启动,调试时需额外配置--jsdebugger参数
|
package/lib/instance/dev.js
CHANGED
|
@@ -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,
|
|
26
|
+
async install(rpkPath, opt) {
|
|
27
27
|
// 基于 vapp 启动的应用只需要将 rpk 解压到指定的目录下
|
|
28
|
-
rpkPath = rpkPath || `${this.appDir}/${
|
|
29
|
-
const targetPath = `${this.appDir}/${
|
|
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);
|
package/lib/instance/miwear.d.ts
CHANGED
|
@@ -14,7 +14,10 @@ declare class MiwearInstance extends CommonEmulatorInstance {
|
|
|
14
14
|
* 使用 pm 安装快应用
|
|
15
15
|
* @param targeRpk 快应用的rpk文件路径
|
|
16
16
|
*/
|
|
17
|
-
install(targeRpk: string
|
|
17
|
+
install(targeRpk: string, options?: {
|
|
18
|
+
packageName?: string;
|
|
19
|
+
size?: number;
|
|
20
|
+
}): Promise<void>;
|
|
18
21
|
/**
|
|
19
22
|
* 使用 pm 卸载快应用
|
|
20
23
|
* @param packageName 快应用的包名
|
package/lib/instance/miwear.js
CHANGED
|
@@ -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
|
-
},
|
|
74
|
+
}, timeout);
|
|
69
75
|
this.stdoutReadline.on('line', func);
|
|
70
76
|
this.stdoutReadline.on('close', () => {
|
|
71
77
|
this.stdoutReadline.off('line', func);
|
package/lib/instance/pre.d.ts
CHANGED
|
@@ -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,
|
|
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
|
* 在模拟器中启动快应用
|
package/lib/instance/pre.js
CHANGED
|
@@ -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,
|
|
20
|
+
async install(rpkPath, opt) {
|
|
21
21
|
// 基于 vapp 启动的应用只需要将 rpk 解压到指定的目录下
|
|
22
|
-
rpkPath = rpkPath || `${this.appDir}/${
|
|
23
|
-
const targetPath = `${this.appDir}/${
|
|
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);
|
package/lib/instance/vela5.js
CHANGED
|
@@ -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 = /
|
|
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":
|
|
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
|
|
40
|
-
"hw.sensors.
|
|
41
|
-
"hw.sensors.
|
|
42
|
-
"hw.sensors.
|
|
43
|
-
"hw.sensors.light
|
|
44
|
-
"hw.sensors.humidity
|
|
45
|
-
"hw.sensors.heart_rate
|
|
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
|
}
|
package/lib/typing/Vvd.d.ts
CHANGED
|
@@ -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) {
|
package/lib/utils/file.d.ts
CHANGED
|
@@ -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
|
+
}
|
package/lib/vvd/index.d.ts
CHANGED
|
@@ -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):
|
|
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
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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": "
|
|
56
|
+
"gitHead": "9db5595088ce88b2530a20f9edae156e9026718e"
|
|
57
57
|
}
|