appium-android-driver 13.3.4 → 14.0.0
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/CHANGELOG.md +16 -0
- package/build/lib/commands/app-management.d.ts +2 -2
- package/build/lib/commands/app-management.d.ts.map +1 -1
- package/build/lib/commands/app-management.js +41 -67
- package/build/lib/commands/app-management.js.map +1 -1
- package/build/lib/commands/appearance.d.ts +1 -1
- package/build/lib/commands/appearance.d.ts.map +1 -1
- package/build/lib/commands/appearance.js +2 -6
- package/build/lib/commands/appearance.js.map +1 -1
- package/build/lib/commands/bidi/constants.js +4 -8
- package/build/lib/commands/bidi/constants.js.map +1 -1
- package/build/lib/commands/bidi/models.d.ts +1 -1
- package/build/lib/commands/bidi/models.d.ts.map +1 -1
- package/build/lib/commands/bidi/models.js +7 -13
- package/build/lib/commands/bidi/models.js.map +1 -1
- package/build/lib/commands/bidi/types.js +1 -2
- package/build/lib/commands/bluetooth.d.ts +1 -1
- package/build/lib/commands/bluetooth.d.ts.map +1 -1
- package/build/lib/commands/bluetooth.js +3 -6
- package/build/lib/commands/bluetooth.js.map +1 -1
- package/build/lib/commands/context/cache.d.ts +1 -1
- package/build/lib/commands/context/cache.d.ts.map +1 -1
- package/build/lib/commands/context/cache.js +5 -10
- package/build/lib/commands/context/cache.js.map +1 -1
- package/build/lib/commands/context/exports.d.ts +2 -2
- package/build/lib/commands/context/exports.d.ts.map +1 -1
- package/build/lib/commands/context/exports.js +64 -86
- package/build/lib/commands/context/exports.js.map +1 -1
- package/build/lib/commands/context/helpers.d.ts +2 -2
- package/build/lib/commands/context/helpers.d.ts.map +1 -1
- package/build/lib/commands/context/helpers.js +69 -82
- package/build/lib/commands/context/helpers.js.map +1 -1
- package/build/lib/commands/device/common.d.ts +2 -2
- package/build/lib/commands/device/common.d.ts.map +1 -1
- package/build/lib/commands/device/common.js +47 -77
- package/build/lib/commands/device/common.js.map +1 -1
- package/build/lib/commands/device/emulator-actions.d.ts +2 -2
- package/build/lib/commands/device/emulator-actions.d.ts.map +1 -1
- package/build/lib/commands/device/emulator-actions.js +33 -52
- package/build/lib/commands/device/emulator-actions.js.map +1 -1
- package/build/lib/commands/device/emulator-console.d.ts +1 -1
- package/build/lib/commands/device/emulator-console.d.ts.map +1 -1
- package/build/lib/commands/device/emulator-console.js +3 -6
- package/build/lib/commands/device/emulator-console.js.map +1 -1
- package/build/lib/commands/device/utils.d.ts +1 -1
- package/build/lib/commands/device/utils.d.ts.map +1 -1
- package/build/lib/commands/device/utils.js +27 -37
- package/build/lib/commands/device/utils.js.map +1 -1
- package/build/lib/commands/deviceidle.d.ts +1 -1
- package/build/lib/commands/deviceidle.d.ts.map +1 -1
- package/build/lib/commands/deviceidle.js +4 -7
- package/build/lib/commands/deviceidle.js.map +1 -1
- package/build/lib/commands/element.d.ts +2 -2
- package/build/lib/commands/element.d.ts.map +1 -1
- package/build/lib/commands/element.js +22 -39
- package/build/lib/commands/element.js.map +1 -1
- package/build/lib/commands/execute.d.ts +1 -1
- package/build/lib/commands/execute.d.ts.map +1 -1
- package/build/lib/commands/execute.js +6 -9
- package/build/lib/commands/execute.js.map +1 -1
- package/build/lib/commands/file-actions.d.ts +1 -1
- package/build/lib/commands/file-actions.d.ts.map +1 -1
- package/build/lib/commands/file-actions.js +25 -34
- package/build/lib/commands/file-actions.js.map +1 -1
- package/build/lib/commands/find.d.ts +2 -2
- package/build/lib/commands/find.d.ts.map +1 -1
- package/build/lib/commands/find.js +10 -14
- package/build/lib/commands/find.js.map +1 -1
- package/build/lib/commands/geolocation.d.ts +1 -1
- package/build/lib/commands/geolocation.d.ts.map +1 -1
- package/build/lib/commands/geolocation.js +21 -35
- package/build/lib/commands/geolocation.js.map +1 -1
- package/build/lib/commands/gestures.d.ts +1 -1
- package/build/lib/commands/gestures.d.ts.map +1 -1
- package/build/lib/commands/gestures.js +4 -7
- package/build/lib/commands/gestures.js.map +1 -1
- package/build/lib/commands/image-injection.d.ts +1 -1
- package/build/lib/commands/image-injection.d.ts.map +1 -1
- package/build/lib/commands/image-injection.js +16 -23
- package/build/lib/commands/image-injection.js.map +1 -1
- package/build/lib/commands/ime.d.ts +1 -1
- package/build/lib/commands/ime.d.ts.map +1 -1
- package/build/lib/commands/ime.js +10 -18
- package/build/lib/commands/ime.js.map +1 -1
- package/build/lib/commands/intent.d.ts +1 -1
- package/build/lib/commands/intent.d.ts.map +1 -1
- package/build/lib/commands/intent.js +22 -29
- package/build/lib/commands/intent.js.map +1 -1
- package/build/lib/commands/keyboard.d.ts +2 -2
- package/build/lib/commands/keyboard.d.ts.map +1 -1
- package/build/lib/commands/keyboard.js +21 -33
- package/build/lib/commands/keyboard.js.map +1 -1
- package/build/lib/commands/legacy.d.ts +1 -1
- package/build/lib/commands/legacy.d.ts.map +1 -1
- package/build/lib/commands/legacy.js +7 -12
- package/build/lib/commands/legacy.js.map +1 -1
- package/build/lib/commands/lock/exports.d.ts +2 -2
- package/build/lib/commands/lock/exports.d.ts.map +1 -1
- package/build/lib/commands/lock/exports.js +18 -25
- package/build/lib/commands/lock/exports.js.map +1 -1
- package/build/lib/commands/lock/helpers.d.ts +2 -2
- package/build/lib/commands/lock/helpers.d.ts.map +1 -1
- package/build/lib/commands/lock/helpers.js +48 -64
- package/build/lib/commands/lock/helpers.js.map +1 -1
- package/build/lib/commands/log.d.ts +2 -2
- package/build/lib/commands/log.d.ts.map +1 -1
- package/build/lib/commands/log.js +38 -42
- package/build/lib/commands/log.js.map +1 -1
- package/build/lib/commands/media-projection.d.ts +2 -2
- package/build/lib/commands/media-projection.d.ts.map +1 -1
- package/build/lib/commands/media-projection.js +14 -22
- package/build/lib/commands/media-projection.js.map +1 -1
- package/build/lib/commands/memory.d.ts +2 -2
- package/build/lib/commands/memory.d.ts.map +1 -1
- package/build/lib/commands/memory.js +4 -7
- package/build/lib/commands/memory.js.map +1 -1
- package/build/lib/commands/misc.d.ts +2 -2
- package/build/lib/commands/misc.d.ts.map +1 -1
- package/build/lib/commands/misc.js +10 -19
- package/build/lib/commands/misc.js.map +1 -1
- package/build/lib/commands/network.d.ts +2 -2
- package/build/lib/commands/network.d.ts.map +1 -1
- package/build/lib/commands/network.js +14 -26
- package/build/lib/commands/network.js.map +1 -1
- package/build/lib/commands/nfc.d.ts +2 -2
- package/build/lib/commands/nfc.d.ts.map +1 -1
- package/build/lib/commands/nfc.js +3 -6
- package/build/lib/commands/nfc.js.map +1 -1
- package/build/lib/commands/performance.d.ts +2 -2
- package/build/lib/commands/performance.d.ts.map +1 -1
- package/build/lib/commands/performance.js +48 -58
- package/build/lib/commands/performance.js.map +1 -1
- package/build/lib/commands/permissions.d.ts +1 -1
- package/build/lib/commands/permissions.d.ts.map +1 -1
- package/build/lib/commands/permissions.js +16 -20
- package/build/lib/commands/permissions.js.map +1 -1
- package/build/lib/commands/recordscreen.d.ts +2 -2
- package/build/lib/commands/recordscreen.d.ts.map +1 -1
- package/build/lib/commands/recordscreen.js +32 -39
- package/build/lib/commands/recordscreen.js.map +1 -1
- package/build/lib/commands/resources.d.ts +1 -1
- package/build/lib/commands/resources.d.ts.map +1 -1
- package/build/lib/commands/resources.js +7 -11
- package/build/lib/commands/resources.js.map +1 -1
- package/build/lib/commands/shell.d.ts +1 -1
- package/build/lib/commands/shell.d.ts.map +1 -1
- package/build/lib/commands/shell.js +9 -12
- package/build/lib/commands/shell.js.map +1 -1
- package/build/lib/commands/streamscreen.d.ts +1 -1
- package/build/lib/commands/streamscreen.d.ts.map +1 -1
- package/build/lib/commands/streamscreen.js +32 -37
- package/build/lib/commands/streamscreen.js.map +1 -1
- package/build/lib/commands/system-bars.d.ts +2 -2
- package/build/lib/commands/system-bars.d.ts.map +1 -1
- package/build/lib/commands/system-bars.js +10 -16
- package/build/lib/commands/system-bars.js.map +1 -1
- package/build/lib/commands/time.d.ts +1 -1
- package/build/lib/commands/time.d.ts.map +1 -1
- package/build/lib/commands/time.js +9 -17
- package/build/lib/commands/time.js.map +1 -1
- package/build/lib/commands/types.d.ts +15 -1
- package/build/lib/commands/types.d.ts.map +1 -1
- package/build/lib/commands/types.js +1 -2
- package/build/lib/constraints.d.ts +3 -0
- package/build/lib/constraints.d.ts.map +1 -1
- package/build/lib/constraints.js +5 -5
- package/build/lib/constraints.js.map +1 -1
- package/build/lib/doctor/checks.js +54 -65
- package/build/lib/doctor/checks.js.map +1 -1
- package/build/lib/doctor/utils.js +4 -7
- package/build/lib/doctor/utils.js.map +1 -1
- package/build/lib/driver.d.ts +39 -39
- package/build/lib/driver.d.ts.map +1 -1
- package/build/lib/driver.js +220 -223
- package/build/lib/driver.js.map +1 -1
- package/build/lib/execute-method-map.js +1 -4
- package/build/lib/execute-method-map.js.map +1 -1
- package/build/lib/index.d.ts +7 -7
- package/build/lib/index.d.ts.map +1 -1
- package/build/lib/index.js +11 -51
- package/build/lib/index.js.map +1 -1
- package/build/lib/logger.js +2 -5
- package/build/lib/logger.js.map +1 -1
- package/build/lib/method-map.js +1 -4
- package/build/lib/method-map.js.map +1 -1
- package/build/lib/utils.d.ts +9 -7
- package/build/lib/utils.d.ts.map +1 -1
- package/build/lib/utils.js +22 -28
- package/build/lib/utils.js.map +1 -1
- package/lib/commands/app-management.ts +5 -11
- package/lib/commands/appearance.ts +1 -1
- package/lib/commands/bidi/models.ts +3 -3
- package/lib/commands/bluetooth.ts +2 -2
- package/lib/commands/context/cache.ts +1 -1
- package/lib/commands/context/exports.ts +7 -7
- package/lib/commands/context/helpers.ts +4 -4
- package/lib/commands/device/common.ts +36 -20
- package/lib/commands/device/emulator-actions.ts +4 -4
- package/lib/commands/device/emulator-console.ts +2 -2
- package/lib/commands/device/utils.ts +3 -3
- package/lib/commands/deviceidle.ts +2 -2
- package/lib/commands/element.ts +3 -3
- package/lib/commands/execute.ts +2 -2
- package/lib/commands/file-actions.ts +2 -2
- package/lib/commands/find.ts +4 -4
- package/lib/commands/geolocation.ts +2 -2
- package/lib/commands/gestures.ts +3 -3
- package/lib/commands/image-injection.ts +2 -2
- package/lib/commands/ime.ts +3 -3
- package/lib/commands/intent.ts +3 -3
- package/lib/commands/keyboard.ts +3 -3
- package/lib/commands/legacy.ts +2 -2
- package/lib/commands/lock/exports.ts +3 -3
- package/lib/commands/lock/helpers.ts +2 -2
- package/lib/commands/log.ts +18 -11
- package/lib/commands/media-projection.ts +2 -2
- package/lib/commands/memory.ts +3 -3
- package/lib/commands/misc.ts +3 -3
- package/lib/commands/network.ts +3 -3
- package/lib/commands/nfc.ts +3 -3
- package/lib/commands/performance.ts +4 -4
- package/lib/commands/permissions.ts +3 -3
- package/lib/commands/recordscreen.ts +5 -5
- package/lib/commands/resources.ts +2 -2
- package/lib/commands/shell.ts +3 -3
- package/lib/commands/streamscreen.ts +6 -4
- package/lib/commands/system-bars.ts +6 -6
- package/lib/commands/time.ts +3 -3
- package/lib/commands/types.ts +15 -1
- package/lib/constraints.ts +3 -0
- package/lib/doctor/checks.ts +1 -1
- package/lib/driver.ts +44 -44
- package/lib/index.ts +7 -7
- package/lib/method-map.ts +1 -1
- package/lib/utils.ts +10 -8
- package/package.json +12 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AndroidDriver } from '../driver';
|
|
2
|
-
import type { StartScreenRecordingOpts, StopScreenRecordingOpts } from './types';
|
|
1
|
+
import type { AndroidDriver } from '../driver.js';
|
|
2
|
+
import type { StartScreenRecordingOpts, StopScreenRecordingOpts } from './types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Starts screen recording on the Android device.
|
|
5
5
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recordscreen.d.ts","sourceRoot":"","sources":["../../../lib/commands/recordscreen.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"recordscreen.d.ts","sourceRoot":"","sources":["../../../lib/commands/recordscreen.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EACV,wBAAwB,EACxB,uBAAuB,EAExB,MAAM,YAAY,CAAC;AAcpB;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,aAAa,EACnB,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,MAAM,CAAC,CAsDjB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,aAAa,EACnB,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,MAAM,CAAC,CA0EjB"}
|
|
@@ -1,14 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.startRecordingScreen = startRecordingScreen;
|
|
7
|
-
exports.stopRecordingScreen = stopRecordingScreen;
|
|
8
|
-
const support_1 = require("@appium/support");
|
|
9
|
-
const asyncbox_1 = require("asyncbox");
|
|
10
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
11
|
-
const teen_process_1 = require("teen_process");
|
|
1
|
+
import { fs, net, system, tempDir, timing, util } from '@appium/support';
|
|
2
|
+
import { waitForCondition } from 'asyncbox';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { exec } from 'teen_process';
|
|
12
5
|
const RETRY_PAUSE = 300;
|
|
13
6
|
const RETRY_TIMEOUT = 5000;
|
|
14
7
|
const MAX_RECORDING_TIME_SEC = 60 * 3;
|
|
@@ -18,7 +11,7 @@ const PROCESS_SHUTDOWN_TIMEOUT = 10 * 1000;
|
|
|
18
11
|
const SCREENRECORD_BINARY = 'screenrecord';
|
|
19
12
|
const DEFAULT_EXT = '.mp4';
|
|
20
13
|
const MIN_EMULATOR_API_LEVEL = 27;
|
|
21
|
-
const FFMPEG_BINARY = `ffmpeg${
|
|
14
|
+
const FFMPEG_BINARY = `ffmpeg${system.isWindows() ? '.exe' : ''}`;
|
|
22
15
|
const ADB_PULL_TIMEOUT = 5 * 60 * 1000;
|
|
23
16
|
/**
|
|
24
17
|
* Starts screen recording on the Android device.
|
|
@@ -33,7 +26,7 @@ const ADB_PULL_TIMEOUT = 5 * 60 * 1000;
|
|
|
33
26
|
* @throws {Error} If screen recording is not supported on the device or emulator,
|
|
34
27
|
* or if the time limit is invalid.
|
|
35
28
|
*/
|
|
36
|
-
async function startRecordingScreen(options = {}) {
|
|
29
|
+
export async function startRecordingScreen(options = {}) {
|
|
37
30
|
await verifyScreenRecordIsSupported(this.adb, this.isEmulator());
|
|
38
31
|
let result = '';
|
|
39
32
|
const { videoSize, timeLimit = DEFAULT_RECORDING_TIME_SEC, bugReport, bitRate, forceRestart, } = options;
|
|
@@ -48,7 +41,7 @@ async function startRecordingScreen(options = {}) {
|
|
|
48
41
|
if (this._screenRecordingProperties) {
|
|
49
42
|
// XXX: this doesn't need to be done in serial, does it?
|
|
50
43
|
const props = this._screenRecordingProperties;
|
|
51
|
-
for (const record of props
|
|
44
|
+
for (const record of props?.records || []) {
|
|
52
45
|
await this.adb.rimraf(record);
|
|
53
46
|
}
|
|
54
47
|
this._screenRecordingProperties = undefined;
|
|
@@ -59,7 +52,7 @@ async function startRecordingScreen(options = {}) {
|
|
|
59
52
|
`The value of '${timeLimit}' has been passed instead.`);
|
|
60
53
|
}
|
|
61
54
|
const recordingProps = {
|
|
62
|
-
timer: new
|
|
55
|
+
timer: new timing.Timer().start(),
|
|
63
56
|
videoSize,
|
|
64
57
|
timeLimit,
|
|
65
58
|
currentTimeLimit: timeLimit,
|
|
@@ -87,7 +80,7 @@ async function startRecordingScreen(options = {}) {
|
|
|
87
80
|
* @throws {Error} If screen recording is not supported, no recording was active,
|
|
88
81
|
* or if the recording process cannot be stopped.
|
|
89
82
|
*/
|
|
90
|
-
async function stopRecordingScreen(options = {}) {
|
|
83
|
+
export async function stopRecordingScreen(options = {}) {
|
|
91
84
|
await verifyScreenRecordIsSupported(this.adb, this.isEmulator());
|
|
92
85
|
const props = this._screenRecordingProperties;
|
|
93
86
|
if (props) {
|
|
@@ -106,7 +99,7 @@ async function stopRecordingScreen(options = {}) {
|
|
|
106
99
|
this.log.info(`Screen recording has not been previously started by Appium. There is nothing to stop`);
|
|
107
100
|
return '';
|
|
108
101
|
}
|
|
109
|
-
if (props
|
|
102
|
+
if (props?.recordingProcess?.isRunning) {
|
|
110
103
|
try {
|
|
111
104
|
await props.recordingProcess.stop('SIGINT', PROCESS_SHUTDOWN_TIMEOUT);
|
|
112
105
|
}
|
|
@@ -115,15 +108,15 @@ async function stopRecordingScreen(options = {}) {
|
|
|
115
108
|
}
|
|
116
109
|
props.recordingProcess = null;
|
|
117
110
|
}
|
|
118
|
-
if (
|
|
111
|
+
if (util.isEmpty(props.records)) {
|
|
119
112
|
throw this.log.errorWithException(`No screen recordings have been stored on the device so far. ` +
|
|
120
113
|
`Are you sure the ${SCREENRECORD_BINARY} utility works as expected?`);
|
|
121
114
|
}
|
|
122
|
-
const tmpRoot = await
|
|
115
|
+
const tmpRoot = await tempDir.openDir();
|
|
123
116
|
try {
|
|
124
117
|
const localRecords = [];
|
|
125
|
-
for (const pathOnDevice of props
|
|
126
|
-
const relativePath =
|
|
118
|
+
for (const pathOnDevice of props?.records || []) {
|
|
119
|
+
const relativePath = path.resolve(tmpRoot, path.posix.basename(pathOnDevice));
|
|
127
120
|
localRecords.push(relativePath);
|
|
128
121
|
await this.adb.pull(pathOnDevice, relativePath, { timeout: ADB_PULL_TIMEOUT });
|
|
129
122
|
await this.adb.rimraf(pathOnDevice);
|
|
@@ -139,21 +132,21 @@ async function stopRecordingScreen(options = {}) {
|
|
|
139
132
|
`Original error: ${e.message}`);
|
|
140
133
|
}
|
|
141
134
|
}
|
|
142
|
-
if (
|
|
143
|
-
const { size } = await
|
|
144
|
-
this.log.debug(`The size of the resulting screen recording is ${
|
|
135
|
+
if (util.isEmpty(options.remotePath)) {
|
|
136
|
+
const { size } = await fs.stat(resultFilePath);
|
|
137
|
+
this.log.debug(`The size of the resulting screen recording is ${util.toReadableSizeString(size)}`);
|
|
145
138
|
}
|
|
146
139
|
return await uploadRecordedMedia(resultFilePath, options.remotePath, options);
|
|
147
140
|
}
|
|
148
141
|
finally {
|
|
149
|
-
await
|
|
142
|
+
await fs.rimraf(tmpRoot);
|
|
150
143
|
this._screenRecordingProperties = undefined;
|
|
151
144
|
}
|
|
152
145
|
}
|
|
153
146
|
// #region Internal helpers
|
|
154
147
|
async function uploadRecordedMedia(localFile, remotePath, uploadOptions = {}) {
|
|
155
|
-
if (
|
|
156
|
-
return (await
|
|
148
|
+
if (util.isEmpty(remotePath)) {
|
|
149
|
+
return (await util.toInMemoryBase64(localFile)).toString();
|
|
157
150
|
}
|
|
158
151
|
const { user, pass, method, headers, fileFieldName, formFields } = uploadOptions;
|
|
159
152
|
const options = {
|
|
@@ -165,7 +158,7 @@ async function uploadRecordedMedia(localFile, remotePath, uploadOptions = {}) {
|
|
|
165
158
|
if (user && pass) {
|
|
166
159
|
options.auth = { user, pass };
|
|
167
160
|
}
|
|
168
|
-
await
|
|
161
|
+
await net.uploadFile(localFile, remotePath, options);
|
|
169
162
|
return '';
|
|
170
163
|
}
|
|
171
164
|
async function verifyScreenRecordIsSupported(adb, isEmulator) {
|
|
@@ -180,13 +173,13 @@ async function scheduleScreenRecord(recordingProperties) {
|
|
|
180
173
|
}
|
|
181
174
|
const { timer, videoSize, bitRate, timeLimit, bugReport } = recordingProperties;
|
|
182
175
|
let currentTimeLimit = MAX_RECORDING_TIME_SEC;
|
|
183
|
-
if (
|
|
176
|
+
if (util.hasValue(recordingProperties.currentTimeLimit)) {
|
|
184
177
|
const currentTimeLimitInt = parseInt(String(recordingProperties.currentTimeLimit), 10);
|
|
185
178
|
if (!isNaN(currentTimeLimitInt) && currentTimeLimitInt < MAX_RECORDING_TIME_SEC) {
|
|
186
179
|
currentTimeLimit = currentTimeLimitInt;
|
|
187
180
|
}
|
|
188
181
|
}
|
|
189
|
-
const pathOnDevice = `/sdcard/${
|
|
182
|
+
const pathOnDevice = `/sdcard/${util.uuidV4().substring(0, 8)}${DEFAULT_EXT}`;
|
|
190
183
|
const recordingProc = this.adb.screenrecord(pathOnDevice, {
|
|
191
184
|
videoSize,
|
|
192
185
|
bitRate,
|
|
@@ -194,7 +187,7 @@ async function scheduleScreenRecord(recordingProperties) {
|
|
|
194
187
|
bugReport,
|
|
195
188
|
});
|
|
196
189
|
recordingProc.on('end', () => {
|
|
197
|
-
if (recordingProperties.stopped || !
|
|
190
|
+
if (recordingProperties.stopped || !util.hasValue(timeLimit)) {
|
|
198
191
|
return;
|
|
199
192
|
}
|
|
200
193
|
const currentDuration = timer.getDuration().asSeconds.toFixed(0);
|
|
@@ -222,7 +215,7 @@ async function scheduleScreenRecord(recordingProperties) {
|
|
|
222
215
|
});
|
|
223
216
|
await recordingProc.start(0);
|
|
224
217
|
try {
|
|
225
|
-
await
|
|
218
|
+
await waitForCondition(async () => await this.adb.fileExists(pathOnDevice), {
|
|
226
219
|
waitMs: RETRY_TIMEOUT,
|
|
227
220
|
intervalMs: RETRY_PAUSE,
|
|
228
221
|
});
|
|
@@ -236,29 +229,29 @@ async function scheduleScreenRecord(recordingProperties) {
|
|
|
236
229
|
}
|
|
237
230
|
async function mergeScreenRecords(mediaFiles) {
|
|
238
231
|
try {
|
|
239
|
-
await
|
|
232
|
+
await fs.which(FFMPEG_BINARY);
|
|
240
233
|
}
|
|
241
234
|
catch {
|
|
242
235
|
throw new Error(`${FFMPEG_BINARY} utility is not available in PATH. Please install it from https://www.ffmpeg.org/`);
|
|
243
236
|
}
|
|
244
237
|
const configContent = mediaFiles.map((x) => `file '${x}'`).join('\n');
|
|
245
|
-
const configFile =
|
|
246
|
-
await
|
|
238
|
+
const configFile = path.resolve(path.dirname(mediaFiles[0]), 'config.txt');
|
|
239
|
+
await fs.writeFile(configFile, configContent, 'utf8');
|
|
247
240
|
this.log.debug(`Generated ffmpeg merging config '${configFile}' with items:\n${configContent}`);
|
|
248
|
-
const result =
|
|
241
|
+
const result = path.resolve(path.dirname(mediaFiles[0]), `merge_${Math.floor(+new Date())}${DEFAULT_EXT}`);
|
|
249
242
|
const args = ['-safe', '0', '-f', 'concat', '-i', configFile, '-c', 'copy', result];
|
|
250
243
|
this.log.info(`Initiating screen records merging using the command '${FFMPEG_BINARY} ${args.join(' ')}'`);
|
|
251
|
-
await
|
|
244
|
+
await exec(FFMPEG_BINARY, args);
|
|
252
245
|
return result;
|
|
253
246
|
}
|
|
254
247
|
async function terminateBackgroundScreenRecording(adb, force = true) {
|
|
255
248
|
const screenrecordPids = await adb.getProcessIdsByName(SCREENRECORD_BINARY);
|
|
256
|
-
if (
|
|
249
|
+
if (util.isEmpty(screenrecordPids)) {
|
|
257
250
|
return false;
|
|
258
251
|
}
|
|
259
252
|
try {
|
|
260
253
|
await adb.shell(['kill', force ? '-15' : '-2', ...screenrecordPids.map(String)]);
|
|
261
|
-
await
|
|
254
|
+
await waitForCondition(async () => util.isEmpty(await adb.getProcessIdsByName(SCREENRECORD_BINARY)), {
|
|
262
255
|
waitMs: PROCESS_SHUTDOWN_TIMEOUT,
|
|
263
256
|
intervalMs: 500,
|
|
264
257
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recordscreen.js","sourceRoot":"","sources":["../../../lib/commands/recordscreen.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"recordscreen.js","sourceRoot":"","sources":["../../../lib/commands/recordscreen.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../../lib/commands/resources.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAC,aAAa,EAAoB,MAAM,
|
|
1
|
+
{"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../../lib/commands/resources.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAC,aAAa,EAAoB,MAAM,cAAc,CAAC;AAGnE;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,aAAa,EACnB,QAAQ,GAAE,MAAM,GAAG,IAAW,GAC7B,OAAO,CAAC,YAAY,CAAC,CAiBvB;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,aAAa,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAqBf"}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getStrings = getStrings;
|
|
4
|
-
exports.ensureDeviceLocale = ensureDeviceLocale;
|
|
5
|
-
const support_1 = require("@appium/support");
|
|
1
|
+
import { fs, tempDir, util } from '@appium/support';
|
|
6
2
|
/**
|
|
7
3
|
* Gets the localized strings from the application.
|
|
8
4
|
*
|
|
@@ -10,7 +6,7 @@ const support_1 = require("@appium/support");
|
|
|
10
6
|
* the device's current language will be used.
|
|
11
7
|
* @returns Promise that resolves to a mapping of string keys to their localized values.
|
|
12
8
|
*/
|
|
13
|
-
async function getStrings(language = null) {
|
|
9
|
+
export async function getStrings(language = null) {
|
|
14
10
|
if (!language) {
|
|
15
11
|
language = await this.adb.getDeviceLanguage();
|
|
16
12
|
this.log.info(`No language specified, returning strings for: ${language}`);
|
|
@@ -35,7 +31,7 @@ async function getStrings(language = null) {
|
|
|
35
31
|
* @returns Promise that resolves when the locale is set and verified.
|
|
36
32
|
* @throws {Error} If the locale cannot be set or verified.
|
|
37
33
|
*/
|
|
38
|
-
async function ensureDeviceLocale(language, country, script) {
|
|
34
|
+
export async function ensureDeviceLocale(language, country, script) {
|
|
39
35
|
try {
|
|
40
36
|
await this.settingsApp.setDeviceLocale(language, country, script);
|
|
41
37
|
if (!(await this.adb.ensureCurrentLocale(language, country, script))) {
|
|
@@ -65,7 +61,7 @@ async function extractStringsFromResources(language, opts = null) {
|
|
|
65
61
|
let tmpRoot;
|
|
66
62
|
try {
|
|
67
63
|
if (!app && caps.appPackage) {
|
|
68
|
-
tmpRoot = await
|
|
64
|
+
tmpRoot = await tempDir.openDir();
|
|
69
65
|
try {
|
|
70
66
|
app = await this.adb.pullApk(caps.appPackage, tmpRoot);
|
|
71
67
|
}
|
|
@@ -73,14 +69,14 @@ async function extractStringsFromResources(language, opts = null) {
|
|
|
73
69
|
throw new Error(`Could not extract app strings, failed to pull an apk from '${caps.appPackage}'. Original error: ${e.message}`, { cause: e });
|
|
74
70
|
}
|
|
75
71
|
}
|
|
76
|
-
if (!app || !(await
|
|
72
|
+
if (!app || !(await fs.exists(app))) {
|
|
77
73
|
throw new Error(`Could not extract app strings, no app or package specified`);
|
|
78
74
|
}
|
|
79
75
|
return (await this.adb.extractStringsFromApk(app, language ?? null)).apkStrings;
|
|
80
76
|
}
|
|
81
77
|
finally {
|
|
82
78
|
if (tmpRoot) {
|
|
83
|
-
await
|
|
79
|
+
await fs.rimraf(tmpRoot);
|
|
84
80
|
}
|
|
85
81
|
}
|
|
86
82
|
}
|
|
@@ -88,7 +84,7 @@ async function fetchLocaleSuggestions(language, country) {
|
|
|
88
84
|
const supportedLocales = await this.settingsApp.listSupportedLocales();
|
|
89
85
|
const suggestedLocales = supportedLocales.filter((locale) => language?.toLowerCase() === locale.language?.toLowerCase() ||
|
|
90
86
|
country?.toLowerCase() === locale.country?.toLowerCase());
|
|
91
|
-
return
|
|
87
|
+
return util.isEmpty(suggestedLocales) ? supportedLocales : suggestedLocales;
|
|
92
88
|
}
|
|
93
89
|
function toLocaleAbbr({ language, country, script }) {
|
|
94
90
|
return `${language}_${country}${script ? '-' + script : ''}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../../../lib/commands/resources.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../../../lib/commands/resources.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../../lib/commands/shell.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../../lib/commands/shell.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,cAAc,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,WAAW,CAAC,CAAC,SAAS,OAAO,EACjD,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,MAAM,EAAO,EACnB,OAAO,GAAE,MAAc,EACvB,aAAa,CAAC,EAAE,CAAC,GAChB,OAAO,CAAC,CAAC,SAAS,IAAI,GAAG;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,GAAG,MAAM,CAAC,CAiCrE"}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const driver_1 = require("appium/driver");
|
|
6
|
-
const teen_process_1 = require("teen_process");
|
|
7
|
-
const utils_1 = require("../utils");
|
|
1
|
+
import { util } from '@appium/support';
|
|
2
|
+
import { errors } from 'appium/driver.js';
|
|
3
|
+
import { exec } from 'teen_process';
|
|
4
|
+
import { ADB_SHELL_FEATURE } from '../utils.js';
|
|
8
5
|
/**
|
|
9
6
|
* Executes a shell command on the device via ADB.
|
|
10
7
|
*
|
|
@@ -26,10 +23,10 @@ const utils_1 = require("../utils");
|
|
|
26
23
|
* @throws {errors.InvalidArgumentError} If `command` is not a string.
|
|
27
24
|
* @throws {Error} If the command execution fails or times out.
|
|
28
25
|
*/
|
|
29
|
-
async function mobileShell(command, args = [], timeout = 20000, includeStderr) {
|
|
30
|
-
this.assertFeatureEnabled(
|
|
26
|
+
export async function mobileShell(command, args = [], timeout = 20000, includeStderr) {
|
|
27
|
+
this.assertFeatureEnabled(ADB_SHELL_FEATURE);
|
|
31
28
|
if (typeof command !== 'string') {
|
|
32
|
-
throw new
|
|
29
|
+
throw new errors.InvalidArgumentError(`The 'command' argument is mandatory`);
|
|
33
30
|
}
|
|
34
31
|
const adbArgs = [
|
|
35
32
|
...this.adb.executable.defaultArgs,
|
|
@@ -37,9 +34,9 @@ async function mobileShell(command, args = [], timeout = 20000, includeStderr) {
|
|
|
37
34
|
command,
|
|
38
35
|
...(Array.isArray(args) ? args : [args]),
|
|
39
36
|
];
|
|
40
|
-
this.log.debug(`Running '${this.adb.executable.path} ${
|
|
37
|
+
this.log.debug(`Running '${this.adb.executable.path} ${util.quote(adbArgs)}'`);
|
|
41
38
|
try {
|
|
42
|
-
const { stdout, stderr } = await
|
|
39
|
+
const { stdout, stderr } = await exec(this.adb.executable.path, adbArgs, { timeout });
|
|
43
40
|
if (includeStderr) {
|
|
44
41
|
// @ts-ignore We know what we are doing here
|
|
45
42
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell.js","sourceRoot":"","sources":["../../../lib/commands/shell.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"shell.js","sourceRoot":"","sources":["../../../lib/commands/shell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,iBAAiB,CAAC;AACrC,OAAO,EAAC,MAAM,EAAC,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAC,IAAI,EAAC,MAAM,cAAc,CAAC;AAElC,OAAO,EAAC,iBAAiB,EAAC,MAAM,aAAa,CAAC;AAG9C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAE/B,OAAe,EACf,OAAiB,EAAE,EACnB,UAAkB,KAAK,EACvB,aAAiB;IAEjB,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,CAAC;IAE7C,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,IAAI,MAAM,CAAC,oBAAoB,CAAC,qCAAqC,CAAC,CAAC;IAC/E,CAAC;IAED,MAAM,OAAO,GAAG;QACd,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW;QAClC,OAAO;QACP,OAAO;QACP,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;KACzC,CAAC;IACF,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/E,IAAI,CAAC;QACH,MAAM,EAAC,MAAM,EAAE,MAAM,EAAC,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,EAAC,OAAO,EAAC,CAAC,CAAC;QAClF,IAAI,aAAa,EAAE,CAAC;YAClB,4CAA4C;YAC5C,OAAO;gBACL,MAAM;gBACN,MAAM;aACP,CAAC;QACJ,CAAC;QACD,4CAA4C;QAC5C,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,GAAG,GAAG,CAAc,CAAC;QAC3B,MAAM,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAC/B,uBAAuB,OAAO,mBAAmB;YAC/C,mBAAmB,GAAG,CAAC,OAAO,IAAI;YAClC,WAAW,GAAG,CAAC,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,CACjD,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streamscreen.d.ts","sourceRoot":"","sources":["../../../lib/commands/streamscreen.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"streamscreen.d.ts","sourceRoot":"","sources":["../../../lib/commands/streamscreen.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,cAAc,CAAC;AA2BhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,aAAa,EACnB,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,EAChB,IAAI,GAAE,MAAqB,EAC3B,IAAI,GAAE,MAAqB,EAC3B,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,GAAE,MAAyB,EAClC,OAAO,GAAE,MAAwB,EACjC,gBAAgB,GAAE,OAAe,EACjC,kBAAkB,GAAE,OAAe,GAClC,OAAO,CAAC,IAAI,CAAC,CAoJf;AAED;;;;;;;;;GASG;AACH,wBAAsB,yBAAyB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAmClF"}
|
|
@@ -1,22 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const asyncbox_1 = require("asyncbox");
|
|
10
|
-
const node_child_process_1 = require("node:child_process");
|
|
11
|
-
const node_http_1 = __importDefault(require("node:http"));
|
|
12
|
-
const node_net_1 = __importDefault(require("node:net"));
|
|
13
|
-
const node_url_1 = __importDefault(require("node:url"));
|
|
14
|
-
const portscanner_1 = require("portscanner");
|
|
15
|
-
const teen_process_1 = require("teen_process");
|
|
1
|
+
import { fs, logger, system, util } from '@appium/support';
|
|
2
|
+
import { waitForCondition } from 'asyncbox';
|
|
3
|
+
import { spawn } from 'node:child_process';
|
|
4
|
+
import http from 'node:http';
|
|
5
|
+
import net from 'node:net';
|
|
6
|
+
import url from 'node:url';
|
|
7
|
+
import { checkPortStatus } from 'portscanner';
|
|
8
|
+
import { SubProcess, exec } from 'teen_process';
|
|
16
9
|
const RECORDING_INTERVAL_SEC = 5;
|
|
17
10
|
const STREAMING_STARTUP_TIMEOUT_MS = 5000;
|
|
18
|
-
const GSTREAMER_BINARY = `gst-launch-1.0${
|
|
19
|
-
const GST_INSPECT_BINARY = `gst-inspect-1.0${
|
|
11
|
+
const GSTREAMER_BINARY = `gst-launch-1.0${system.isWindows() ? '.exe' : ''}`;
|
|
12
|
+
const GST_INSPECT_BINARY = `gst-inspect-1.0${system.isWindows() ? '.exe' : ''}`;
|
|
20
13
|
const REQUIRED_GST_PLUGINS = {
|
|
21
14
|
avdec_h264: 'gst-libav',
|
|
22
15
|
h264parse: 'gst-plugins-bad',
|
|
@@ -73,7 +66,7 @@ const ADB_SCREEN_STREAMING_FEATURE = 'adb_screen_streaming';
|
|
|
73
66
|
* Might be useful for debugging purposes.
|
|
74
67
|
* @throws {Error} If streaming requirements are not met, ports are busy, or streaming fails to start.
|
|
75
68
|
*/
|
|
76
|
-
async function mobileStartScreenStreaming(width, height, bitRate, host = DEFAULT_HOST, port = DEFAULT_PORT, pathname, tcpPort = DEFAULT_PORT + 1, quality = DEFAULT_QUALITY, considerRotation = false, logPipelineDetails = false) {
|
|
69
|
+
export async function mobileStartScreenStreaming(width, height, bitRate, host = DEFAULT_HOST, port = DEFAULT_PORT, pathname, tcpPort = DEFAULT_PORT + 1, quality = DEFAULT_QUALITY, considerRotation = false, logPipelineDetails = false) {
|
|
77
70
|
this.assertFeatureEnabled(ADB_SCREEN_STREAMING_FEATURE);
|
|
78
71
|
if (this._screenStreamingProps === undefined) {
|
|
79
72
|
await verifyStreamingRequirements(this.adb);
|
|
@@ -83,11 +76,11 @@ async function mobileStartScreenStreaming(width, height, bitRate, host = DEFAULT
|
|
|
83
76
|
`Stop it first in order to start a new one.`);
|
|
84
77
|
return;
|
|
85
78
|
}
|
|
86
|
-
if ((await
|
|
79
|
+
if ((await checkPortStatus(port, host)) === 'open') {
|
|
87
80
|
this.log.info(`The port #${port} at ${host} is busy. ` + `Assuming the screen streaming is already running`);
|
|
88
81
|
return;
|
|
89
82
|
}
|
|
90
|
-
if ((await
|
|
83
|
+
if ((await checkPortStatus(tcpPort, TCP_HOST)) === 'open') {
|
|
91
84
|
throw this.log.errorWithException(`The port #${tcpPort} at ${TCP_HOST} is busy. ` +
|
|
92
85
|
`Make sure there are no leftovers from previous sessions.`);
|
|
93
86
|
}
|
|
@@ -122,9 +115,9 @@ async function mobileStartScreenStreaming(width, height, bitRate, host = DEFAULT
|
|
|
122
115
|
mjpegConnectTimeoutId = setTimeout(() => reject(new Error(`Cannot connect to the streaming server within ${STREAMING_STARTUP_TIMEOUT_MS}ms`)), STREAMING_STARTUP_TIMEOUT_MS);
|
|
123
116
|
});
|
|
124
117
|
const mjpegServerReadyPromise = new Promise((resolve, reject) => {
|
|
125
|
-
mjpegSocket =
|
|
118
|
+
mjpegSocket = net.createConnection(tcpPort, TCP_HOST, () => {
|
|
126
119
|
this.log.info(`Successfully connected to MJPEG stream at tcp://${TCP_HOST}:${tcpPort}`);
|
|
127
|
-
mjpegServer =
|
|
120
|
+
mjpegServer = http.createServer((req, res) => {
|
|
128
121
|
const remoteAddress = extractRemoteAddress(req);
|
|
129
122
|
const currentPathname = extractSafePathnameFromUrl(req.url);
|
|
130
123
|
this.log.info(`Got an incoming screen broadcasting request from ${remoteAddress} ` +
|
|
@@ -191,11 +184,13 @@ async function mobileStartScreenStreaming(width, height, bitRate, host = DEFAULT
|
|
|
191
184
|
clearTimeout(mjpegConnectTimeoutId);
|
|
192
185
|
}
|
|
193
186
|
}
|
|
187
|
+
// Both are guaranteed to be set at this point, since mjpegServerReadyPromise
|
|
188
|
+
// only resolves after the MJPEG server has started listening.
|
|
194
189
|
this._screenStreamingProps = {
|
|
195
190
|
deviceStreamingProc,
|
|
196
191
|
gstreamerPipeline,
|
|
197
|
-
mjpegSocket,
|
|
198
|
-
mjpegServer,
|
|
192
|
+
mjpegSocket: mjpegSocket,
|
|
193
|
+
mjpegServer: mjpegServer,
|
|
199
194
|
};
|
|
200
195
|
}
|
|
201
196
|
/**
|
|
@@ -208,7 +203,7 @@ async function mobileStartScreenStreaming(width, height, bitRate, host = DEFAULT
|
|
|
208
203
|
*
|
|
209
204
|
* If no streaming session is active, this method returns without error.
|
|
210
205
|
*/
|
|
211
|
-
async function mobileStopScreenStreaming() {
|
|
206
|
+
export async function mobileStopScreenStreaming() {
|
|
212
207
|
if (!this._screenStreamingProps) {
|
|
213
208
|
if (this._screenStreamingProps !== undefined) {
|
|
214
209
|
this.log.debug(`Screen streaming is not running. There is nothing to stop`);
|
|
@@ -246,8 +241,8 @@ async function mobileStopScreenStreaming() {
|
|
|
246
241
|
}
|
|
247
242
|
// #region Internal helpers
|
|
248
243
|
function createStreamingLogger(streamName, udid) {
|
|
249
|
-
return
|
|
250
|
-
|
|
244
|
+
return logger.getLogger(`${streamName}@` +
|
|
245
|
+
util.truncateString(udid, {
|
|
251
246
|
length: 8,
|
|
252
247
|
omission: '',
|
|
253
248
|
}));
|
|
@@ -260,7 +255,7 @@ async function verifyStreamingRequirements(adb) {
|
|
|
260
255
|
for (const binaryName of [GSTREAMER_BINARY, GST_INSPECT_BINARY]) {
|
|
261
256
|
gstreamerCheckPromises.push((async () => {
|
|
262
257
|
try {
|
|
263
|
-
await
|
|
258
|
+
await fs.which(binaryName);
|
|
264
259
|
}
|
|
265
260
|
catch {
|
|
266
261
|
throw new Error(`The '${binaryName}' binary is not available in the PATH on the host system. ` +
|
|
@@ -272,7 +267,7 @@ async function verifyStreamingRequirements(adb) {
|
|
|
272
267
|
const moduleCheckPromises = [];
|
|
273
268
|
for (const [name, modName] of Object.entries(REQUIRED_GST_PLUGINS)) {
|
|
274
269
|
moduleCheckPromises.push((async () => {
|
|
275
|
-
const { stdout } = await
|
|
270
|
+
const { stdout } = await exec(GST_INSPECT_BINARY, [name]);
|
|
276
271
|
if (!stdout?.includes(modName)) {
|
|
277
272
|
throw new Error(`The required GStreamer plugin '${name}' from '${modName}' module is not installed. ` +
|
|
278
273
|
`See ${GST_TUTORIAL_URL} for more details on how to install it.`);
|
|
@@ -323,7 +318,7 @@ async function initDeviceStreamingProc(adb, log, deviceInfo, opts = {}) {
|
|
|
323
318
|
// for screenrecord is always limited
|
|
324
319
|
`while true; do ${screenRecordCmd} -; done`,
|
|
325
320
|
];
|
|
326
|
-
const deviceStreaming =
|
|
321
|
+
const deviceStreaming = spawn(adb.executable.path, adbArgs);
|
|
327
322
|
deviceStreaming.on('exit', (code, signal) => {
|
|
328
323
|
log.debug(`Device streaming process exited with code ${code}, signal ${signal}`);
|
|
329
324
|
});
|
|
@@ -338,13 +333,13 @@ async function initDeviceStreamingProc(adb, log, deviceInfo, opts = {}) {
|
|
|
338
333
|
deviceStreaming.stderr.on('data', errorsListener);
|
|
339
334
|
const startupListener = (chunk) => {
|
|
340
335
|
if (!isStarted) {
|
|
341
|
-
isStarted = !
|
|
336
|
+
isStarted = !util.isEmpty(chunk);
|
|
342
337
|
}
|
|
343
338
|
};
|
|
344
339
|
deviceStreaming.stdout.on('data', startupListener);
|
|
345
340
|
try {
|
|
346
|
-
log.info(`Starting device streaming: ${
|
|
347
|
-
await
|
|
341
|
+
log.info(`Starting device streaming: ${util.quote([adb.executable.path, ...adbArgs])}`);
|
|
342
|
+
await waitForCondition(() => isStarted, {
|
|
348
343
|
waitMs: STREAMING_STARTUP_TIMEOUT_MS,
|
|
349
344
|
intervalMs: 300,
|
|
350
345
|
});
|
|
@@ -362,7 +357,7 @@ async function initGstreamerPipeline(deviceStreamingProc, deviceInfo, log, opts)
|
|
|
362
357
|
const { width, height, quality, tcpPort, considerRotation, logPipelineDetails } = opts;
|
|
363
358
|
const adjustedWidth = parseInt(String(width), 10) || deviceInfo.width;
|
|
364
359
|
const adjustedHeight = parseInt(String(height), 10) || deviceInfo.height;
|
|
365
|
-
const gstreamerPipeline = new
|
|
360
|
+
const gstreamerPipeline = new SubProcess(GSTREAMER_BINARY, [
|
|
366
361
|
'-v',
|
|
367
362
|
'fdsrc',
|
|
368
363
|
'fd=0',
|
|
@@ -409,9 +404,9 @@ async function initGstreamerPipeline(deviceStreamingProc, deviceInfo, log, opts)
|
|
|
409
404
|
try {
|
|
410
405
|
log.info(`Starting GStreamer pipeline: ${gstreamerPipeline.rep}`);
|
|
411
406
|
await gstreamerPipeline.start(0);
|
|
412
|
-
await
|
|
407
|
+
await waitForCondition(async () => {
|
|
413
408
|
try {
|
|
414
|
-
return (await
|
|
409
|
+
return (await checkPortStatus(tcpPort, TCP_HOST)) === 'open';
|
|
415
410
|
}
|
|
416
411
|
catch {
|
|
417
412
|
return false;
|
|
@@ -437,7 +432,7 @@ async function initGstreamerPipeline(deviceStreamingProc, deviceInfo, log, opts)
|
|
|
437
432
|
*/
|
|
438
433
|
function extractSafePathnameFromUrl(requestUrl) {
|
|
439
434
|
try {
|
|
440
|
-
return new
|
|
435
|
+
return new url.URL(String(requestUrl ?? '/'), 'http://127.0.0.1').pathname;
|
|
441
436
|
}
|
|
442
437
|
catch {
|
|
443
438
|
return '/';
|