@aiot-toolkit/emulator 2.0.5-beta.22 → 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/index.d.ts +2 -2
- package/lib/index.js +12 -0
- package/lib/instance/common.d.ts +5 -2
- package/lib/instance/common.js +24 -3
- package/lib/instance/dev.d.ts +4 -1
- package/lib/instance/dev.js +3 -3
- package/lib/instance/miwear.d.ts +5 -1
- package/lib/instance/miwear.js +35 -13
- package/lib/instance/miwear5.d.ts +0 -1
- package/lib/instance/miwear5.js +0 -1
- package/lib/instance/pre.d.ts +4 -1
- package/lib/instance/pre.js +3 -3
- package/lib/instance/vela5.d.ts +5 -0
- package/lib/instance/vela5.js +60 -1
- package/lib/shared/index.d.ts +9 -0
- package/lib/shared/index.js +13 -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 +89 -6
- package/lib/vvd/logcat.js +3 -3
- 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/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { VvdManager } from './vvd';
|
|
2
|
-
|
|
2
|
+
export { getSystemArch, tryRun } from './utils';
|
|
3
3
|
export * from './instance';
|
|
4
4
|
export * from './typing/Vvd';
|
|
5
5
|
export * from './typing/Instance';
|
|
6
6
|
export * from './emulatorutil';
|
|
7
|
-
export
|
|
7
|
+
export * from './shared';
|
package/lib/index.js
CHANGED
|
@@ -75,4 +75,16 @@ Object.keys(_emulatorutil).forEach(function (key) {
|
|
|
75
75
|
return _emulatorutil[key];
|
|
76
76
|
}
|
|
77
77
|
});
|
|
78
|
+
});
|
|
79
|
+
var _shared = require("./shared");
|
|
80
|
+
Object.keys(_shared).forEach(function (key) {
|
|
81
|
+
if (key === "default" || key === "__esModule") return;
|
|
82
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
83
|
+
if (key in exports && exports[key] === _shared[key]) return;
|
|
84
|
+
Object.defineProperty(exports, key, {
|
|
85
|
+
enumerable: true,
|
|
86
|
+
get: function () {
|
|
87
|
+
return _shared[key];
|
|
88
|
+
}
|
|
89
|
+
});
|
|
78
90
|
});
|
package/lib/instance/common.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ declare abstract class CommonEmulatorInstance {
|
|
|
10
10
|
static appInstallFailedFlag: RegExp;
|
|
11
11
|
static appUninstalledFlag: RegExp;
|
|
12
12
|
static appStartedFlag: RegExp;
|
|
13
|
-
static isAppInstalled(
|
|
13
|
+
static isAppInstalled(...args: any[]): boolean;
|
|
14
14
|
static isAppInstallFailed(log: string): boolean;
|
|
15
15
|
static isAppUninstalled(log: string, packageName: string): boolean;
|
|
16
16
|
static isEmulatorStarted(log: string): boolean;
|
|
@@ -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
|
@@ -11,6 +11,8 @@ var adbMiwt = _adb;
|
|
|
11
11
|
var _utils = require("../utils");
|
|
12
12
|
var _logcat = require("../vvd/logcat");
|
|
13
13
|
var _emulatorutil = require("../emulatorutil");
|
|
14
|
+
var _shared = require("../shared");
|
|
15
|
+
var _fs = _interopRequireDefault(require("fs"));
|
|
14
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); }
|
|
15
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; }
|
|
16
18
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -21,14 +23,15 @@ class CommonEmulatorInstance {
|
|
|
21
23
|
static appInstallFailedFlag = /uv_mq_read_cb: install prepare failed/;
|
|
22
24
|
static appUninstalledFlag = /uninstalled app/;
|
|
23
25
|
static appStartedFlag = /Start App loop/;
|
|
24
|
-
static isAppInstalled(
|
|
26
|
+
static isAppInstalled() {
|
|
27
|
+
const log = arguments.length <= 0 ? undefined : arguments[0];
|
|
25
28
|
return this.appInstalledFlag.test(log);
|
|
26
29
|
}
|
|
27
30
|
static isAppInstallFailed(log) {
|
|
28
31
|
return this.appInstallFailedFlag.test(log);
|
|
29
32
|
}
|
|
30
33
|
static isAppUninstalled(log, packageName) {
|
|
31
|
-
return new RegExp(this.appUninstalledFlag + ':\\s+' + packageName).test(log);
|
|
34
|
+
return new RegExp(this.appUninstalledFlag.source + ':\\s+' + packageName).test(log);
|
|
32
35
|
}
|
|
33
36
|
static isEmulatorStarted(log) {
|
|
34
37
|
return this.emulatorStartedFlag.test(log);
|
|
@@ -117,7 +120,25 @@ class CommonEmulatorInstance {
|
|
|
117
120
|
}
|
|
118
121
|
async pushAndInstall(rpkPath, appName) {
|
|
119
122
|
const targetPath = await this.pushRpk(rpkPath, appName);
|
|
120
|
-
|
|
123
|
+
try {
|
|
124
|
+
await this.install(targetPath, {
|
|
125
|
+
packageName: appName,
|
|
126
|
+
size: _fs.default.statSync(rpkPath).size
|
|
127
|
+
});
|
|
128
|
+
} catch (error) {
|
|
129
|
+
let timer;
|
|
130
|
+
if (error === _shared.RpkInstallFailedReason.Busy) {
|
|
131
|
+
this.logger('install process is busy, 3s later retry');
|
|
132
|
+
await new Promise((resolve, rejcet) => {
|
|
133
|
+
timer = setTimeout(() => {
|
|
134
|
+
this.pushAndInstall(rpkPath, appName).then(resolve).catch(rejcet);
|
|
135
|
+
}, 3000);
|
|
136
|
+
});
|
|
137
|
+
} else {
|
|
138
|
+
clearTimeout(timer);
|
|
139
|
+
throw error;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
121
142
|
}
|
|
122
143
|
|
|
123
144
|
/** 关闭模拟器 */
|
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
|
@@ -9,11 +9,15 @@ declare class MiwearInstance extends CommonEmulatorInstance {
|
|
|
9
9
|
static appInstalledFlag: RegExp;
|
|
10
10
|
imageType: VelaImageType;
|
|
11
11
|
appDir: string;
|
|
12
|
+
static isAppInstalled(log: string, targetRpk: string): boolean;
|
|
12
13
|
/**
|
|
13
14
|
* 使用 pm 安装快应用
|
|
14
15
|
* @param targeRpk 快应用的rpk文件路径
|
|
15
16
|
*/
|
|
16
|
-
install(targeRpk: string
|
|
17
|
+
install(targeRpk: string, options?: {
|
|
18
|
+
packageName?: string;
|
|
19
|
+
size?: number;
|
|
20
|
+
}): Promise<void>;
|
|
17
21
|
/**
|
|
18
22
|
* 使用 pm 卸载快应用
|
|
19
23
|
* @param packageName 快应用的包名
|
package/lib/instance/miwear.js
CHANGED
|
@@ -9,6 +9,7 @@ var _path = _interopRequireDefault(require("path"));
|
|
|
9
9
|
var _utils = require("../utils");
|
|
10
10
|
var _common = _interopRequireDefault(require("./common"));
|
|
11
11
|
var _Vvd = require("../typing/Vvd");
|
|
12
|
+
var _shared = require("../shared");
|
|
12
13
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
14
|
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); }
|
|
14
15
|
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; }
|
|
@@ -21,40 +22,61 @@ class MiwearInstance extends _common.default {
|
|
|
21
22
|
static appInstalledFlag = /InstallState_Finished|install finished/;
|
|
22
23
|
imageType = (() => _Vvd.VelaImageType.REL)();
|
|
23
24
|
appDir = '/data/quickapp/app';
|
|
24
|
-
|
|
25
|
+
static isAppInstalled(log, targetRpk) {
|
|
26
|
+
// 注意:targetRpk 可能包含特殊字符,需要转义
|
|
27
|
+
const escapedRpk = targetRpk.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
28
|
+
const reg = new RegExp(`executeInstall: rpk install: ${escapedRpk} .* success`);
|
|
29
|
+
return reg.test(log);
|
|
30
|
+
}
|
|
25
31
|
/**
|
|
26
32
|
* 使用 pm 安装快应用
|
|
27
33
|
* @param targeRpk 快应用的rpk文件路径
|
|
28
34
|
*/
|
|
29
|
-
async install(targeRpk) {
|
|
35
|
+
async install(targeRpk, options) {
|
|
30
36
|
const installCmd = `adb -s ${this.sn} shell pm install ${targeRpk}`;
|
|
31
37
|
this.logger(`Excuting: ${installCmd}`);
|
|
32
38
|
adbMiwt.execAdbCmd(installCmd);
|
|
33
39
|
return new Promise((resolve, reject) => {
|
|
40
|
+
const clearFn = () => {
|
|
41
|
+
clearTimeout(timer);
|
|
42
|
+
this.stdoutReadline.off('line', func);
|
|
43
|
+
};
|
|
34
44
|
const func = msg => {
|
|
35
|
-
if (MiwearInstance.isAppInstalled(msg)) {
|
|
36
|
-
clearTimeout(timer);
|
|
45
|
+
if (MiwearInstance.isAppInstalled(msg, targeRpk)) {
|
|
37
46
|
this.logger(`Install to ${this.vvdName} ${targeRpk} successfully`);
|
|
38
|
-
|
|
47
|
+
clearFn();
|
|
39
48
|
resolve();
|
|
40
49
|
}
|
|
41
50
|
if (MiwearInstance.isAppInstallFailed(msg)) {
|
|
42
|
-
clearTimeout(timer);
|
|
43
|
-
this.stdoutReadline.off('line', func);
|
|
44
51
|
this.logger(`Failed Install to ${this.vvdName} ${targeRpk}`);
|
|
45
|
-
|
|
52
|
+
this.logger(_shared.RpkInstallFailedReason.LowStorage);
|
|
53
|
+
clearFn();
|
|
54
|
+
reject(_shared.RpkInstallFailedReason.LowStorage);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// 当前安装进程被占用
|
|
58
|
+
if (msg.includes('installRpk: installation is running, please wait')) {
|
|
59
|
+
this.logger(_shared.RpkInstallFailedReason.Busy);
|
|
60
|
+
clearFn();
|
|
61
|
+
reject(_shared.RpkInstallFailedReason.Busy);
|
|
46
62
|
}
|
|
47
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);
|
|
48
70
|
let timer = setTimeout(() => {
|
|
49
71
|
this.stdoutReadline.off('line', func);
|
|
50
72
|
this.logger(`Install to ${this.vvdName} ${targeRpk} timeout`);
|
|
51
|
-
reject(
|
|
52
|
-
},
|
|
73
|
+
reject(_shared.RpkInstallFailedReason.Timeout);
|
|
74
|
+
}, timeout);
|
|
53
75
|
this.stdoutReadline.on('line', func);
|
|
54
76
|
this.stdoutReadline.on('close', () => {
|
|
55
|
-
this.stdoutReadline.
|
|
77
|
+
this.stdoutReadline.off('line', func);
|
|
56
78
|
clearTimeout(timer);
|
|
57
|
-
reject(
|
|
79
|
+
reject(_shared.RpkInstallFailedReason.Poweroff);
|
|
58
80
|
});
|
|
59
81
|
});
|
|
60
82
|
}
|
|
@@ -98,9 +120,9 @@ class MiwearInstance extends _common.default {
|
|
|
98
120
|
}
|
|
99
121
|
async closeApp(appName) {
|
|
100
122
|
const stopCmd = `adb -s ${this.sn} shell am stop ${appName}`;
|
|
123
|
+
this.logger(`Excuting: ${stopCmd}`);
|
|
101
124
|
await adbMiwt.execAdbCmdAsync(stopCmd);
|
|
102
125
|
this.logger(`Stop ${this.vvdName} ${appName} successfully`);
|
|
103
|
-
// 这里是为了等am stop命令清除资源等
|
|
104
126
|
}
|
|
105
127
|
async reboot() {
|
|
106
128
|
await super.reboot();
|
package/lib/instance/miwear5.js
CHANGED
|
@@ -10,6 +10,5 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
10
10
|
class VelaMiwear5 extends _miwear.default {
|
|
11
11
|
imageType = (() => _Vvd.VelaImageType.VELA_MIWEAR_WATCH_5)();
|
|
12
12
|
appDir = '/data/app';
|
|
13
|
-
static emulatorStartedFlag = /\[App Active Flag/;
|
|
14
13
|
}
|
|
15
14
|
exports.VelaMiwear5 = VelaMiwear5;
|
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.d.ts
CHANGED
|
@@ -10,4 +10,9 @@ export declare class Vela5Instance extends MiwearInstance {
|
|
|
10
10
|
* @param targeRpk 快应用的rpk文件路径
|
|
11
11
|
*/
|
|
12
12
|
install(targeRpk: string): Promise<void>;
|
|
13
|
+
/** 使用 am start 启动快应用 */
|
|
14
|
+
startApp(packageName: string): Promise<void>;
|
|
15
|
+
/** 重启模拟器 */
|
|
16
|
+
reboot(): Promise<void>;
|
|
17
|
+
closeApp(appName: string): Promise<void>;
|
|
13
18
|
}
|
package/lib/instance/vela5.js
CHANGED
|
@@ -4,7 +4,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.Vela5Instance = void 0;
|
|
7
|
+
var _shared = require("../shared");
|
|
7
8
|
var _Vvd = require("../typing/Vvd");
|
|
9
|
+
var _logcat = require("../vvd/logcat");
|
|
8
10
|
var _miwear = _interopRequireDefault(require("./miwear"));
|
|
9
11
|
var adbMiwt = _interopRequireWildcard(require("@miwt/adb"));
|
|
10
12
|
var _util = require("util");
|
|
@@ -12,7 +14,7 @@ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return
|
|
|
12
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; }
|
|
13
15
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
16
|
class Vela5Instance extends _miwear.default {
|
|
15
|
-
static emulatorStartedFlag = /
|
|
17
|
+
static emulatorStartedFlag = /booting completed|Boot completed/;
|
|
16
18
|
static appStartedFlag = /Start main loop/;
|
|
17
19
|
imageType = (() => _Vvd.VelaImageType.VELA_WATCH_5)();
|
|
18
20
|
appDir = '/data/app';
|
|
@@ -35,5 +37,62 @@ class Vela5Instance extends _miwear.default {
|
|
|
35
37
|
return Promise.reject(res);
|
|
36
38
|
}
|
|
37
39
|
}
|
|
40
|
+
|
|
41
|
+
/** 使用 am start 启动快应用 */
|
|
42
|
+
async startApp(packageName) {
|
|
43
|
+
const startCmd = `adb -s ${this.sn} shell am start ${packageName}`;
|
|
44
|
+
this.logger(`Excuting: ${startCmd}`);
|
|
45
|
+
adbMiwt.execAdbCmdAsync(startCmd);
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
47
|
+
const clearFn = () => {
|
|
48
|
+
clearTimeout(timer);
|
|
49
|
+
this.stdoutReadline.off('line', func);
|
|
50
|
+
};
|
|
51
|
+
const func = msg => {
|
|
52
|
+
if (Vela5Instance.appStartedFlag.test(msg)) {
|
|
53
|
+
this.logger(`Start ${packageName} for ${this.vvdName} successfully`);
|
|
54
|
+
clearFn();
|
|
55
|
+
resolve();
|
|
56
|
+
}
|
|
57
|
+
const escapedPackageName = packageName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
58
|
+
const reg = new RegExp(`Failed to open: .+?/${escapedPackageName}/manifest\.json`);
|
|
59
|
+
if (reg.test(msg)) {
|
|
60
|
+
this.logger(`Failed Start ${packageName} for ${this.vvdName}`);
|
|
61
|
+
clearFn();
|
|
62
|
+
reject(_shared.RpkStartFailedReason.getManifestFailed);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
let timer = setTimeout(() => {
|
|
66
|
+
this.stdoutReadline.off('line', func);
|
|
67
|
+
this.logger(`Start ${packageName} for ${this.vvdName} timeout`);
|
|
68
|
+
reject('Timeout');
|
|
69
|
+
}, 8 * 1000);
|
|
70
|
+
this.stdoutReadline.on('line', func);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** 重启模拟器 */
|
|
75
|
+
async reboot() {
|
|
76
|
+
const rebootCmd = `adb -s ${this.sn} shell reboot`;
|
|
77
|
+
this.logger(`Excuting: ${rebootCmd}`);
|
|
78
|
+
await adbMiwt.execAdbCmdAsync(rebootCmd);
|
|
79
|
+
await this.isConnected();
|
|
80
|
+
if (this.logcatProcess.exitCode !== null) {
|
|
81
|
+
// 如果 logcat 进程被杀死,则重新创建
|
|
82
|
+
const r = (0, _logcat.creatLogcat)(this.sn, this.onStdout, this.onErrout);
|
|
83
|
+
this.logcatProcess = r.logcatProcess;
|
|
84
|
+
this.stdoutReadline = r.stdoutReadline;
|
|
85
|
+
this.stderrReadline = r.stderrReadline;
|
|
86
|
+
this.disposeReadlines = r.dispose;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async closeApp(appName) {
|
|
90
|
+
await super.closeApp(appName);
|
|
91
|
+
await new Promise(resolve => {
|
|
92
|
+
setTimeout(() => {
|
|
93
|
+
resolve();
|
|
94
|
+
}, 2000);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
38
97
|
}
|
|
39
98
|
exports.Vela5Instance = Vela5Instance;
|
package/lib/shared/index.d.ts
CHANGED
|
@@ -6,3 +6,12 @@ import { VelaImageType } from '../typing/Vvd';
|
|
|
6
6
|
export declare function isVelaImageType(value: any): value is VelaImageType;
|
|
7
7
|
export declare function isMiwearImageType(val: VelaImageType): boolean;
|
|
8
8
|
export declare function getDefaultImage(): VelaImageType;
|
|
9
|
+
export declare enum RpkStartFailedReason {
|
|
10
|
+
getManifestFailed = "Get app manifest.json failed"
|
|
11
|
+
}
|
|
12
|
+
export declare enum RpkInstallFailedReason {
|
|
13
|
+
Busy = "Installation process is busy",
|
|
14
|
+
Timeout = "Install timeout",
|
|
15
|
+
Poweroff = "Device poweroff",
|
|
16
|
+
LowStorage = "Application exceeds maximum quantity or remaining space is low"
|
|
17
|
+
}
|
package/lib/shared/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.RpkStartFailedReason = exports.RpkInstallFailedReason = void 0;
|
|
6
7
|
exports.getDefaultImage = getDefaultImage;
|
|
7
8
|
exports.isMiwearImageType = isMiwearImageType;
|
|
8
9
|
exports.isVelaImageType = isVelaImageType;
|
|
@@ -20,4 +21,15 @@ function isMiwearImageType(val) {
|
|
|
20
21
|
}
|
|
21
22
|
function getDefaultImage() {
|
|
22
23
|
return _Vvd.VelaImageType.VELA_MIWEAR_WATCH_5;
|
|
23
|
-
}
|
|
24
|
+
}
|
|
25
|
+
let RpkStartFailedReason = exports.RpkStartFailedReason = /*#__PURE__*/function (RpkStartFailedReason) {
|
|
26
|
+
RpkStartFailedReason["getManifestFailed"] = "Get app manifest.json failed";
|
|
27
|
+
return RpkStartFailedReason;
|
|
28
|
+
}({});
|
|
29
|
+
let RpkInstallFailedReason = exports.RpkInstallFailedReason = /*#__PURE__*/function (RpkInstallFailedReason) {
|
|
30
|
+
RpkInstallFailedReason["Busy"] = "Installation process is busy";
|
|
31
|
+
RpkInstallFailedReason["Timeout"] = "Install timeout";
|
|
32
|
+
RpkInstallFailedReason["Poweroff"] = "Device poweroff";
|
|
33
|
+
RpkInstallFailedReason["LowStorage"] = "Application exceeds maximum quantity or remaining space is low";
|
|
34
|
+
return RpkInstallFailedReason;
|
|
35
|
+
}({});
|
|
@@ -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);
|
|
@@ -394,12 +467,14 @@ class VvdManager {
|
|
|
394
467
|
} else continue;
|
|
395
468
|
if (!_fs.default.existsSync(pOfVvd)) {
|
|
396
469
|
// 文件不存在则直接复制
|
|
470
|
+
_ColorConsole.default.log(`${file} not found, copy from ${pOfImageDir}`);
|
|
397
471
|
_fs.default.copyFileSync(pOfImageDir, pOfVvd);
|
|
398
472
|
} else {
|
|
399
473
|
// 文件存在但过时
|
|
400
474
|
const statsInAvd = _fs.default.statSync(pOfVvd);
|
|
401
475
|
const stats = _fs.default.statSync(pOfImageDir);
|
|
402
476
|
if ((0, _dayjs.default)(stats.mtime).isAfter(statsInAvd.mtime)) {
|
|
477
|
+
_ColorConsole.default.log(`${file} file is outdate, update from ${pOfImageDir}`);
|
|
403
478
|
_fs.default.copyFileSync(pOfImageDir, pOfVvd);
|
|
404
479
|
}
|
|
405
480
|
}
|
|
@@ -745,6 +820,10 @@ class VvdManager {
|
|
|
745
820
|
zip.extractAllTo(targetDir, true, true);
|
|
746
821
|
await _fs.default.promises.rm(zipFile, {
|
|
747
822
|
force: true
|
|
823
|
+
}).catch(e => {
|
|
824
|
+
_ColorConsole.default.info(`remove ${zipFile} failed: ${e}`);
|
|
825
|
+
// my be failed on windows as resource busy or locked, don't care
|
|
826
|
+
return Promise.resolve();
|
|
748
827
|
});
|
|
749
828
|
}
|
|
750
829
|
const verFile = this.getSDKVersionPath();
|
|
@@ -774,6 +853,10 @@ class VvdManager {
|
|
|
774
853
|
zip.extractAllTo(_path.default.resolve(this.sdkHome, _Vvd.SDKParts.SYSTEM_IMAGES, imageId), true, true);
|
|
775
854
|
await _fs.default.promises.rm(zipFile, {
|
|
776
855
|
force: true
|
|
856
|
+
}).catch(e => {
|
|
857
|
+
_ColorConsole.default.info(`remove ${zipFile} failed: ${e}`);
|
|
858
|
+
// my be failed on windows as resource busy or locked, don't care
|
|
859
|
+
return Promise.resolve();
|
|
777
860
|
});
|
|
778
861
|
});
|
|
779
862
|
return Object.assign(downloader, {
|
package/lib/vvd/logcat.js
CHANGED
|
@@ -27,7 +27,7 @@ function attachReadline(p, onStdout, onErrout) {
|
|
|
27
27
|
let stderrReadline;
|
|
28
28
|
|
|
29
29
|
// 利用 readline 接口可解决子进程日志换行的问题
|
|
30
|
-
if (p
|
|
30
|
+
if (p?.stdout) {
|
|
31
31
|
stdoutReadline = _readline.default.createInterface({
|
|
32
32
|
input: p.stdout
|
|
33
33
|
});
|
|
@@ -39,7 +39,7 @@ function attachReadline(p, onStdout, onErrout) {
|
|
|
39
39
|
stdoutReadline = undefined;
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
|
-
if (p
|
|
42
|
+
if (p?.stderr) {
|
|
43
43
|
stderrReadline = _readline.default.createInterface({
|
|
44
44
|
input: p.stderr
|
|
45
45
|
});
|
|
@@ -59,7 +59,7 @@ function attachReadline(p, onStdout, onErrout) {
|
|
|
59
59
|
stdoutReadline = undefined;
|
|
60
60
|
stderrReadline = undefined;
|
|
61
61
|
}
|
|
62
|
-
p
|
|
62
|
+
p?.on('exit', () => {
|
|
63
63
|
dispose();
|
|
64
64
|
});
|
|
65
65
|
return {
|
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
|
}
|