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
@@ -0,0 +1,285 @@
1
+ import _ from 'lodash';
2
+ import {util} from '@appium/support';
3
+ import ADB from 'appium-adb';
4
+ import {retryInterval} from 'asyncbox';
5
+ import {
6
+ path as SETTINGS_APK_PATH,
7
+ SETTINGS_HELPER_ID,
8
+ UNICODE_IME,
9
+ EMPTY_IME,
10
+ } from 'io.appium.settings';
11
+ import B from 'bluebird';
12
+
13
+ const HELPER_APP_INSTALL_RETRIES = 3;
14
+ const HELPER_APP_INSTALL_RETRY_DELAY_MS = 5000;
15
+
16
+ /**
17
+ * @this {import('../../driver').AndroidDriver}
18
+ * @param {string} errMsg
19
+ */
20
+ export function requireEmulator(errMsg) {
21
+ if (!this.isEmulator()) {
22
+ this.log.errorAndThrow(errMsg);
23
+ }
24
+ }
25
+
26
+ /**
27
+ * @this {import('../../driver').AndroidDriver}
28
+ * @returns {void}
29
+ */
30
+ export function validatePackageActivityNames() {
31
+ for (const key of ['appPackage', 'appActivity', 'appWaitPackage', 'appWaitActivity']) {
32
+ const name = this.opts[key];
33
+ if (!name) {
34
+ continue;
35
+ }
36
+
37
+ const match = /([^\w.*,])+/.exec(String(name));
38
+ if (!match) {
39
+ continue;
40
+ }
41
+
42
+ this.log.warn(
43
+ `Capability '${key}' is expected to only include latin letters, digits, underscore, dot, comma and asterisk characters.`,
44
+ );
45
+ this.log.warn(
46
+ `Current value '${name}' has non-matching character at index ${match.index}: '${String(
47
+ name,
48
+ ).substring(0, match.index + 1)}'`,
49
+ );
50
+ }
51
+ }
52
+
53
+ /**
54
+ * @this {import('../../driver').AndroidDriver}
55
+ * @param {string} networkSpeed
56
+ * @returns {string}
57
+ */
58
+ export function ensureNetworkSpeed(networkSpeed) {
59
+ if (networkSpeed.toUpperCase() in this.adb.NETWORK_SPEED) {
60
+ return networkSpeed;
61
+ }
62
+ this.log.warn(
63
+ `Wrong network speed param '${networkSpeed}', using default: ${this.adb.NETWORK_SPEED.FULL}. ` +
64
+ `Supported values: ${_.values(this.adb.NETWORK_SPEED)}`,
65
+ );
66
+ return this.adb.NETWORK_SPEED.FULL;
67
+ }
68
+
69
+ /**
70
+ * @this {import('../../driver').AndroidDriver}
71
+ * @returns {string[]}
72
+ */
73
+ export function prepareAvdArgs() {
74
+ const {networkSpeed, isHeadless, avdArgs} = this.opts;
75
+ const result = [];
76
+ if (avdArgs) {
77
+ if (_.isArray(avdArgs)) {
78
+ result.push(...avdArgs);
79
+ } else {
80
+ result.push(...util.shellParse(`${avdArgs}`));
81
+ }
82
+ }
83
+ if (networkSpeed) {
84
+ result.push('-netspeed', ensureNetworkSpeed.bind(this)(networkSpeed));
85
+ }
86
+ if (isHeadless) {
87
+ result.push('-no-window');
88
+ }
89
+ return result;
90
+ }
91
+
92
+ /**
93
+ * @this {import('../../driver').AndroidDriver}
94
+ * @returns {Promise<void>}
95
+ */
96
+ export async function prepareEmulator() {
97
+ const {
98
+ avd,
99
+ avdEnv: env,
100
+ language,
101
+ locale: country,
102
+ avdLaunchTimeout: launchTimeout,
103
+ avdReadyTimeout: readyTimeout,
104
+ } = this.opts;
105
+ if (!avd) {
106
+ throw new Error('Cannot launch AVD without AVD name');
107
+ }
108
+
109
+ const avdName = avd.replace('@', '');
110
+ let isEmulatorRunning = true;
111
+ try {
112
+ await this.adb.getRunningAVDWithRetry(avdName, 5000);
113
+ } catch (e) {
114
+ this.log.debug(`Emulator '${avdName}' is not running: ${e.message}`);
115
+ isEmulatorRunning = false;
116
+ }
117
+ const args = prepareAvdArgs.bind(this)();
118
+ if (isEmulatorRunning) {
119
+ if (args.includes('-wipe-data')) {
120
+ this.log.debug(`Killing '${avdName}' because it needs to be wiped at start.`);
121
+ await this.adb.killEmulator(avdName);
122
+ } else {
123
+ this.log.debug('Not launching AVD because it is already running.');
124
+ return;
125
+ }
126
+ }
127
+ await this.adb.launchAVD(avd, {
128
+ args,
129
+ env,
130
+ language,
131
+ country,
132
+ launchTimeout,
133
+ readyTimeout,
134
+ });
135
+ }
136
+
137
+ /**
138
+ * @param {import('../../driver').AndroidDriverOpts?} [opts=null]
139
+ * @returns {Promise<ADB>}
140
+ */
141
+ export async function createBaseADB(opts = null) {
142
+ // filter out any unwanted options sent in
143
+ // this list should be updated as ADB takes more arguments
144
+ const {
145
+ adbPort,
146
+ suppressKillServer,
147
+ remoteAdbHost,
148
+ clearDeviceLogsOnStart,
149
+ adbExecTimeout,
150
+ useKeystore,
151
+ keystorePath,
152
+ keystorePassword,
153
+ keyAlias,
154
+ keyPassword,
155
+ remoteAppsCacheLimit,
156
+ buildToolsVersion,
157
+ allowOfflineDevices,
158
+ allowDelayAdb,
159
+ } = opts ?? {};
160
+ return await ADB.createADB({
161
+ adbPort,
162
+ suppressKillServer,
163
+ remoteAdbHost,
164
+ clearDeviceLogsOnStart,
165
+ adbExecTimeout,
166
+ useKeystore,
167
+ keystorePath,
168
+ keystorePassword,
169
+ keyAlias,
170
+ keyPassword,
171
+ remoteAppsCacheLimit,
172
+ buildToolsVersion,
173
+ allowOfflineDevices,
174
+ allowDelayAdb,
175
+ });
176
+ }
177
+
178
+ /**
179
+ * @this {import('../../driver').AndroidDriver}
180
+ * @param {boolean} throwIfError
181
+ * @returns {Promise<void>}
182
+ */
183
+ export async function pushSettingsApp(throwIfError) {
184
+ this.log.debug('Pushing settings apk to the device...');
185
+
186
+ try {
187
+ // Sometimes adb push or adb instal take more time than expected to install an app
188
+ // e.g. https://github.com/appium/io.appium.settings/issues/40#issuecomment-476593174
189
+ await retryInterval(
190
+ HELPER_APP_INSTALL_RETRIES,
191
+ HELPER_APP_INSTALL_RETRY_DELAY_MS,
192
+ async () =>
193
+ await this.adb.installOrUpgrade(SETTINGS_APK_PATH, SETTINGS_HELPER_ID, {
194
+ grantPermissions: true,
195
+ }),
196
+ );
197
+ } catch (err) {
198
+ if (throwIfError) {
199
+ throw err;
200
+ }
201
+
202
+ this.log.warn(
203
+ `Ignored error while installing '${SETTINGS_APK_PATH}': ` +
204
+ `'${err.message}'. Features that rely on this helper ` +
205
+ 'require the apk such as toggle WiFi and getting location ' +
206
+ 'will raise an error if you try to use them.',
207
+ );
208
+ }
209
+
210
+ // Reinstall would stop the settings helper process anyway, so
211
+ // there is no need to continue if the application is still running
212
+ if (await this.settingsApp.isRunningInForeground()) {
213
+ this.log.debug(
214
+ `${SETTINGS_HELPER_ID} is already running. ` + `There is no need to reset its permissions.`,
215
+ );
216
+ return;
217
+ }
218
+
219
+ const fixSettingsAppPermissionsForLegacyApis = async () => {
220
+ if ((await this.adb.getApiLevel()) > 23) {
221
+ return;
222
+ }
223
+
224
+ // Android 6- devices should have granted permissions
225
+ // https://github.com/appium/appium/pull/11640#issuecomment-438260477
226
+ const perms = ['SET_ANIMATION_SCALE', 'CHANGE_CONFIGURATION', 'ACCESS_FINE_LOCATION'];
227
+ this.log.info(`Granting permissions ${perms} to '${SETTINGS_HELPER_ID}'`);
228
+ await this.adb.grantPermissions(
229
+ SETTINGS_HELPER_ID,
230
+ perms.map((x) => `android.permission.${x}`),
231
+ );
232
+ };
233
+
234
+ try {
235
+ await B.all([
236
+ this.settingsApp.adjustNotificationsPermissions(),
237
+ this.settingsApp.adjustMediaProjectionServicePermissions(),
238
+ fixSettingsAppPermissionsForLegacyApis(),
239
+ ]);
240
+ } catch (e) {
241
+ this.log.debug(e.stack);
242
+ }
243
+
244
+ // launch io.appium.settings app due to settings failing to be set
245
+ // if the app is not launched prior to start the session on android 7+
246
+ // see https://github.com/appium/appium/issues/8957
247
+ try {
248
+ await this.settingsApp.requireRunning({
249
+ timeout: this.isEmulator() ? 30000 : 5000,
250
+ });
251
+ } catch (err) {
252
+ this.log.debug(err.stack);
253
+ if (throwIfError) {
254
+ throw err;
255
+ }
256
+ }
257
+ }
258
+
259
+ /**
260
+ * @deprecated
261
+ * @this {import('../../driver').AndroidDriver}
262
+ * @returns {Promise<string?>}
263
+ */
264
+ export async function initUnicodeKeyboard() {
265
+ this.log.debug('Enabling Unicode keyboard support');
266
+
267
+ // get the default IME so we can return back to it later if we want
268
+ const defaultIME = await this.adb.defaultIME();
269
+
270
+ this.log.debug(`Unsetting previous IME ${defaultIME}`);
271
+ this.log.debug(`Setting IME to '${UNICODE_IME}'`);
272
+ await this.adb.enableIME(UNICODE_IME);
273
+ await this.adb.setIME(UNICODE_IME);
274
+ return defaultIME;
275
+ }
276
+
277
+ /**
278
+ * @this {import('../../driver').AndroidDriver}
279
+ * @returns {Promise<void>}
280
+ */
281
+ export async function hideKeyboardCompletely() {
282
+ this.log.debug(`Hiding the on-screen keyboard by setting IME to '${EMPTY_IME}'`);
283
+ await this.adb.enableIME(EMPTY_IME);
284
+ await this.adb.setIME(EMPTY_IME);
285
+ }
@@ -1,56 +1,43 @@
1
1
  import {errors} from 'appium/driver';
