appium-adb 14.0.4 → 14.0.6

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.
@@ -3,30 +3,32 @@ import _ from 'lodash';
3
3
  import { retryInterval } from 'asyncbox';
4
4
  import { util } from '@appium/support';
5
5
  import B from 'bluebird';
6
+ import type { ADB } from '../adb.js';
7
+ import type { SetPropOpts } from './types.js';
8
+ import type { ExecError } from 'teen_process';
6
9
 
7
10
  const ANIMATION_SCALE_KEYS = [
8
11
  'animator_duration_scale',
9
12
  'transition_animation_scale',
10
13
  'window_animation_scale'
11
- ];
14
+ ] as const;
12
15
  const HIDDEN_API_POLICY_KEYS = [
13
16
  'hidden_api_policy_pre_p_apps',
14
17
  'hidden_api_policy_p_apps',
15
18
  'hidden_api_policy'
16
- ];
19
+ ] as const;
17
20
 
18
21
  /**
19
22
  * Get the particular property of the device under test.
20
23
  *
21
- * @this {import('../adb.js').ADB}
22
- * @param {string} property - The name of the property. This name should
24
+ * @param property - The name of the property. This name should
23
25
  * be known to _adb shell getprop_ tool.
24
26
  *
25
- * @return {Promise<string>} The value of the given property.
27
+ * @returns The value of the given property.
26
28
  */
