appium-android-driver 7.8.3 → 8.0.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.
Files changed (261) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/build/lib/commands/app-management.d.ts +129 -5
  3. package/build/lib/commands/app-management.d.ts.map +1 -1
  4. package/build/lib/commands/app-management.js +433 -128
  5. package/build/lib/commands/app-management.js.map +1 -1
  6. package/build/lib/commands/appearance.d.ts +17 -4
  7. package/build/lib/commands/appearance.d.ts.map +1 -1
  8. package/build/lib/commands/appearance.js +32 -33
  9. package/build/lib/commands/appearance.js.map +1 -1
  10. package/build/lib/commands/context/cache.d.ts +19 -0
  11. package/build/lib/commands/context/cache.d.ts.map +1 -0
  12. package/build/lib/commands/context/cache.js +32 -0
  13. package/build/lib/commands/context/cache.js.map +1 -0
  14. package/build/lib/commands/context/exports.d.ts +141 -0
  15. package/build/lib/commands/context/exports.d.ts.map +1 -0
  16. package/build/lib/commands/context/exports.js +351 -0
  17. package/build/lib/commands/context/exports.js.map +1 -0
  18. package/build/lib/commands/context/helpers.d.ts +98 -0
  19. package/build/lib/commands/context/helpers.d.ts.map +1 -0
  20. package/build/lib/commands/context/helpers.js +715 -0
  21. package/build/lib/commands/context/helpers.js.map +1 -0
  22. package/build/lib/commands/device/common.d.ts +23 -0
  23. package/build/lib/commands/device/common.d.ts.map +1 -0
  24. package/build/lib/commands/device/common.js +230 -0
  25. package/build/lib/commands/device/common.js.map +1 -0
  26. package/build/lib/commands/device/emulator-actions.d.ts +114 -0
  27. package/build/lib/commands/device/emulator-actions.d.ts.map +1 -0
  28. package/build/lib/commands/device/emulator-actions.js +197 -0
  29. package/build/lib/commands/device/emulator-actions.js.map +1 -0
  30. package/build/lib/commands/device/emulator-console.d.ts +7 -0
  31. package/build/lib/commands/device/emulator-console.d.ts.map +1 -0
  32. package/build/lib/commands/device/emulator-console.js +24 -0
  33. package/build/lib/commands/device/emulator-console.js.map +1 -0
  34. package/build/lib/commands/device/utils.d.ts +50 -0
  35. package/build/lib/commands/device/utils.d.ts.map +1 -0
  36. package/build/lib/commands/device/utils.js +238 -0
  37. package/build/lib/commands/device/utils.js.map +1 -0
  38. package/build/lib/commands/deviceidle.d.ts +8 -5
  39. package/build/lib/commands/deviceidle.d.ts.map +1 -1
  40. package/build/lib/commands/deviceidle.js +31 -37
  41. package/build/lib/commands/deviceidle.js.map +1 -1
  42. package/build/lib/commands/element.d.ts +99 -5
  43. package/build/lib/commands/element.d.ts.map +1 -1
  44. package/build/lib/commands/element.js +152 -116
  45. package/build/lib/commands/element.js.map +1 -1
  46. package/build/lib/commands/execute.d.ts +12 -4
  47. package/build/lib/commands/execute.d.ts.map +1 -1
  48. package/build/lib/commands/execute.js +83 -78
  49. package/build/lib/commands/execute.js.map +1 -1
  50. package/build/lib/commands/file-actions.d.ts +42 -5
  51. package/build/lib/commands/file-actions.d.ts.map +1 -1
  52. package/build/lib/commands/file-actions.js +230 -194
  53. package/build/lib/commands/file-actions.js.map +1 -1
  54. package/build/lib/commands/find.d.ts +5 -4
  55. package/build/lib/commands/find.d.ts.map +1 -1
  56. package/build/lib/commands/find.js +7 -10
  57. package/build/lib/commands/find.js.map +1 -1
  58. package/build/lib/commands/geolocation.d.ts +45 -0
  59. package/build/lib/commands/geolocation.d.ts.map +1 -0
  60. package/build/lib/commands/geolocation.js +182 -0
  61. package/build/lib/commands/geolocation.js.map +1 -0
  62. package/build/lib/commands/ime.d.ts +25 -5
  63. package/build/lib/commands/ime.d.ts.map +1 -1
  64. package/build/lib/commands/ime.js +59 -42
  65. package/build/lib/commands/ime.js.map +1 -1
  66. package/build/lib/commands/intent.d.ts +56 -5
  67. package/build/lib/commands/intent.d.ts.map +1 -1
  68. package/build/lib/commands/intent.js +135 -83
  69. package/build/lib/commands/intent.js.map +1 -1
  70. package/build/lib/commands/keyboard.d.ts +58 -4
  71. package/build/lib/commands/keyboard.d.ts.map +1 -1
  72. package/build/lib/commands/keyboard.js +119 -17
  73. package/build/lib/commands/keyboard.js.map +1 -1
  74. package/build/lib/commands/lock/exports.d.ts +301 -0
  75. package/build/lib/commands/lock/exports.d.ts.map +1 -0
  76. package/build/lib/commands/lock/exports.js +121 -0
  77. package/build/lib/commands/lock/exports.js.map +1 -0
  78. package/build/lib/commands/lock/helpers.d.ts +349 -0
  79. package/build/lib/commands/lock/helpers.d.ts.map +1 -0
  80. package/build/lib/commands/lock/helpers.js +375 -0
  81. package/build/lib/commands/lock/helpers.js.map +1 -0
  82. package/build/lib/commands/log.d.ts +59 -5
  83. package/build/lib/commands/log.d.ts.map +1 -1
  84. package/build/lib/commands/log.js +150 -140
  85. package/build/lib/commands/log.js.map +1 -1
  86. package/build/lib/commands/media-projection.d.ts +16 -5
  87. package/build/lib/commands/media-projection.d.ts.map +1 -1
  88. package/build/lib/commands/media-projection.js +69 -58
  89. package/build/lib/commands/media-projection.js.map +1 -1
  90. package/build/lib/commands/memory.d.ts +9 -5
  91. package/build/lib/commands/memory.d.ts.map +1 -1
  92. package/build/lib/commands/memory.js +19 -24
  93. package/build/lib/commands/memory.js.map +1 -1
  94. package/build/lib/commands/misc.d.ts +42 -0
  95. package/build/lib/commands/misc.d.ts.map +1 -0
  96. package/build/lib/commands/misc.js +100 -0
  97. package/build/lib/commands/misc.js.map +1 -0
  98. package/build/lib/commands/network.d.ts +61 -5
  99. package/build/lib/commands/network.d.ts.map +1 -1
  100. package/build/lib/commands/network.js +196 -189
  101. package/build/lib/commands/network.js.map +1 -1
  102. package/build/lib/commands/performance.d.ts +67 -27
  103. package/build/lib/commands/performance.d.ts.map +1 -1
  104. package/build/lib/commands/performance.js +105 -80
  105. package/build/lib/commands/performance.js.map +1 -1
  106. package/build/lib/commands/permissions.d.ts +12 -6
  107. package/build/lib/commands/permissions.d.ts.map +1 -1
  108. package/build/lib/commands/permissions.js +65 -62
  109. package/build/lib/commands/permissions.js.map +1 -1
  110. package/build/lib/commands/recordscreen.d.ts +44 -5
  111. package/build/lib/commands/recordscreen.d.ts.map +1 -1
  112. package/build/lib/commands/recordscreen.js +131 -126
  113. package/build/lib/commands/recordscreen.js.map +1 -1
  114. package/build/lib/commands/resources.d.ts +16 -0
  115. package/build/lib/commands/resources.d.ts.map +1 -0
  116. package/build/lib/commands/resources.js +91 -0
  117. package/build/lib/commands/resources.js.map +1 -0
  118. package/build/lib/commands/shell.d.ts +8 -5
  119. package/build/lib/commands/shell.d.ts.map +1 -1
  120. package/build/lib/commands/shell.js +29 -33
  121. package/build/lib/commands/shell.js.map +1 -1
  122. package/build/lib/commands/streamscreen.d.ts +34 -6
  123. package/build/lib/commands/streamscreen.d.ts.map +1 -1
  124. package/build/lib/commands/streamscreen.js +166 -162
  125. package/build/lib/commands/streamscreen.js.map +1 -1
  126. package/build/lib/commands/system-bars.d.ts +18 -13
  127. package/build/lib/commands/system-bars.d.ts.map +1 -1
  128. package/build/lib/commands/system-bars.js +68 -64
  129. package/build/lib/commands/system-bars.js.map +1 -1
  130. package/build/lib/commands/time.d.ts +14 -0
  131. package/build/lib/commands/time.d.ts.map +1 -0
  132. package/build/lib/commands/time.js +39 -0
  133. package/build/lib/commands/time.js.map +1 -0
  134. package/build/lib/commands/touch.d.ts +99 -6
  135. package/build/lib/commands/touch.d.ts.map +1 -1
  136. package/build/lib/commands/touch.js +399 -280
  137. package/build/lib/commands/touch.js.map +1 -1
  138. package/build/lib/commands/types.d.ts +110 -2
  139. package/build/lib/commands/types.d.ts.map +1 -1
  140. package/build/lib/doctor/checks.d.ts.map +1 -1
  141. package/build/lib/doctor/checks.js +4 -4
  142. package/build/lib/doctor/checks.js.map +1 -1
  143. package/build/lib/driver.d.ts +224 -27
  144. package/build/lib/driver.d.ts.map +1 -1
  145. package/build/lib/driver.js +232 -7
  146. package/build/lib/driver.js.map +1 -1
  147. package/build/lib/index.d.ts +1 -4
  148. package/build/lib/index.d.ts.map +1 -1
  149. package/build/lib/index.js +1 -13
  150. package/build/lib/index.js.map +1 -1
  151. package/build/lib/logger.js.map +1 -1
  152. package/build/lib/method-map.d.ts +0 -23
  153. package/build/lib/method-map.d.ts.map +1 -1
  154. package/build/lib/method-map.js +0 -11
  155. package/build/lib/method-map.js.map +1 -1
  156. package/build/lib/utils.d.ts +12 -0
  157. package/build/lib/utils.d.ts.map +1 -1
  158. package/build/lib/utils.js +38 -2
  159. package/build/lib/utils.js.map +1 -1
  160. package/lib/commands/app-management.js +470 -145
  161. package/lib/commands/appearance.js +29 -36
  162. package/lib/commands/context/cache.js +29 -0
  163. package/lib/commands/context/exports.js +379 -0
  164. package/lib/commands/context/helpers.js +802 -0
  165. package/lib/commands/device/common.js +264 -0
  166. package/lib/commands/device/emulator-actions.js +194 -0
  167. package/lib/commands/device/emulator-console.js +24 -0
  168. package/lib/commands/device/utils.js +285 -0
  169. package/lib/commands/deviceidle.js +31 -44
  170. package/lib/commands/element.js +149 -142
  171. package/lib/commands/execute.js +86 -87
  172. package/lib/commands/file-actions.js +249 -222
  173. package/lib/commands/find.ts +13 -19
  174. package/lib/commands/geolocation.js +179 -0
  175. package/lib/commands/ime.js +53 -45
  176. package/lib/commands/intent.js +149 -91
  177. package/lib/commands/keyboard.js +114 -17
  178. package/lib/commands/lock/exports.js +139 -0
  179. package/lib/commands/lock/helpers.js +379 -0
  180. package/lib/commands/log.js +170 -166
  181. package/lib/commands/media-projection.js +75 -70
  182. package/lib/commands/memory.js +17 -29
  183. package/lib/commands/misc.js +94 -0
  184. package/lib/commands/network.js +209 -223
  185. package/lib/commands/performance.js +88 -73
  186. package/lib/commands/permissions.js +83 -84
  187. package/lib/commands/recordscreen.js +171 -170
  188. package/lib/commands/resources.js +96 -0
  189. package/lib/commands/shell.js +28 -42
  190. package/lib/commands/streamscreen.js +207 -206
  191. package/lib/commands/system-bars.js +76 -77
  192. package/lib/commands/time.js +36 -0
  193. package/lib/commands/touch.js +442 -346
  194. package/lib/commands/types.ts +123 -2
  195. package/lib/doctor/checks.js +24 -16
  196. package/lib/driver.ts +454 -12
  197. package/lib/index.ts +1 -13
  198. package/lib/logger.js +1 -1
  199. package/lib/method-map.js +0 -11
  200. package/lib/utils.js +40 -3
  201. package/package.json +2 -2
  202. package/build/lib/commands/actions.d.ts +0 -8
  203. package/build/lib/commands/actions.d.ts.map +0 -1
  204. package/build/lib/commands/actions.js +0 -207
  205. package/build/lib/commands/actions.js.map +0 -1
  206. package/build/lib/commands/alert.d.ts +0 -8
  207. package/build/lib/commands/alert.d.ts.map +0 -1
  208. package/build/lib/commands/alert.js +0 -29
  209. package/build/lib/commands/alert.js.map +0 -1
  210. package/build/lib/commands/context.d.ts +0 -10
  211. package/build/lib/commands/context.d.ts.map +0 -1
  212. package/build/lib/commands/context.js +0 -431
  213. package/build/lib/commands/context.js.map +0 -1
  214. package/build/lib/commands/emu-console.d.ts +0 -7
  215. package/build/lib/commands/emu-console.d.ts.map +0 -1
  216. package/build/lib/commands/emu-console.js +0 -27
  217. package/build/lib/commands/emu-console.js.map +0 -1
  218. package/build/lib/commands/general.d.ts +0 -9
  219. package/build/lib/commands/general.d.ts.map +0 -1
  220. package/build/lib/commands/general.js +0 -293
  221. package/build/lib/commands/general.js.map +0 -1
  222. package/build/lib/commands/index.d.ts +0 -28
  223. package/build/lib/commands/index.d.ts.map +0 -1
  224. package/build/lib/commands/index.js +0 -57
  225. package/build/lib/commands/index.js.map +0 -1
  226. package/build/lib/commands/mixins.d.ts +0 -747
  227. package/build/lib/commands/mixins.d.ts.map +0 -1
  228. package/build/lib/commands/mixins.js +0 -19
  229. package/build/lib/commands/mixins.js.map +0 -1
  230. package/build/lib/helpers/android.d.ts +0 -163
  231. package/build/lib/helpers/android.d.ts.map +0 -1
  232. package/build/lib/helpers/android.js +0 -818
  233. package/build/lib/helpers/android.js.map +0 -1
  234. package/build/lib/helpers/index.d.ts +0 -7
  235. package/build/lib/helpers/index.d.ts.map +0 -1
  236. package/build/lib/helpers/index.js +0 -29
  237. package/build/lib/helpers/index.js.map +0 -1
  238. package/build/lib/helpers/types.d.ts +0 -122
  239. package/build/lib/helpers/types.d.ts.map +0 -1
  240. package/build/lib/helpers/types.js +0 -3
  241. package/build/lib/helpers/types.js.map +0 -1
  242. package/build/lib/helpers/unlock.d.ts +0 -32
  243. package/build/lib/helpers/unlock.d.ts.map +0 -1
  244. package/build/lib/helpers/unlock.js +0 -273
  245. package/build/lib/helpers/unlock.js.map +0 -1
  246. package/build/lib/helpers/webview.d.ts +0 -74
  247. package/build/lib/helpers/webview.d.ts.map +0 -1
  248. package/build/lib/helpers/webview.js +0 -448
  249. package/build/lib/helpers/webview.js.map +0 -1
  250. package/lib/commands/actions.js +0 -244
  251. package/lib/commands/alert.js +0 -34
  252. package/lib/commands/context.js +0 -507
  253. package/lib/commands/emu-console.js +0 -31
  254. package/lib/commands/general.js +0 -343
  255. package/lib/commands/index.ts +0 -54
  256. package/lib/commands/mixins.ts +0 -976
  257. package/lib/helpers/android.ts +0 -1153
  258. package/lib/helpers/index.ts +0 -6
  259. package/lib/helpers/types.ts +0 -136
  260. package/lib/helpers/unlock.ts +0 -329
  261. package/lib/helpers/webview.ts +0 -610