2
2
  import _ from 'lodash';
3
- import {mixin} from './mixins';
4
3
 
5
4
  const SUPPORTED_ACTIONS = ['whitelistAdd', 'whitelistRemove'];
6
5
 
7
6
  /**
8
- * @type {import('./mixins').DeviceidleMixin & ThisType<import('../driver').AndroidDriver>}
9
- * @satisfies {import('@appium/types').ExternalDriver}
7
+ * This is a wrapper to 'adb shell dumpsys deviceidle' interface.
8
+ * Read https://www.protechtraining.com/blog/post/diving-into-android-m-doze-875
9
+ * for more details.
10
+ *
11
+ * @param {import('./types').DeviceidleOpts} opts
12
+ * @returns {Promise<void>}
10
13
  */
11
- const DeviceidleMixin = {
12
- /**
13
- * This is a wrapper to 'adb shell dumpsys deviceidle' interface.
14
- * Read https://www.protechtraining.com/blog/post/diving-into-android-m-doze-875
15
- * for more details.
16
- *
17
- * @param {import('./types').DeviceidleOpts} opts
18
- */
19
- async mobileDeviceidle(opts) {
20
- const {
21
- action,
22
- packages,
23
- } = opts;
14
+ export async function mobileDeviceidle(opts) {
15
+ const {action, packages} = opts;
24
16
 
25
- if (!(_.isString(packages) || _.isArray(packages))) {
26
- throw new errors.InvalidArgumentError(`packages argument must be a string or an array`);
27
- }
17
+ if (!(_.isString(packages) || _.isArray(packages))) {
18
+ throw new errors.InvalidArgumentError(`packages argument must be a string or an array`);
19
+ }
28
20
 
29
- /** @type {string[]} */
30
- const packagesArr = _.isArray(packages) ? packages : [packages];
31
- /** @type {string[]} */
32
- const commonArgs = ['dumpsys', 'deviceidle', 'whitelist'];
33
- /** @type {(x: string) => string[]} */
34
- let argsGenerator;
35
- switch (action) {
36
- case SUPPORTED_ACTIONS[0]:
37
- argsGenerator = (pkg) => [...commonArgs, `+${pkg}`];
38
- break;
39
- case SUPPORTED_ACTIONS[1]:
40
- argsGenerator = (pkg) => [...commonArgs, `-${pkg}`];
41
- break;
42
- default:
43
- throw new errors.InvalidArgumentError(
44
- `action must be one of ${JSON.stringify(SUPPORTED_ACTIONS)}. Got '${action}' instead`
45
- );
46
- }
47
- await (this.adb).shellChunks(argsGenerator, packagesArr);
48
- },
49
- };
50
-
51
- mixin(DeviceidleMixin);
52
-
53
- export default DeviceidleMixin;
21
+ /** @type {string[]} */
22
+ const packagesArr = _.isArray(packages) ? packages : [packages];
23
+ /** @type {string[]} */
24
+ const commonArgs = ['dumpsys', 'deviceidle', 'whitelist'];
25
+ /** @type {(x: string) => string[]} */
26
+ let argsGenerator;
27
+ switch (action) {
28
+ case SUPPORTED_ACTIONS[0]:
29
+ argsGenerator = (pkg) => [...commonArgs, `+${pkg}`];
30
+ break;
31
+ case SUPPORTED_ACTIONS[1]:
32
+ argsGenerator = (pkg) => [...commonArgs, `-${pkg}`];
33
+ break;
34
+ default:
35
+ throw new errors.InvalidArgumentError(
36
+ `action must be one of ${JSON.stringify(SUPPORTED_ACTIONS)}. Got '${action}' instead`,
37
+ );
38
+ }
39
+ await this.adb.shellChunks(argsGenerator, packagesArr);
40
+ }
54
41
 
