@aiot-toolkit/emulator 2.0.5-widget-provider-beta.2 → 2.0.6-beta.1
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/README.md +173 -173
- package/lib/emulatorutil/constants.js +11 -11
- package/lib/emulatorutil/running.js +14 -6
- 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 +26 -5
- package/lib/instance/dev.d.ts +4 -1
- package/lib/instance/dev.js +9 -9
- package/lib/instance/index.js +6 -6
- package/lib/instance/minisound.js +6 -6
- package/lib/instance/miwear.d.ts +5 -1
- package/lib/instance/miwear.js +44 -22
- 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 +9 -9
- package/lib/instance/vela5.d.ts +5 -0
- package/lib/instance/vela5.js +63 -4
- package/lib/shared/index.d.ts +9 -0
- package/lib/shared/index.js +16 -4
- package/lib/static/advancedFeatures.ini +1 -1
- package/lib/static/avdConfigIni.json +45 -39
- package/lib/static/debugger_ip.cfg +1 -1
- package/lib/static/proto/README.MD +2 -2
- package/lib/static/proto/emulator_controller.proto +1321 -1321
- package/lib/static/proto/rtc_service.proto +117 -117
- package/lib/typing/Instance.js +3 -3
- package/lib/typing/Vvd.d.ts +3 -3
- package/lib/typing/Vvd.js +1 -2
- package/lib/utils/file.d.ts +8 -0
- package/lib/utils/file.js +48 -1
- package/lib/utils/index.js +19 -19
- package/lib/vvd/index.d.ts +5 -1
- package/lib/vvd/index.js +127 -43
- package/lib/vvd/logcat.js +3 -3
- package/package.json +3 -3
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'];
|
|
@@ -62,13 +79,13 @@ class VvdManager {
|
|
|
62
79
|
return _path.default.resolve(__dirname, '../static/debugger_ip.cfg');
|
|
63
80
|
}
|
|
64
81
|
|
|
65
|
-
/**
|
|
66
|
-
* 创建Vela端的 VVD ,统一保存在 .vela/vvd 目录下
|
|
67
|
-
* 1. 创建.vela/advancedFeatures.ini文件
|
|
68
|
-
* 2. 创建.vela/vvd/${avdName}.ini文件
|
|
69
|
-
* 3. 创建.vela/vvd/${avdName}.vvd/config.ini文件
|
|
70
|
-
* @param vvdParams VVD参数,宽高、绑定的镜像路径等
|
|
71
|
-
* @returns
|
|
82
|
+
/**
|
|
83
|
+
* 创建Vela端的 VVD ,统一保存在 .vela/vvd 目录下
|
|
84
|
+
* 1. 创建.vela/advancedFeatures.ini文件
|
|
85
|
+
* 2. 创建.vela/vvd/${avdName}.ini文件
|
|
86
|
+
* 3. 创建.vela/vvd/${avdName}.vvd/config.ini文件
|
|
87
|
+
* @param vvdParams VVD参数,宽高、绑定的镜像路径等
|
|
88
|
+
* @returns
|
|
72
89
|
*/
|
|
73
90
|
createVvd(vvdParams) {
|
|
74
91
|
const {
|
|
@@ -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
|
}
|
|
@@ -448,7 +523,8 @@ class VvdManager {
|
|
|
448
523
|
return {
|
|
449
524
|
coldBoot: false,
|
|
450
525
|
emulatorInstance,
|
|
451
|
-
getAgent: () => (0, _grpc.createGrpcClient)(e)
|
|
526
|
+
getAgent: () => (0, _grpc.createGrpcClient)(e),
|
|
527
|
+
grpcConfig: e
|
|
452
528
|
};
|
|
453
529
|
}
|
|
454
530
|
|
|
@@ -471,10 +547,9 @@ class VvdManager {
|
|
|
471
547
|
|
|
472
548
|
// 利用 readline 接口可解决子进程日志换行的问题
|
|
473
549
|
const readlines = (0, _logcat.attachReadline)(emulatorProcess, onStdout, onErrout);
|
|
474
|
-
const emulatorStartedHandler =
|
|
550
|
+
const emulatorStartedHandler = msg => {
|
|
475
551
|
if (func(msg)) {
|
|
476
|
-
const
|
|
477
|
-
const e = runningVvds.find(e => e['avd.id'] === vvdName);
|
|
552
|
+
const e = (0, _emulatorutil.getRunningAvdConfigByName)(vvdName);
|
|
478
553
|
if (e) {
|
|
479
554
|
const emulatorInstance = (0, _instance.findInstance)(vvdInfo.imageType, {
|
|
480
555
|
serialPort: e['port.serial'],
|
|
@@ -491,7 +566,8 @@ class VvdManager {
|
|
|
491
566
|
resolve({
|
|
492
567
|
coldBoot: true,
|
|
493
568
|
emulatorInstance,
|
|
494
|
-
getAgent: () => (0, _grpc.createGrpcClient)(e)
|
|
569
|
+
getAgent: () => (0, _grpc.createGrpcClient)(e),
|
|
570
|
+
grpcConfig: e
|
|
495
571
|
});
|
|
496
572
|
} else {
|
|
497
573
|
reject('get emulator running config failed');
|
|
@@ -663,31 +739,31 @@ class VvdManager {
|
|
|
663
739
|
}
|
|
664
740
|
}
|
|
665
741
|
|
|
666
|
-
/**
|
|
667
|
-
* 下载 SDK,默认只下载需要更新的部分
|
|
668
|
-
* @param opt.force 强制下载所有部分
|
|
669
|
-
*
|
|
670
|
-
* @example
|
|
671
|
-
* async function main() {
|
|
672
|
-
* const sdkHome = path.resolve(os.homedir(), '.export_dev1')
|
|
673
|
-
* const velaAvdCls = new VelaAvdCls({ sdkHome })
|
|
674
|
-
*
|
|
675
|
-
* const downloder = await velaAvdCls.downloadSDK({
|
|
676
|
-
* force: true,
|
|
677
|
-
* cliProgress: false,
|
|
678
|
-
* parallelDownloads: 6
|
|
679
|
-
* })
|
|
680
|
-
*
|
|
681
|
-
* downloder.on('progress', (progress) => {
|
|
682
|
-
* console.log(
|
|
683
|
-
* `progress: ${progress.formattedSpeed} ${progress.formattedPercentage} ${progress.formatTotal} ${progress.formatTimeLeft}`
|
|
684
|
-
* )
|
|
685
|
-
* })
|
|
686
|
-
*
|
|
687
|
-
* await downloder.downlodPromise
|
|
688
|
-
*
|
|
689
|
-
* console.log('download success')
|
|
690
|
-
* }
|
|
742
|
+
/**
|
|
743
|
+
* 下载 SDK,默认只下载需要更新的部分
|
|
744
|
+
* @param opt.force 强制下载所有部分
|
|
745
|
+
*
|
|
746
|
+
* @example
|
|
747
|
+
* async function main() {
|
|
748
|
+
* const sdkHome = path.resolve(os.homedir(), '.export_dev1')
|
|
749
|
+
* const velaAvdCls = new VelaAvdCls({ sdkHome })
|
|
750
|
+
*
|
|
751
|
+
* const downloder = await velaAvdCls.downloadSDK({
|
|
752
|
+
* force: true,
|
|
753
|
+
* cliProgress: false,
|
|
754
|
+
* parallelDownloads: 6
|
|
755
|
+
* })
|
|
756
|
+
*
|
|
757
|
+
* downloder.on('progress', (progress) => {
|
|
758
|
+
* console.log(
|
|
759
|
+
* `progress: ${progress.formattedSpeed} ${progress.formattedPercentage} ${progress.formatTotal} ${progress.formatTimeLeft}`
|
|
760
|
+
* )
|
|
761
|
+
* })
|
|
762
|
+
*
|
|
763
|
+
* await downloder.downlodPromise
|
|
764
|
+
*
|
|
765
|
+
* console.log('download success')
|
|
766
|
+
* }
|
|
691
767
|
*/
|
|
692
768
|
async downloadSDK(opt) {
|
|
693
769
|
const updateList = opt.force ? Object.values(_Vvd.SDKParts) : await this.hasSDKPartUpdate();
|
|
@@ -744,6 +820,10 @@ class VvdManager {
|
|
|
744
820
|
zip.extractAllTo(targetDir, true, true);
|
|
745
821
|
await _fs.default.promises.rm(zipFile, {
|
|
746
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();
|
|
747
827
|
});
|
|
748
828
|
}
|
|
749
829
|
const verFile = this.getSDKVersionPath();
|
|
@@ -773,6 +853,10 @@ class VvdManager {
|
|
|
773
853
|
zip.extractAllTo(_path.default.resolve(this.sdkHome, _Vvd.SDKParts.SYSTEM_IMAGES, imageId), true, true);
|
|
774
854
|
await _fs.default.promises.rm(zipFile, {
|
|
775
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();
|
|
776
860
|
});
|
|
777
861
|
});
|
|
778
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.
|
|
3
|
+
"version": "2.0.6-beta.1",
|
|
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.
|
|
39
|
+
"@aiot-toolkit/shared-utils": "2.0.6-beta.1",
|
|
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": "892743ccc51408960e6cee86675538501b3e47f1"
|
|
57
57
|
}
|