@@ -10,7 +10,6 @@ import net from 'node:net';
10
10
  import url from 'node:url';
11
11
  import {checkPortStatus} from 'portscanner';
12
12
  import {SubProcess, exec} from 'teen_process';
13
- import {mixin} from './mixins';
14
13
 
15
14
  const RECORDING_INTERVAL_SEC = 5;
16
15
  const STREAMING_STARTUP_TIMEOUT_MS = 5000;
@@ -34,6 +33,201 @@ const BOUNDARY_STRING = '--2ae9746887f170b8cf7c271047ce314c';
34
33
 
35
34
  const ADB_SCREEN_STREAMING_FEATURE = 'adb_screen_streaming';
36
35
 
36
+ /**
37
+ * @this {import('../driver').AndroidDriver}
38
+ * @param {import('./types').StartScreenStreamingOpts} [options={}]
39
+ * @returns {Promise<void>}
40
+ */
41
+ export async function mobileStartScreenStreaming(options = {}) {
42
+ this.ensureFeatureEnabled(ADB_SCREEN_STREAMING_FEATURE);
43
+
44
+ const {
45
+ width,
46
+ height,
47
+ bitRate,
48
+ host = DEFAULT_HOST,
49
+ port = DEFAULT_PORT,
50
+ pathname,
51
+ tcpPort = DEFAULT_PORT + 1,
52
+ quality = DEFAULT_QUALITY,
53
+ considerRotation = false,
54
+ logPipelineDetails = false,
55
+ } = options;
56
+ if (_.isUndefined(this._screenStreamingProps)) {
57
+ await verifyStreamingRequirements(this.adb);
58
+ }
59
+ if (!_.isEmpty(this._screenStreamingProps)) {
60
+ this.log.info(
61
+ `The screen streaming session is already running. ` +
62
+ `Stop it first in order to start a new one.`,
63
+ );
64
+ return;
65
+ }
66
+ if ((await checkPortStatus(port, host)) === 'open') {
67
+ this.log.info(
68
+ `The port #${port} at ${host} is busy. ` + `Assuming the screen streaming is already running`,
69
+ );
70
+ return;
71
+ }
72
+ if ((await checkPortStatus(tcpPort, TCP_HOST)) === 'open') {
73
+ this.log.errorAndThrow(
74
+ `The port #${tcpPort} at ${TCP_HOST} is busy. ` +
75
+ `Make sure there are no leftovers from previous sessions.`,
76
+ );
77
+ }
78
+ this._screenStreamingProps = undefined;
79
+
80
+ const deviceInfo = await getDeviceInfo(this.adb, this.log);
81
+ const deviceStreamingProc = await initDeviceStreamingProc(this.adb, this.log, deviceInfo, {
82
+ width,
83
+ height,
84
+ bitRate,
85
+ });
86
+ let gstreamerPipeline;
87
+ try {
88
+ gstreamerPipeline = await initGstreamerPipeline(deviceStreamingProc, deviceInfo, this.log, {
89
+ width,
90
+ height,
91
+ quality,
92
+ tcpPort,
93
+ considerRotation,
94
+ logPipelineDetails,
95
+ });
96
+ } catch (e) {
97
+ if (deviceStreamingProc.kill(0)) {
98
+ deviceStreamingProc.kill();
99
+ }
100
+ throw e;
101
+ }
102
+
103
+ /** @type {import('node:net').Socket|undefined} */
104
+ let mjpegSocket;
105
+ /** @type {import('node:http').Server|undefined} */
106
+ let mjpegServer;
107
+ try {
108
+ await new B((resolve, reject) => {
109
+ mjpegSocket = net.createConnection(tcpPort, TCP_HOST, () => {
110
+ this.log.info(`Successfully connected to MJPEG stream at tcp://${TCP_HOST}:${tcpPort}`);
111
+ mjpegServer = http.createServer((req, res) => {
112
+ const remoteAddress = extractRemoteAddress(req);
113
+ const currentPathname = url.parse(String(req.url)).pathname;
114
+ this.log.info(
115
+ `Got an incoming screen broadcasting request from ${remoteAddress} ` +
116
+ `(${req.headers['user-agent'] || 'User Agent unknown'}) at ${currentPathname}`,
117
+ );
118
+
119
+ if (pathname && currentPathname !== pathname) {
120
+ this.log.info(
121
+ 'Rejecting the broadcast request since it does not match the given pathname',
122
+ );
123
+ res.writeHead(404, {
124
+ Connection: 'close',
125
+ 'Content-Type': 'text/plain; charset=utf-8',
126
+ });
127
+ res.write(`'${currentPathname}' did not match any known endpoints`);
128
+ res.end();
129
+ return;
130
+ }
131
+
132
+ this.log.info('Starting MJPEG broadcast');
133
+ res.writeHead(200, {
134
+ 'Cache-Control':
135
+ 'no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0',
136
+ Pragma: 'no-cache',
137
+ Connection: 'close',
138
+ 'Content-Type': `multipart/x-mixed-replace; boundary=${BOUNDARY_STRING}`,
139
+ });
140
+
141
+ /** @type {import('node:net').Socket} */ (mjpegSocket).pipe(res);
142
+ });
143
+ mjpegServer.on('error', (e) => {
144
+ this.log.warn(e);
145
+ reject(e);
146
+ });
147
+ mjpegServer.on('close', () => {
148
+ this.log.debug(`MJPEG server at http://${host}:${port} has been closed`);
149
+ });
150
+ mjpegServer.on('listening', () => {
151
+ this.log.info(`Successfully started MJPEG server at http://${host}:${port}`);
152
+ resolve();
153
+ });
154
+ mjpegServer.listen(port, host);
155
+ });
156
+ mjpegSocket.on('error', (e) => {
157
+ this.log.error(e);
158
+ reject(e);
159
+ });
160
+ }).timeout(
161
+ STREAMING_STARTUP_TIMEOUT_MS,
162
+ `Cannot connect to the streaming server within ${STREAMING_STARTUP_TIMEOUT_MS}ms`,
163
+ );
164
+ } catch (e) {
165
+ if (deviceStreamingProc.kill(0)) {
166
+ deviceStreamingProc.kill();
167
+ }
168
+ if (gstreamerPipeline.isRunning) {
169
+ await gstreamerPipeline.stop();
170
+ }
171
+ if (mjpegSocket) {
172
+ mjpegSocket.destroy();
173
+ }
174
+ if (mjpegServer && mjpegServer.listening) {
175
+ mjpegServer.close();
176
+ }
177
+ throw e;
178
+ }
179
+
180
+ this._screenStreamingProps = {
181
+ deviceStreamingProc,
182
+ gstreamerPipeline,
183
+ mjpegSocket,
184
+ mjpegServer,
185
+ };
186
+ }
187
+
188
+ /**
189
+ * @this {import('../driver').AndroidDriver}
190
+ * @returns {Promise<void>}
191
+ */
192
+ export async function mobileStopScreenStreaming() {
193
+ if (_.isEmpty(this._screenStreamingProps)) {
194
+ if (!_.isUndefined(this._screenStreamingProps)) {
195
+ this.log.debug(`Screen streaming is not running. There is nothing to stop`);
196
+ }
197
+ return;
198
+ }
199
+
200
+ const {deviceStreamingProc, gstreamerPipeline, mjpegSocket, mjpegServer} =
201
+ this._screenStreamingProps;
202
+
203
+ try {
204
+ mjpegSocket.end();
205
+ if (mjpegServer.listening) {
206
+ mjpegServer.close();
207
+ }
208
+ if (deviceStreamingProc.kill(0)) {
209
+ deviceStreamingProc.kill('SIGINT');
210
+ }
211
+ if (gstreamerPipeline.isRunning) {
212
+ try {
213
+ await gstreamerPipeline.stop('SIGINT');
214
+ } catch (e) {
215
+ this.log.warn(e);
216
+ try {
217
+ await gstreamerPipeline.stop('SIGKILL');
218
+ } catch (e1) {
219
+ this.log.error(e1);
220
+ }
221
+ }
222
+ }
223
+ this.log.info(`Successfully terminated the screen streaming MJPEG server`);
224
+ } finally {
225
+ this._screenStreamingProps = undefined;
226
+ }
227
+ }
228
+
229
+ // #region Internal helpers
230
+
37
231
  /**
38
232
  *
39
233
  * @param {string} streamName
@@ -46,7 +240,7 @@ function createStreamingLogger(streamName, udid) {
46
240
  _.truncate(udid, {
47
241
  length: 8,
48
242
  omission: '',
49
- })
243
+ }),
50
244
  );
51
245
  }
52
246
 
@@ -57,7 +251,7 @@ function createStreamingLogger(streamName, udid) {
57
251
  async function verifyStreamingRequirements(adb) {
58
252
  if (!_.trim(await adb.shell(['which', SCREENRECORD_BINARY]))) {
59
253
  throw new Error(
60
- `The required '${SCREENRECORD_BINARY}' binary is not available on the device under test`
254
+ `The required '${SCREENRECORD_BINARY}' binary is not available on the device under test`,
61
255
  );
62
256
  }
63
257
 
@@ -70,10 +264,10 @@ async function verifyStreamingRequirements(adb) {
70
264
  } catch (e) {
71
265
  throw new Error(
72
266
  `The '${binaryName}' binary is not available in the PATH on the host system. ` +
73
- `See ${GST_TUTORIAL_URL} for more details on how to install it.`
267
+ `See ${GST_TUTORIAL_URL} for more details on how to install it.`,
74
268
  );
75
269
  }
76
- })()
270
+ })(),
77
271
  );
78
272
  }
79
273
  await B.all(gstreamerCheckPromises);
@@ -86,10 +280,10 @@ async function verifyStreamingRequirements(adb) {
86
280
  if (!_.includes(stdout, modName)) {
87
281
  throw new Error(
88
282
  `The required GStreamer plugin '${name}' from '${modName}' module is not installed. ` +
89
- `See ${GST_TUTORIAL_URL} for more details on how to install it.`
283
+ `See ${GST_TUTORIAL_URL} for more details on how to install it.`,
90
284
  );
91
285
  }
92
- })()
286
+ })(),
93
287
  );
94
288
  }
95
289
  await B.all(moduleCheckPromises);
@@ -118,7 +312,7 @@ async function getDeviceInfo(adb, log) {
118
312
  log?.debug(output);
119
313
  throw new Error(
120
314
  `Cannot parse the device ${key} from the adb command output. ` +
121
- `Check the server log for more details.`
315
+ `Check the server log for more details.`,
122
316
  );
123
317
  }
124
318
  result[key] = parseInt(match[1], 10);
@@ -198,7 +392,7 @@ async function initDeviceStreamingProc(adb, log, deviceInfo, opts = {}) {
198
392
  log.errorAndThrow(
199
393
  `Cannot start the screen streaming process. Original error: ${
200
394
  /** @type {Error} */ (e).message