55
42
  /**
56
43
  * @typedef {import('appium-adb').ADB} ADB
@@ -1,151 +1,158 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-vars */
2
2
 
3
- import {mixin} from './mixins';
4
- import {retryInterval} from 'asyncbox';
5
3
  import {errors} from 'appium/driver';
6
4
 
7
5
  /**
8
- * @type {import('./mixins').ElementMixin & ThisType<import('../driver').AndroidDriver>}
9
- * @satisfies {import('@appium/types').ExternalDriver}
6
+ * @this {import('../driver').AndroidDriver}
7
+ * @param {string} attribute
8
+ * @param {string} elementId
9
+ * @returns {Promise<string?>}
10
10
  */
11
- const ElementMixin = {
12
- async getAttribute(attribute, elementId) {
13
- throw new errors.NotImplementedError('Not implemented');
14
- },
15
-
16
- async getName(elementId) {
17
- return await this.getAttribute('className', elementId);
18
- },
19
-
20
- async elementDisplayed(elementId) {
21
- return (await this.getAttribute('displayed', elementId)) === 'true';
22
- },
23
-
24
- async elementEnabled(elementId) {
25
- return (await this.getAttribute('enabled', elementId)) === 'true';
26
- },
27
-
28
- async elementSelected(elementId) {
29
- return (await this.getAttribute('selected', elementId)) === 'true';
30
- },
31
-
32
- async setElementValue(keys, elementId, replace = false) {
33
- const text = keys instanceof Array ? keys.join('') : keys;
34
- return await this.doSetElementValue({
35
- elementId,
36
- text: String(text),
37
- replace,
38
- });
39
- },
40
-
41
- /**
42
- * Reason for isolating doSetElementValue from setElementValue is for reusing setElementValue
43
- * across android-drivers (like appium-uiautomator2-driver) and to avoid code duplication.
44
- * Other android-drivers (like appium-uiautomator2-driver) need to override doSetElementValue
45
- * to facilitate setElementValue.
46
- */
47
- async doSetElementValue(params) {
48
- throw new errors.NotImplementedError('Not implemented');
49
- },
50
-
51
- async setValue(keys, elementId) {
52
- return await this.setElementValue(keys, elementId, false);
53
- },
54
-
55
- async replaceValue(keys, elementId) {
56
- return await this.setElementValue(keys, elementId, true);
57
- },
58
-
59
- async setValueImmediate(keys, elementId) {
60
- let text = keys;
61
- if (keys instanceof Array) {
62
- text = keys.join('');
63
- }
64
-
65
- // first, make sure we are focused on the element
66
- await this.click(elementId);
67
-
68
- // then send through adb
69
- await this.adb.inputText(/** @type {string} */ (text));
70
- },
71
-
72
- async getText(elementId) {
73
- throw new errors.NotImplementedError('Not implemented');
74
- },
75
-
76
- async clear(elementId) {
77
- let text = (await this.getText(elementId)) || '';
78
- let length = text.length;
79
- if (length === 0) {
80
- // if length is zero there are two possibilities:
81
- // 1. there is nothing in the text field
82
- // 2. it is a password field
83
- // since there is little overhead to the adb call, delete 100 elements
84
- // if we get zero, just in case it is #2
85
- length = 100;
86
- }
87
- await this.click(elementId);
88
- this.log.debug(`Sending up to ${length} clear characters to device`);
89
- await retryInterval(5, 500, async () => {
90
- let remainingLength = length;
91
- while (remainingLength > 0) {
92
- let lengthToSend = remainingLength < 50 ? remainingLength : 50;
93
- this.log.debug(`Sending ${lengthToSend} clear characters to device`);
94
- await this.adb.clearTextField(lengthToSend);
95
- remainingLength -= lengthToSend;
96
- }
97
- });
98
- },
99
-
100
- async click(elementId) {
101
- throw new errors.NotImplementedError('Not implemented');
102
- },
103
-
104
- async getLocation(elementId) {
105
- throw new errors.NotImplementedError('Not implemented');
106
- },
107
-
108
- async getLocationInView(elementId) {
109
- return await this.getLocation(elementId);
110
- },
111
-
112
- async getSize(elementId) {
113
- throw new errors.NotImplementedError('Not implemented');
114
- },
115
-
116
- async getElementRect(elementId) {
117
- throw new errors.NotImplementedError('Not implemented');
118
- },
119
-
120
- async touchLongClick(elementId, x, y, duration) {
121
- throw new errors.NotImplementedError('Not implemented');
122
- },
123
-
124
- async touchDown(elementId, x, y) {
125
- throw new errors.NotImplementedError('Not implemented');
126
- },
127
-
128
- async touchUp(elementId, x, y) {
129
- throw new errors.NotImplementedError('Not implemented');
130
- },
131
-
132
- async touchMove(elementId, x, y) {
133
- throw new errors.NotImplementedError('Not implemented');
134
- },
135
-
136
- async complexTap(tapCount, touchCount, duration, x, y) {
137
- throw new errors.NotImplementedError('Not implemented');
138
- },
139
-
140
- async tap(elementId = null, x = null, y = null, count = 1) {
141
- throw new errors.NotImplementedError('Not implemented');
142
- },
143
- };
144
-
145
- mixin(ElementMixin);
146
-
147
- export default ElementMixin;
11
+ export async function getAttribute(attribute, elementId) {
12
+ throw new errors.NotImplementedError('Not implemented');
13
+ }
148
14
 