27
- export async function getDeviceProperty (property) {
28
- let stdout = await this.shell(['getprop', property]);
29
- let val = stdout.trim();
29
+ export async function getDeviceProperty (this: ADB, property: string): Promise<string> {
30
+ const stdout = await this.shell(['getprop', property]);
31
+ const val = stdout.trim();
30
32
  log.debug(`Current device property '${property}': ${val}`);
31
33
  return val;
32
34
  }
@@ -34,15 +36,14 @@ export async function getDeviceProperty (property) {
34
36
  /**
35
37
  * Set the particular property of the device under test.
36
38
  *
37
- * @this {import('../adb.js').ADB}
38
- * @param {string} prop - The name of the property. This name should
39
+ * @param prop - The name of the property. This name should
39
40
  * be known to _adb shell setprop_ tool.
40
- * @param {string} val - The new property value.
41
- * @param {import('./types').SetPropOpts} [opts={}]
41
+ * @param val - The new property value.
42
+ * @param opts
42
43
  *
43
- * @throws {error} If _setprop_ utility fails to change property value.
44
+ * @throws If _setprop_ utility fails to change property value.
44
45
  */
45
- export async function setDeviceProperty (prop, val, opts = {}) {
46
+ export async function setDeviceProperty (this: ADB, prop: string, val: string, opts: SetPropOpts = {}): Promise<void> {
46
47
  const {privileged = true} = opts;
47
48
  log.debug(`Setting device property '${prop}' to '${val}'`);
48
49
  await this.shell(['setprop', prop, val], {
@@ -51,79 +52,70 @@ export async function setDeviceProperty (prop, val, opts = {}) {
51
52
  }
52
53
 
53
54
  /**
54
- * @this {import('../adb.js').ADB}
55
- * @return {Promise<string>} Current system language on the device under test.
55
+ * @returns Current system language on the device under test.
56
56
  */
57
- export async function getDeviceSysLanguage () {
57
+ export async function getDeviceSysLanguage (this: ADB): Promise<string> {
58
58
  return await this.getDeviceProperty('persist.sys.language');
59
59
  }
60
60
 
61
61
  /**
62
- * @this {import('../adb.js').ADB}
63
- * @return {Promise<string>} Current country name on the device under test.
62
+ * @returns Current country name on the device under test.
64
63
  */
65
- export async function getDeviceSysCountry () {
64
+ export async function getDeviceSysCountry (this: ADB): Promise<string> {
66
65
  return await this.getDeviceProperty('persist.sys.country');
67
66
  }
68
67
 
69
68
  /**
70
- * @this {import('../adb.js').ADB}
71
- * @return {Promise<string>} Current system locale name on the device under test.
69
+ * @returns Current system locale name on the device under test.
72
70
  */
73
- export async function getDeviceSysLocale () {
71
+ export async function getDeviceSysLocale (this: ADB): Promise<string> {
74
72
  return await this.getDeviceProperty('persist.sys.locale');
75
73
  }
76
74
 
77
75
  /**
78
- * @this {import('../adb.js').ADB}
79
- * @return {Promise<string>} Current product language name on the device under test.
76
+ * @returns Current product language name on the device under test.
80
77
  */
81
- export async function getDeviceProductLanguage () {
78
+ export async function getDeviceProductLanguage (this: ADB): Promise<string> {
82
79
  return await this.getDeviceProperty('ro.product.locale.language');
83
80
  }
84
81
 
85
82
  /**
86
- * @this {import('../adb.js').ADB}
87
- * @return {Promise<string>} Current product country name on the device under test.
83
+ * @returns Current product country name on the device under test.
88
84
  */
89
- export async function getDeviceProductCountry () {
85
+ export async function getDeviceProductCountry (this: ADB): Promise<string> {
90
86
  return await this.getDeviceProperty('ro.product.locale.region');
91
87
  }
92
88
 
93
89
  /**
94
- * @this {import('../adb.js').ADB}
95
- * @return {Promise<string>} Current product locale name on the device under test.
90
+ * @returns Current product locale name on the device under test.
96
91
  */
97
- export async function getDeviceProductLocale () {
92
+ export async function getDeviceProductLocale (this: ADB): Promise<string> {
98
93
  return await this.getDeviceProperty('ro.product.locale');
99
94
  }
100
95
 
101
96
  /**
102
- * @this {import('../adb.js').ADB}
103
- * @return {Promise<string>} The model name of the device under test.
97
+ * @returns The model name of the device under test.
104
98
  */
105
- export async function getModel () {
99
+ export async function getModel (this: ADB): Promise<string> {
106
100
  return await this.getDeviceProperty('ro.product.model');
107
101
  }
108
102
 
109
103
  /**
110
- * @this {import('../adb.js').ADB}
111
- * @return {Promise<string>} The manufacturer name of the device under test.
104
+ * @returns The manufacturer name of the device under test.
112
105
  */
113
- export async function getManufacturer () {
106
+ export async function getManufacturer (this: ADB): Promise<string> {
114
107
  return await this.getDeviceProperty('ro.product.manufacturer');
115
108
  }
116
109
 
117
110
  /**
118
111
  * Get the current screen size.
119
112
  *
120
- * @this {import('../adb.js').ADB}
121
- * @return {Promise<string?>} Device screen size as string in format 'WxH' or
113
+ * @returns Device screen size as string in format 'WxH' or
122
114
  * _null_ if it cannot be determined.
123
115
  */
124
- export async function getScreenSize () {
125
- let stdout = await this.shell(['wm', 'size']);
126
- let size = new RegExp(/Physical size: ([^\r?\n]+)*/g).exec(stdout);
116
+ export async function getScreenSize (this: ADB): Promise<string | null> {
117
+ const stdout = await this.shell(['wm', 'size']);
118
+ const size = new RegExp(/Physical size: ([^\r?\n]+)*/g).exec(stdout);
127
119
  if (size && size.length >= 2) {
128
120
  return size[1].trim();
129
121
  }
@@ -133,15 +125,14 @@ export async function getScreenSize () {
133
125
  /**
134
126
  * Get the current screen density in dpi
135
127
  *
136
- * @this {import('../adb.js').ADB}
137
- * @return {Promise<number?>} Device screen density as a number or _null_ if it
128
+ * @returns Device screen density as a number or _null_ if it
138
129
  * cannot be determined
139
130
  */
140
- export async function getScreenDensity () {
141
- let stdout = await this.shell(['wm', 'density']);
142
- let density = new RegExp(/Physical density: ([^\r?\n]+)*/g).exec(stdout);
131
+ export async function getScreenDensity (this: ADB): Promise<number | null> {
132
+ const stdout = await this.shell(['wm', 'density']);
133
+ const density = new RegExp(/Physical density: ([^\r?\n]+)*/g).exec(stdout);
143
134
  if (density && density.length >= 2) {
144
- let densityNumber = parseInt(density[1].trim(), 10);
135
+ const densityNumber = parseInt(density[1].trim(), 10);
145
136
  return isNaN(densityNumber) ? null : densityNumber;
146
137
  }
147
138
  return null;
@@ -151,12 +142,11 @@ export async function getScreenDensity () {
151
142
  * Setup HTTP proxy in device global settings.
152
143
  * Read https://android.googlesource.com/platform/frameworks/base/+/android-9.0.0_r21/core/java/android/provider/Settings.java for each property
153
144
  *
154
- * @this {import('../adb.js').ADB}
155
- * @param {string} proxyHost - The host name of the proxy.
156
- * @param {string|number} proxyPort - The port number to be set.
145
+ * @param proxyHost - The host name of the proxy.
146
+ * @param proxyPort - The port number to be set.
157
147
  */
158
- export async function setHttpProxy (proxyHost, proxyPort) {
159
- let proxy = `${proxyHost}:${proxyPort}`;
148
+ export async function setHttpProxy (this: ADB, proxyHost: string, proxyPort: string | number): Promise<void> {
149
+ const proxy = `${proxyHost}:${proxyPort}`;
160
150
  if (_.isUndefined(proxyHost)) {
161
151
  throw new Error(`Call to setHttpProxy method with undefined proxy_host: ${proxy}`);
162
152
  }
@@ -165,7 +155,7 @@ export async function setHttpProxy (proxyHost, proxyPort) {
165
155
  }
166
156
 
167
157
  /** @type {[string, string][]} */
168
- const httpProxySettins = [
158
+ const httpProxySettins: [string, string][] = [
169
159
  ['http_proxy', proxy],
170
160
  ['global_http_proxy_host', proxyHost],
171
161
  ['global_http_proxy_port', `${proxyPort}`]
@@ -178,9 +168,8 @@ export async function setHttpProxy (proxyHost, proxyPort) {
178
168
  /**
179
169
  * Delete HTTP proxy in device global settings.
180
170
  * Rebooting the test device is necessary to apply the change.
181
- * @this {import('../adb.js').ADB}
182
171
  */
183
- export async function deleteHttpProxy () {
172
+ export async function deleteHttpProxy (this: ADB): Promise<void> {
184
173
  const httpProxySettins = [
185
174
  'http_proxy',
186
175
  'global_http_proxy_host',
@@ -196,13 +185,12 @@ export async function deleteHttpProxy () {
196
185
  * Set device property.
197
186
  * [android.provider.Settings]{@link https://developer.android.com/reference/android/provider/Settings.html}
198
187
  *
199
- * @this {import('../adb.js').ADB}
200
- * @param {string} namespace - one of {system, secure, global}, case-insensitive.
201
- * @param {string} setting - property name.
202
- * @param {string|number} value - property value.
203
- * @return {Promise<string>} command output.
188
+ * @param namespace - one of {system, secure, global}, case-insensitive.
189
+ * @param setting - property name.
190
+ * @param value - property value.
191
+ * @returns command output.
204
192
  */
205
- export async function setSetting (namespace, setting, value) {
193
+ export async function setSetting (this: ADB, namespace: string, setting: string, value: string | number): Promise<string> {
206
194
  return await this.shell(['settings', 'put', namespace, setting, `${value}`]);
207
195
  }
208
196
 
@@ -210,46 +198,45 @@ export async function setSetting (namespace, setting, value) {
210
198
  * Get device property.
211
199
  * [android.provider.Settings]{@link https://developer.android.com/reference/android/provider/Settings.html}
212
200
  *
213
- * @this {import('../adb.js').ADB}
214
- * @param {string} namespace - one of {system, secure, global}, case-insensitive.
215
- * @param {string} setting - property name.
216
- * @return {Promise<string>} property value.
201
+ * @param namespace - one of {system, secure, global}, case-insensitive.
202
+ * @param setting - property name.
203
+ * @returns property value.
217
204
  */
218
- export async function getSetting (namespace, setting) {
205
+ export async function getSetting (this: ADB, namespace: string, setting: string): Promise<string> {
219
206
  return await this.shell(['settings', 'get', namespace, setting]);
220
207
  }
221
208
 
222
209
  /**
223
210
  * Get tz database time zone formatted timezone
224
211
  *
225
- * @this {import('../adb.js').ADB}
226
- * @returns {Promise<string>} TZ database Time Zones format
227
- * @throws {Error} If any exception is reported by adb shell.
212
+ * @returns TZ database Time Zones format
213
+ * @throws If any exception is reported by adb shell.
228
214
  */
229
- export async function getTimeZone () {
215
+ export async function getTimeZone (this: ADB): Promise<string> {
230
216
  log.debug('Getting current timezone');
231
217
  try {
232
218
  return await this.getDeviceProperty('persist.sys.timezone');
233
219
  } catch (e) {
234
- throw new Error(`Error getting timezone. Original error: ${(/** @type {Error} */ (e)).message}`);
220
+ const err = e as Error;
221
+ throw new Error(`Error getting timezone. Original error: ${err.message}`);
235
222
  }
236
223
  }
237
224
 
238
225
  /**
239
226
  * Retrieve the platform version of the device under test.
240
227
  *
241
- * @this {import('../adb.js').ADB}
242
- * @return {Promise<string>} The platform version as a string, for example '5.0' for
228
+ * @returns The platform version as a string, for example '5.0' for
243
229
  * Android Lollipop.
244
230
  */
245
- export async function getPlatformVersion () {
231
+ export async function getPlatformVersion (this: ADB): Promise<string> {
246
232
  log.info('Getting device platform version');
247
233
  try {
248
234
  return await this.getDeviceProperty('ro.build.version.release');
249
235
  } catch (e) {
236
+ const err = e as Error;
250
237
  throw new Error(
251
238
  `Error getting device platform version. ` +
252
- `Original error: ${(/**@type {Error} */ (e)).message}`
239
+ `Original error: ${err.message}`
253
240
  );
254
241
  }
255
242
  }
@@ -258,10 +245,9 @@ export async function getPlatformVersion () {
258
245
  /**
259
246
  * Retrieve the list of location providers for the device under test.
260
247
  *
261
- * @this {import('../adb.js').ADB}
262
- * @return {Promise<string[]>} The list of available location providers or an empty list.
248
+ * @returns The list of available location providers or an empty list.
263
249
  */
264
- export async function getLocationProviders () {
250
+ export async function getLocationProviders (this: ADB): Promise<string[]> {
265
251
  if (await this.getApiLevel() < 31) {
266
252
  // https://stackoverflow.com/questions/70939503/settings-secure-location-providers-allowed-returns-null-in-android-12
267
253
  const stdout = await this.getSetting('secure', 'location_providers_allowed');
@@ -279,10 +265,9 @@ export async function getLocationProviders () {
279
265
  /**
280
266
  * Toggle the state of GPS location provider.
281
267
  *
282
- * @this {import('../adb.js').ADB}
283
- * @param {boolean} enabled - Whether to enable (true) or disable (false) the GPS provider.
268
+ * @param enabled - Whether to enable (true) or disable (false) the GPS provider.
284
269
  */
285
- export async function toggleGPSLocationProvider (enabled) {
270
+ export async function toggleGPSLocationProvider (this: ADB, enabled: boolean): Promise<void> {
286
271
  if (await this.getApiLevel() < 31) {
287
272
  // https://stackoverflow.com/questions/70939503/settings-secure-location-providers-allowed-returns-null-in-android-12
288
273
  await this.setSetting('secure', 'location_providers_allowed', `${enabled ? '+' : '-'}gps`);
@@ -294,10 +279,10 @@ export async function toggleGPSLocationProvider (enabled) {
294
279
  /**
295
280
  * Decorates an exception message with a solution link
296
281
  *
297
- * @param {Error} e The error object to be decorated
298
- * @returns {Error} Either the same error or the decorated one
282
+ * @param e The error object to be decorated
283
+ * @returns Either the same error or the decorated one
299
284
  */
300
- function decorateWriteSecureSettingsException (e) {
285
+ function decorateWriteSecureSettingsException (e: Error): Error {
301
286
  if (_.includes(e.message, 'requires:android.permission.WRITE_SECURE_SETTINGS')) {
302
287
  e.message = `Check https://github.com/appium/appium/issues/13802 for throubleshooting. ${e.message}`;
303
288
  }
@@ -308,8 +293,7 @@ function decorateWriteSecureSettingsException (e) {
308
293
  * Set hidden api policy to manage access to non-SDK APIs.
309
294
  * https://developer.android.com/preview/restrictions-non-sdk-interfaces
310
295
  *
311
- * @this {import('../adb.js').ADB}
312
- * @param {number|string} value - The API enforcement policy.
296
+ * @param value - The API enforcement policy.
313
297
  * For Android P
314
298
  * 0: Disable non-SDK API usage detection. This will also disable logging, and also break the strict mode API,
315
299
  * detectNonSdkApiUsage(). Not recommended.
@@ -327,15 +311,15 @@ function decorateWriteSecureSettingsException (e) {
327
311
  * 2: Disallow usage of non-SDK interfaces that belong to either the black list
328
312
  * or to a restricted greylist for your target API level.
329
313
  *
330
- * @param {boolean} [ignoreError=false] Whether to ignore an exception in 'adb shell settings put global' command
331
- * @throws {error} If there was an error and ignoreError was true while executing 'adb shell settings put global'
314
+ * @param ignoreError - Whether to ignore an exception in 'adb shell settings put global' command
315
+ * @throws If there was an error and ignoreError was true while executing 'adb shell settings put global'
332
316
  * command on the device under test.
333
317
  */
334
- export async function setHiddenApiPolicy (value, ignoreError = false) {
318
+ export async function setHiddenApiPolicy (this: ADB, value: number | string, ignoreError = false): Promise<void> {
335
319
  try {
336
320
  await this.shell(HIDDEN_API_POLICY_KEYS.map((k) => `settings put global ${k} ${value}`).join(';'));
337
321
  } catch (e) {
338
- const err = /** @type {Error} */ (e);
322
+ const err = e as Error;
339
323
  if (!ignoreError) {
340
324
  throw decorateWriteSecureSettingsException(err);
341
325
  }
@@ -350,16 +334,15 @@ export async function setHiddenApiPolicy (value, ignoreError = false) {
350
334
  * Reset access to non-SDK APIs to its default setting.
351
335
  * https://developer.android.com/preview/restrictions-non-sdk-interfaces
352
336
  *
353
- * @this {import('../adb.js').ADB}
354
- * @param {boolean} [ignoreError=false] Whether to ignore an exception in 'adb shell settings delete global' command
355
- * @throws {error} If there was an error and ignoreError was true while executing 'adb shell settings delete global'
337
+ * @param ignoreError - Whether to ignore an exception in 'adb shell settings delete global' command
338
+ * @throws If there was an error and ignoreError was true while executing 'adb shell settings delete global'
356
339
  * command on the device under test.
357
340
  */
358
- export async function setDefaultHiddenApiPolicy (ignoreError = false) {
341
+ export async function setDefaultHiddenApiPolicy (this: ADB, ignoreError = false): Promise<void> {
359
342
  try {
360
343
  await this.shell(HIDDEN_API_POLICY_KEYS.map((k) => `settings delete global ${k}`).join(';'));
361
344
  } catch (e) {
362
- const err = /** @type {Error} */ (e);
345
+ const err = e as Error;
363
346
  if (!ignoreError) {
364
347
  throw decorateWriteSecureSettingsException(err);
365
348
  }
@@ -371,10 +354,9 @@ export async function setDefaultHiddenApiPolicy (ignoreError = false) {
371
354
  /**
372
355
  * Get the language name of the device under test.
373
356
  *
374
- * @this {import('../adb.js').ADB}
375
- * @return {Promise<string>} The name of device language.
357
+ * @returns The name of device language.
376
358
  */
377
- export async function getDeviceLanguage () {
359
+ export async function getDeviceLanguage (this: ADB): Promise<string> {
378
360
  return await this.getApiLevel() < 23
379
361
  ? (await this.getDeviceSysLanguage() || await this.getDeviceProductLanguage())
380
362
  : (await this.getDeviceLocale()).split('-')[0];
@@ -384,10 +366,9 @@ export async function getDeviceLanguage () {
384
366
  * Get the country name of the device under test.
385
367
  *
386
368
  * @summary Could only be used for Android API < 23
387
- * @this {import('../adb.js').ADB}
388
- * @return {Promise<string>} The name of device country.
369
+ * @returns The name of device country.
389
370
  */
390
- export async function getDeviceCountry () {
371
+ export async function getDeviceCountry (this: ADB): Promise<string> {
391
372
  return await this.getDeviceSysCountry() || await this.getDeviceProductCountry();
392
373
  }
393
374
 
@@ -395,25 +376,23 @@ export async function getDeviceCountry () {
395
376
  * Get the locale name of the device under test.
396
377
  *
397
378
  * @summary Could only be used for Android API >= 23
398
- * @this {import('../adb.js').ADB}
399
- * @return {Promise<string>} The name of device locale.
379
+ * @returns The name of device locale.
400
380
  */
401
- export async function getDeviceLocale () {
381
+ export async function getDeviceLocale (this: ADB): Promise<string> {
402
382
  return await this.getDeviceSysLocale() || await this.getDeviceProductLocale();
403
383
  }
404
384
 
405
385
  /**
406
386
  * Make sure current device locale is expected or not.
407
387
  *
408
- * @this {import('../adb.js').ADB}
409
388
  * @privateRemarks FIXME: language or country is required
410
- * @param {string} [language] - Language. The language field is case insensitive, but Locale always canonicalizes to lower case.
411
- * @param {string} [country] - Country. The language field is case insensitive, but Locale always canonicalizes to lower case.
412
- * @param {string} [script] - Script. The script field is case insensitive but Locale always canonicalizes to title case.
389
+ * @param language - Language. The language field is case insensitive, but Locale always canonicalizes to lower case.
390
+ * @param country - Country. The language field is case insensitive, but Locale always canonicalizes to lower case.
391
+ * @param script - Script. The script field is case insensitive but Locale always canonicalizes to title case.
413
392
  *
414
- * @return {Promise<boolean>} If current locale is language and country as arguments, return true.
393
+ * @returns If current locale is language and country as arguments, return true.
415
394
  */
416
- export async function ensureCurrentLocale (language, country, script) {
395
+ export async function ensureCurrentLocale (this: ADB, language?: string, country?: string, script?: string): Promise<boolean> {
417
396
  const hasLanguage = _.isString(language);
418
397
  const hasCountry = _.isString(country);
419
398
  if (!hasLanguage && !hasCountry) {
@@ -424,10 +403,10 @@ export async function ensureCurrentLocale (language, country, script) {
424
403
  const lcLanguage = (language || '').toLowerCase();
425
404
  const lcCountry = (country || '').toLowerCase();
426
405
  const apiLevel = await this.getApiLevel();
427
- return /** @type {boolean} */ (await retryInterval(5, 1000, async () => {
406
+ return (await retryInterval(5, 1000, async () => {
428
407
  if (apiLevel < 23) {
429
408
  log.debug(`Requested locale: ${lcLanguage}-${lcCountry}`);
430
- let actualLanguage;
409
+ let actualLanguage: string | undefined;
431
410
  if (hasLanguage) {
432
411
  actualLanguage = (await this.getDeviceLanguage()).toLowerCase();
433
412
  log.debug(`Actual language: ${actualLanguage}`);
@@ -435,7 +414,7 @@ export async function ensureCurrentLocale (language, country, script) {
435
414
  return true;
436
415
  }
437
416
  }
438
- let actualCountry;
417
+ let actualCountry: string | undefined;
439
418
  if (hasCountry) {
440
419
  actualCountry = (await this.getDeviceCountry()).toLowerCase();
441
420
  log.debug(`Actual country: ${actualCountry}`);
@@ -452,7 +431,7 @@ export async function ensureCurrentLocale (language, country, script) {
452
431
  : `${lcLanguage}-${lcCountry}`;
453
432
  log.debug(`Requested locale: ${expectedLocale}. Actual locale: '${actualLocale}'`);
454
433
  const languagePattern = `^${_.escapeRegExp(lcLanguage)}-${script ? (_.escapeRegExp(script) + '-') : ''}`;
455
- const checkLocalePattern = (/** @type {string} */ p) => new RegExp(p, 'i').test(actualLocale);
434
+ const checkLocalePattern = (p: string) => new RegExp(p, 'i').test(actualLocale);
456
435
  if (hasLanguage && !hasCountry) {
457
436
  return checkLocalePattern(languagePattern);
458
437
  }
@@ -461,19 +440,18 @@ export async function ensureCurrentLocale (language, country, script) {
461
440
  return checkLocalePattern(countryPattern);
462
441
  }
463
442
  return [languagePattern, countryPattern].every(checkLocalePattern);
464
- }));
443
+ })) ?? false;
465
444
  }
466
445
 
467
446
  /**
468
447
  * Change the state of WiFi on the device under test.
469
448
  * Only works for real devices since API 30
470
449
  *
471
- * @this {import('../adb.js').ADB}
472
- * @param {boolean} on - True to enable and false to disable it.
473
- * @param {boolean} [isEmulator=false] - Set it to true if the device under test
450
+ * @param on - True to enable and false to disable it.
451
+ * @param isEmulator - Set it to true if the device under test
474
452
  * is an emulator rather than a real device.
475
453
  */
476
- export async function setWifiState (on, isEmulator = false) {
454
+ export async function setWifiState (this: ADB, on: boolean, isEmulator = false): Promise<void> {
477
455
  if (isEmulator) {
478
456
  // The svc command does not require to be root since API 26
479
457
  await this.shell(['svc', 'wifi', on ? 'enable' : 'disable'], {
@@ -489,12 +467,11 @@ export async function setWifiState (on, isEmulator = false) {
489
467
  * Change the state of Data transfer on the device under test.
490
468
  * Only works for real devices since API 30
491
469
  *
492
- * @this {import('../adb.js').ADB}
493
- * @param {boolean} on - True to enable and false to disable it.
494
- * @param {boolean} [isEmulator=false] - Set it to true if the device under test
470
+ * @param on - True to enable and false to disable it.
471
+ * @param isEmulator - Set it to true if the device under test
495
472
  * is an emulator rather than a real device.
496
473
  */
497
- export async function setDataState (on, isEmulator = false) {
474
+ export async function setDataState (this: ADB, on: boolean, isEmulator = false): Promise<void> {
498
475
  if (isEmulator) {
499
476
  // The svc command does not require to be root since API 26
500
477
  await this.shell(['svc', 'data', on ? 'enable' : 'disable'], {
@@ -510,13 +487,12 @@ export async function setDataState (on, isEmulator = false) {
510
487
  /**
511
488
  * Retrieves the list of packages from Doze whitelist on Android 8+
512
489
  *
513
- * @this {import('../adb.js').ADB}
514
- * @returns {Promise<string[]>} The list of whitelisted packages. An example output:
490
+ * @returns The list of whitelisted packages. An example output:
515
491
  * system,com.android.shell,2000
516
492
  * system,com.google.android.cellbroadcastreceiver,10143
517
493
  * user,io.appium.settings,10157
518
494
  */
519
- export async function getDeviceIdleWhitelist () {
495
+ export async function getDeviceIdleWhitelist (this: ADB): Promise<string[]> {
520
496
  if (await this.getApiLevel() < 23) {
521
497
  // Doze mode has only been added since Android 6
522
498
  return [];
@@ -532,14 +508,13 @@ export async function getDeviceIdleWhitelist () {
532
508
  /**
533
509
  * Adds an existing package(s) into the Doze whitelist on Android 8+
534
510
  *
535
- * @this {import('../adb.js').ADB}
536
- * @param {...string} packages One or more packages to add. If the package
511
+ * @param packages One or more packages to add. If the package
537
512
  * already exists in the whitelist then it is only going to be added once.
538
513
  * If the package with the given name is not installed/not known then an error
539
514
  * will be thrown.
540
- * @returns {Promise<boolean>} `true` if the command to add package(s) has been executed
515
+ * @returns `true` if the command to add package(s) has been executed
541
516
  */
542
- export async function addToDeviceIdleWhitelist (...packages) {
517
+ export async function addToDeviceIdleWhitelist (this: ADB, ...packages: string[]): Promise<boolean> {
543
518
  if (_.isEmpty(packages) || await this.getApiLevel() < 23) {
544
519
  // Doze mode has only been added since Android 6
545
520
  return false;
@@ -554,10 +529,9 @@ export async function addToDeviceIdleWhitelist (...packages) {
554
529
  /**
555
530
  * Check the state of Airplane mode on the device under test.
556
531
  *
557
- * @this {import('../adb.js').ADB}
558
- * @return {Promise<boolean>} True if Airplane mode is enabled.
532
+ * @returns True if Airplane mode is enabled.
559
533
  */
560
- export async function isAirplaneModeOn () {
534
+ export async function isAirplaneModeOn (this: ADB): Promise<boolean> {
561
535
  const stdout = await this.getSetting('global', 'airplane_mode_on');
562
536
  return parseInt(stdout, 10) !== 0;
563
537
  // Alternatively for Android 11+:
@@ -567,10 +541,9 @@ export async function isAirplaneModeOn () {
567
541
  /**
568
542
  * Change the state of Airplane mode in Settings on the device under test.
569
543
  *
570
- * @this {import('../adb.js').ADB}
571
- * @param {boolean} on - True to enable the Airplane mode in Settings and false to disable it.
544
+ * @param on - True to enable the Airplane mode in Settings and false to disable it.
572
545
  */
573
- export async function setAirplaneMode (on) {
546
+ export async function setAirplaneMode (this: ADB, on: boolean): Promise<void> {
574
547
  if (await this.getApiLevel() < 30) {
575
548
  // This requires to call broadcastAirplaneMode afterwards to apply
576
549
  await this.setSetting('global', 'airplane_mode_on', on ? 1 : 0);
@@ -583,10 +556,9 @@ export async function setAirplaneMode (on) {
583
556
  /**
584
557
  * Change the state of the bluetooth service on the device under test.
585
558
  *
586
- * @this {import('../adb.js').ADB}
587
- * @param {boolean} on - True to enable bluetooth service and false to disable it.
559
+ * @param on - True to enable bluetooth service and false to disable it.
588
560
  */
589
- export async function setBluetoothOn (on) {
561
+ export async function setBluetoothOn (this: ADB, on: boolean): Promise<void> {
590
562
  if (await this.getApiLevel() < 30) {
591
563
  throw new Error('Changing of the bluetooth state is not supported on your device');
592
564
  }
@@ -597,14 +569,13 @@ export async function setBluetoothOn (on) {
597
569
  /**
598
570
  * Change the state of the NFC service on the device under test.
599
571
  *
600
- * @this {import('../adb.js').ADB}
601
- * @param {boolean} on - True to enable NFC service and false to disable it.
602
- * @throws {Error} If there was an error while changing the service state
572
+ * @param on - True to enable NFC service and false to disable it.
573
+ * @throws If there was an error while changing the service state
603
574
  */
604
- export async function setNfcOn (on) {
575
+ export async function setNfcOn (this: ADB, on: boolean): Promise<void> {
605
576
  const {stdout, stderr} = await this.shell(['svc', 'nfc', on ? 'enable' : 'disable'], {
606
577
  outputFormat: 'full'
607
- });
578
+ }) as {stdout: string; stderr: string};
608
579
  const output = stderr || stdout;
609
580
  log.debug(output);
610
581
  if (output.includes('null NfcAdapter')) {
@@ -622,10 +593,9 @@ export async function setNfcOn (on) {
622
593
  * there is a dedicated adb command to change airplane mode state, which
623
594
  * does not require to call this one afterwards.
624
595
  *
625
- * @this {import('../adb.js').ADB}
626
- * @param {boolean} on - True to broadcast enable and false to broadcast disable.
596
+ * @param on - True to broadcast enable and false to broadcast disable.
627
597
  */
628
- export async function broadcastAirplaneMode (on) {
598
+ export async function broadcastAirplaneMode (this: ADB, on: boolean): Promise<void> {
629
599
  const args = [
630
600
  'am', 'broadcast',
631
601
  '-a', 'android.intent.action.AIRPLANE_MODE',
@@ -634,7 +604,7 @@ export async function broadcastAirplaneMode (on) {
634
604
  try {
635
605
  await this.shell(args);
636
606
  } catch (e) {
637
- const err = /** @type {import('teen_process').ExecError} */(e);
607
+ const err = e as ExecError;
638
608
  // https://github.com/appium/appium/issues/17422
639
609
  if (_.includes(err.stderr, 'SecurityException')) {
640
610
  try {
@@ -649,10 +619,9 @@ export async function broadcastAirplaneMode (on) {
649
619
  /**
650
620
  * Check the state of WiFi on the device under test.
651
621
  *
652
- * @this {import('../adb.js').ADB}
653
- * @return {Promise<boolean>} True if WiFi is enabled.
622
+ * @returns True if WiFi is enabled.
654
623
  */
655
- export async function isWifiOn () {
624
+ export async function isWifiOn (this: ADB): Promise<boolean> {
656
625
  const stdout = await this.getSetting('global', 'wifi_on');
657
626
  return (parseInt(stdout, 10) !== 0);
658
627
  // Alternative for Android 11+:
@@ -662,10 +631,9 @@ export async function isWifiOn () {
662
631
  /**
663
632
  * Check the state of Data transfer on the device under test.
664
633
  *
665
- * @this {import('../adb.js').ADB}
666
- * @return {Promise<boolean>} True if Data transfer is enabled.
634
+ * @returns True if Data transfer is enabled.
667
635
  */
668
- export async function isDataOn () {
636
+ export async function isDataOn (this: ADB): Promise<boolean> {
669
637
  const stdout = await this.getSetting('global', 'mobile_data');
670
638
  return (parseInt(stdout, 10) !== 0);
671
639
  }
@@ -676,11 +644,10 @@ export async function isDataOn () {
676
644
  * - transition_animation_scale
677
645
  * - window_animation_scale
678
646
  *
679
- * @this {import('../adb.js').ADB}
680
- * @return {Promise<boolean>} True if at least one of animation scale settings
647
+ * @returns True if at least one of animation scale settings
681
648
  * is not equal to '0.0'.
682
649
  */
683
- export async function isAnimationOn () {
650
+ export async function isAnimationOn (this: ADB): Promise<boolean> {
684
651
  return (await B.all(ANIMATION_SCALE_KEYS.map(
685
652
  async (k) => (await this.getSetting('global', k)) !== '0.0'))
686
653
  ).includes(true);
@@ -695,26 +662,23 @@ export async function isAnimationOn () {
695
662
  * API level 28+ real devices checked this worked, but we haven't checked older ones
696
663
  * with real devices.
697
664
  *
698
- * @this {import('../adb.js').ADB}
699
- * @param {number} value Animation scale value (int or float) to set.
665
+ * @param value Animation scale value (int or float) to set.
700
666
  * The minimum value of zero disables animations.
701
667
  * By increasing the value, animations become slower.
702
668
  * '1' is the system default animation scale.
703
- * @return {Promise<void>}
704
- * @throws {Error} If the adb setting command raises an exception.
669
+ * @throws If the adb setting command raises an exception.
705
670
  */
706
- export async function setAnimationScale (value) {
671
+ export async function setAnimationScale (this: ADB, value: number): Promise<void> {
707
672
  await B.all(ANIMATION_SCALE_KEYS.map((k) => this.setSetting('global', k, value)));
708
673
  }
709
674
 
710
675
  /**
711
676
  * Retrieve current screen orientation of the device under test.
712
677
  *
713
- * @this {import('../adb.js').ADB}
714
- * @return {Promise<number?>} The current orientation encoded as an integer number.
678
+ * @returns The current orientation encoded as an integer number.
715
679
  */
716
- export async function getScreenOrientation () {
717
- let stdout = await this.shell(['dumpsys', 'input']);
680
+ export async function getScreenOrientation (this: ADB): Promise<number | null> {
681
+ const stdout = await this.shell(['dumpsys', 'input']);
718
682
  return getSurfaceOrientation(stdout);
719
683
  }
720
684
 
@@ -723,12 +687,12 @@ export async function getScreenOrientation () {
723
687
  /**
724
688
  * Reads SurfaceOrientation in dumpsys output
725
689
  *
726
- * @param {string} dumpsys
727
- * @returns {number | null}
690
+ * @param dumpsys
728
691
  */
729
- function getSurfaceOrientation (dumpsys) {
692
+ function getSurfaceOrientation (dumpsys: string): number | null {
730
693
  const m = /SurfaceOrientation: \d/gi.exec(dumpsys);
731
- return m && parseInt(m[0].split(':')[1], 10);
694
+ return m ? parseInt(m[0].split(':')[1], 10) : null;
732
695
  }
733
696
 
734
697
  // #endregion
698
+