201
- }`
395
+ }`,
202
396
  );
203
397
  } finally {
204
398
  deviceStreaming.stderr.removeListener('data', errorsListener);
@@ -253,7 +447,7 @@ async function initGstreamerPipeline(deviceStreamingProc, deviceInfo, log, opts)
253
447
  ],
254
448
  {
255
449
  stdio: [deviceStreamingProc.stdout, 'pipe', 'pipe'],
256
- }
450
+ },
257
451
  );
258
452
  gstreamerPipeline.on('exit', (code, signal) => {
259
453
  log.debug(`Pipeline streaming process exited with code ${code}, signal ${signal}`);
@@ -285,14 +479,14 @@ async function initGstreamerPipeline(deviceStreamingProc, deviceInfo, log, opts)
285
479
  {
286
480
  waitMs: STREAMING_STARTUP_TIMEOUT_MS,
287
481
  intervalMs: 300,
288
- }
482
+ },
289
483
  );
290
484
  } catch (e) {
291
485
  didFail = true;
292
486
  log.errorAndThrow(
293
487
  `Cannot start the screen streaming pipeline. Original error: ${
294
488
  /** @type {Error} */ (e).message
295
- }`
489
+ }`,
296
490
  );
297
491
  } finally {
298
492
  if (!logPipelineDetails || didFail) {
@@ -316,200 +510,7 @@ function extractRemoteAddress(req) {
316
510
  );
317
511
  }
318
512
 
319
- /**
320
- * @type {import('./mixins').StreamScreenMixin & ThisType<import('../driver').AndroidDriver>}
321
- * @satisfies {import('@appium/types').ExternalDriver}
322
- */
323
- const StreamScreenMixin = {
324
- async mobileStartScreenStreaming(options = {}) {
325
- this.ensureFeatureEnabled(ADB_SCREEN_STREAMING_FEATURE);
326
-
327
- const {
328
- width,
329
- height,
330
- bitRate,
331
- host = DEFAULT_HOST,
332
- port = DEFAULT_PORT,
333
- pathname,
334
- tcpPort = DEFAULT_PORT + 1,
335
- quality = DEFAULT_QUALITY,
336
- considerRotation = false,
337
- logPipelineDetails = false,
338
- } = options;
339
- if (_.isUndefined(this._screenStreamingProps)) {
340
- await verifyStreamingRequirements(this.adb);
341
- }
342
- if (!_.isEmpty(this._screenStreamingProps)) {
343
- this.log.info(
344
- `The screen streaming session is already running. ` +
345
- `Stop it first in order to start a new one.`
346
- );
347
- return;
348
- }
349
- if ((await checkPortStatus(port, host)) === 'open') {
350
- this.log.info(
351
- `The port #${port} at ${host} is busy. ` +
352
- `Assuming the screen streaming is already running`
353
- );
354
- return;
355
- }
356
- if ((await checkPortStatus(tcpPort, TCP_HOST)) === 'open') {
357
- this.log.errorAndThrow(
358
- `The port #${tcpPort} at ${TCP_HOST} is busy. ` +
359
- `Make sure there are no leftovers from previous sessions.`
360
- );
361
- }
362
- this._screenStreamingProps = undefined;
363
-
364
- const deviceInfo = await getDeviceInfo(this.adb, this.log);
365
- const deviceStreamingProc = await initDeviceStreamingProc(this.adb, this.log, deviceInfo, {
366
- width,
367
- height,
368
- bitRate,
369
- });
370
- let gstreamerPipeline;
371
- try {
372
- gstreamerPipeline = await initGstreamerPipeline(deviceStreamingProc, deviceInfo, this.log, {
373
- width,
374
- height,
375
- quality,
376
- tcpPort,
377
- considerRotation,
378
- logPipelineDetails,
379
- });
380
- } catch (e) {
381
- if (deviceStreamingProc.kill(0)) {
382
- deviceStreamingProc.kill();
383
- }
384
- throw e;
385
- }
386
-
387
- /** @type {import('node:net').Socket|undefined} */
388
- let mjpegSocket;
389
- /** @type {import('node:http').Server|undefined} */
390
- let mjpegServer;
391
- try {
392
- await new B((resolve, reject) => {
393
- mjpegSocket = net.createConnection(tcpPort, TCP_HOST, () => {
394
- this.log.info(`Successfully connected to MJPEG stream at tcp://${TCP_HOST}:${tcpPort}`);
395
- mjpegServer = http.createServer((req, res) => {
396
- const remoteAddress = extractRemoteAddress(req);
397
- const currentPathname = url.parse(String(req.url)).pathname;
398
- this.log.info(
399
- `Got an incoming screen broadcasting request from ${remoteAddress} ` +
400
- `(${req.headers['user-agent'] || 'User Agent unknown'}) at ${currentPathname}`
401
- );
402
-
403
- if (pathname && currentPathname !== pathname) {
404
- this.log.info(
405
- 'Rejecting the broadcast request since it does not match the given pathname'
406
- );
407
- res.writeHead(404, {
408
- Connection: 'close',
409
- 'Content-Type': 'text/plain; charset=utf-8',
410
- });
411
- res.write(`'${currentPathname}' did not match any known endpoints`);
412
- res.end();
413
- return;
414
- }
415
-
416
- this.log.info('Starting MJPEG broadcast');
417
- res.writeHead(200, {
418
- 'Cache-Control':
419
- 'no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0',
420
- Pragma: 'no-cache',
421
- Connection: 'close',
422
- 'Content-Type': `multipart/x-mixed-replace; boundary=${BOUNDARY_STRING}`,
423
- });
424
-
425
- /** @type {import('node:net').Socket} */ (mjpegSocket).pipe(res);
426
- });
427
- mjpegServer.on('error', (e) => {
428
- this.log.warn(e);
429
- reject(e);
430
- });
431
- mjpegServer.on('close', () => {
432
- this.log.debug(`MJPEG server at http://${host}:${port} has been closed`);
433
- });
434
- mjpegServer.on('listening', () => {
435
- this.log.info(`Successfully started MJPEG server at http://${host}:${port}`);
436
- resolve();
437
- });
438
- mjpegServer.listen(port, host);
439
- });
440
- mjpegSocket.on('error', (e) => {
441
- this.log.error(e);
442
- reject(e);
443
- });
444
- }).timeout(
445
- STREAMING_STARTUP_TIMEOUT_MS,
446
- `Cannot connect to the streaming server within ${STREAMING_STARTUP_TIMEOUT_MS}ms`
447
- );
448
- } catch (e) {
449
- if (deviceStreamingProc.kill(0)) {
450
- deviceStreamingProc.kill();
451
- }
452
- if (gstreamerPipeline.isRunning) {
453
- await gstreamerPipeline.stop();
454
- }
455
- if (mjpegSocket) {
456
- mjpegSocket.destroy();
457
- }
458
- if (mjpegServer && mjpegServer.listening) {
459
- mjpegServer.close();
460
- }
461
- throw e;
462
- }
463
-
464
- this._screenStreamingProps = {
465
- deviceStreamingProc,
466
- gstreamerPipeline,
467
- mjpegSocket,
468
- mjpegServer,
469
- };
470
- },
471
-
472
- async mobileStopScreenStreaming() {
473
- if (_.isEmpty(this._screenStreamingProps)) {
474
- if (!_.isUndefined(this._screenStreamingProps)) {
475
- this.log.debug(`Screen streaming is not running. There is nothing to stop`);
476
- }
477
- return;
478
- }
479
-
480
- const {deviceStreamingProc, gstreamerPipeline, mjpegSocket, mjpegServer} =
481
- this._screenStreamingProps;
482
-
483
- try {
484
- mjpegSocket.end();
485
- if (mjpegServer.listening) {
486
- mjpegServer.close();
487
- }
488
- if (deviceStreamingProc.kill(0)) {
489
- deviceStreamingProc.kill('SIGINT');
490
- }
491
- if (gstreamerPipeline.isRunning) {
492
- try {
493
- await gstreamerPipeline.stop('SIGINT');
494
- } catch (e) {
495
- this.log.warn(e);
496
- try {
497
- await gstreamerPipeline.stop('SIGKILL');
498
- } catch (e1) {
499
- this.log.error(e1);
500
- }
501
- }
502
- }
503
- this.log.info(`Successfully terminated the screen streaming MJPEG server`);
504
- } finally {
505
- this._screenStreamingProps = undefined;
506
- }
507
- },
508
- };
509
-
510
- mixin(StreamScreenMixin);
511
-
512
- export default StreamScreenMixin;
513
+ // #endregion
513
514
 
514
515
  /**
515
516
  * @typedef {import('appium-adb').ADB} ADB