149
15
  /**
150
- * @typedef {import('appium-adb').ADB} ADB
16
+ * @this {import('../driver').AndroidDriver}
17
+ * @param {string} elementId
18
+ * @returns {Promise<void>}
151
19
  */
20
+ export async function click(elementId) {
21
+ throw new errors.NotImplementedError('Not implemented');
22
+ }
23
+
24
+ /**
25
+ * @this {import('../driver').AndroidDriver}
26
+ * @param {string} elementId
27
+ * @returns {Promise<string>}
28
+ */
29
+ export async function getText(elementId) {
30
+ throw new errors.NotImplementedError('Not implemented');
31
+ }
32
+
33
+ /**
34
+ * @this {import('../driver').AndroidDriver}
35
+ * @param {string} elementId
36
+ * @returns {Promise<import('@appium/types').Position>}
37
+ */
38
+ export async function getLocation(elementId) {
39
+ throw new errors.NotImplementedError('Not implemented');
40
+ }
41
+
42
+ /**
43
+ * @this {import('../driver').AndroidDriver}
44
+ * @param {string} elementId
45
+ * @returns {Promise<import('@appium/types').Size>}
46
+ */
47
+ export async function getSize(elementId) {
48
+ throw new errors.NotImplementedError('Not implemented');
49
+ }
50
+
51
+ /**
52
+ * @this {import('../driver').AndroidDriver}
53
+ * @param {string} elementId
54
+ * @returns {Promise<string>}
55
+ */
56
+ export async function getName(elementId) {
57
+ return /** @type {string} */ (await this.getAttribute('className', elementId));
58
+ }
59
+
60
+ /**
61
+ * @this {import('../driver').AndroidDriver}
62
+ * @param {string} elementId
63
+ * @returns {Promise<boolean>}
64
+ */
65
+ export async function elementDisplayed(elementId) {
66
+ return (await this.getAttribute('displayed', elementId)) === 'true';
67
+ }
68
+
69
+ /**
70
+ * @this {import('../driver').AndroidDriver}
71
+ * @param {string} elementId
72
+ * @returns {Promise<boolean>}
73
+ */
74
+ export async function elementEnabled(elementId) {
75
+ return (await this.getAttribute('enabled', elementId)) === 'true';
76
+ }
77
+
78
+ /**
79
+ * @this {import('../driver').AndroidDriver}
80
+ * @param {string} elementId
81
+ * @returns {Promise<boolean>}
82
+ */
83
+ export async function elementSelected(elementId) {
84
+ return (await this.getAttribute('selected', elementId)) === 'true';
85
+ }
86
+
87
+ /**
88
+ * @this {import('../driver').AndroidDriver}
89
+ * @param {string|string[]} keys
90
+ * @param {string} elementId
91
+ * @param {boolean} [replace=false]
92
+ * @returns {Promise<void>}
93
+ */
94
+ export async function setElementValue(keys, elementId, replace = false) {
95
+ const text = keys instanceof Array ? keys.join('') : keys;
96
+ return await this.doSetElementValue({
97
+ elementId,
98
+ text: String(text),
99
+ replace,
100
+ });
101
+ }
102
+
103
+ /**
104
+ * Reason for isolating doSetElementValue from setElementValue is for reusing setElementValue
105
+ * across android-drivers (like appium-uiautomator2-driver) and to avoid code duplication.
106
+ * Other android-drivers (like appium-uiautomator2-driver) need to override doSetElementValue
107
+ * to facilitate setElementValue.
108
+ *
109
+ * @this {import('../driver').AndroidDriver}
110
+ * @param {import('./types').DoSetElementValueOpts} params
111
+ * @returns {Promise<void>}
112
+ */
113
+ export async function doSetElementValue(params) {
114
+ throw new errors.NotImplementedError('Not implemented');
115
+ }
116
+
117
+ /**
118
+ * @this {import('../driver').AndroidDriver}
119
+ * @param {string|string[]} keys
120
+ * @param {string} elementId
121
+ * @returns {Promise<void>}
122
+ */
123
+ export async function setValue(keys, elementId) {
124
+ return await this.setElementValue(keys, elementId, false);
125
+ }
126
+
127
+ /**
128
+ * @this {import('../driver').AndroidDriver}
129
+ * @param {string|string[]} keys
130
+ * @param {string} elementId
131
+ * @returns {Promise<void>}
132
+ */
133
+ export async function replaceValue(keys, elementId) {
134
+ return await this.setElementValue(keys, elementId, true);
135
+ }
136
+
137
+ /**
138
+ * @this {import('../driver').AndroidDriver}
139
+ * @param {string|string[]} keys
140
+ * @param {string} elementId
141
+ * @returns {Promise<void>}
142
+ */
143
+ export async function setValueImmediate(keys, elementId) {
144
+ const text = Array.isArray(keys) ? keys.join('') : keys;
145
+ // first, make sure we are focused on the element
146
+ await this.click(elementId);
147
+ // then send through adb
148
+ await this.adb.inputText(/** @type {string} */ (text));
149
+ }
150
+
151
+ /**
152
+ * @this {import('../driver').AndroidDriver}
153
+ * @param {string} elementId
154
+ * @returns {Promise<import('@appium/types').Position>}
155
+ */
156
+ export async function getLocationInView(elementId) {
157
+ return await this.getLocation(elementId);
158
+ }