appium-uiautomator2-driver 2.29.10 → 2.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/build/index.d.ts +4 -0
  3. package/build/index.d.ts.map +1 -0
  4. package/build/index.js +8 -16
  5. package/build/index.js.map +1 -0
  6. package/build/lib/commands/actions.d.ts +2 -0
  7. package/build/lib/commands/actions.d.ts.map +1 -0
  8. package/build/lib/commands/actions.js +67 -65
  9. package/build/lib/commands/actions.js.map +1 -1
  10. package/build/lib/commands/alert.d.ts +2 -0
  11. package/build/lib/commands/alert.d.ts.map +1 -0
  12. package/build/lib/commands/alert.js +28 -29
  13. package/build/lib/commands/alert.js.map +1 -1
  14. package/build/lib/commands/app-strings.d.ts +3 -0
  15. package/build/lib/commands/app-strings.d.ts.map +1 -0
  16. package/build/lib/commands/app-strings.js +86 -58
  17. package/build/lib/commands/app-strings.js.map +1 -1
  18. package/build/lib/commands/battery.d.ts +2 -0
  19. package/build/lib/commands/battery.d.ts.map +1 -0
  20. package/build/lib/commands/battery.js +26 -18
  21. package/build/lib/commands/battery.js.map +1 -1
  22. package/build/lib/commands/element.d.ts +2 -0
  23. package/build/lib/commands/element.d.ts.map +1 -0
  24. package/build/lib/commands/element.js +140 -162
  25. package/build/lib/commands/element.js.map +1 -1
  26. package/build/lib/commands/find.d.ts +2 -0
  27. package/build/lib/commands/find.d.ts.map +1 -0
  28. package/build/lib/commands/find.js +39 -27
  29. package/build/lib/commands/find.js.map +1 -1
  30. package/build/lib/commands/general.d.ts +4 -0
  31. package/build/lib/commands/general.d.ts.map +1 -0
  32. package/build/lib/commands/general.js +217 -216
  33. package/build/lib/commands/general.js.map +1 -1
  34. package/build/lib/commands/gestures.d.ts +2 -0
  35. package/build/lib/commands/gestures.d.ts.map +1 -0
  36. package/build/lib/commands/gestures.js +206 -194
  37. package/build/lib/commands/gestures.js.map +1 -1
  38. package/build/lib/commands/index.d.ts +2 -0
  39. package/build/lib/commands/index.d.ts.map +1 -0
  40. package/build/lib/commands/index.js +13 -23
  41. package/build/lib/commands/index.js.map +1 -1
  42. package/build/lib/commands/mixins.d.ts +84 -0
  43. package/build/lib/commands/mixins.d.ts.map +1 -0
  44. package/build/lib/commands/mixins.js +23 -0
  45. package/build/lib/commands/mixins.js.map +1 -0
  46. package/build/lib/commands/screenshot.d.ts +2 -0
  47. package/build/lib/commands/screenshot.d.ts.map +1 -0
  48. package/build/lib/commands/screenshot.js +77 -63
  49. package/build/lib/commands/screenshot.js.map +1 -1
  50. package/build/lib/commands/touch.d.ts +2 -0
  51. package/build/lib/commands/touch.d.ts.map +1 -0
  52. package/build/lib/commands/touch.js +48 -39
  53. package/build/lib/commands/touch.js.map +1 -1
  54. package/build/lib/commands/types.d.ts +452 -0
  55. package/build/lib/commands/types.d.ts.map +1 -0
  56. package/build/lib/commands/types.js +3 -0
  57. package/build/lib/commands/types.js.map +1 -0
  58. package/build/lib/commands/viewport.d.ts +2 -0
  59. package/build/lib/commands/viewport.d.ts.map +1 -0
  60. package/build/lib/commands/viewport.js +37 -37
  61. package/build/lib/commands/viewport.js.map +1 -1
  62. package/build/lib/constraints.d.ts +334 -0
  63. package/build/lib/constraints.d.ts.map +1 -0
  64. package/build/lib/constraints.js +51 -0
  65. package/build/lib/constraints.js.map +1 -0
  66. package/build/lib/css-converter.d.ts +45 -0
  67. package/build/lib/css-converter.d.ts.map +1 -0
  68. package/build/lib/css-converter.js +272 -176
  69. package/build/lib/css-converter.js.map +1 -1
  70. package/build/lib/driver.d.ts +912 -0
  71. package/build/lib/driver.d.ts.map +1 -0
  72. package/build/lib/driver.js +738 -483
  73. package/build/lib/driver.js.map +1 -1
  74. package/build/lib/execute-method-map.d.ts +477 -0
  75. package/build/lib/execute-method-map.d.ts.map +1 -0
  76. package/build/lib/execute-method-map.js +542 -0
  77. package/build/lib/execute-method-map.js.map +1 -0
  78. package/build/lib/extensions.d.ts +3 -0
  79. package/build/lib/extensions.d.ts.map +1 -0
  80. package/build/lib/extensions.js +3 -7
  81. package/build/lib/extensions.js.map +1 -1
  82. package/build/lib/helpers.d.ts +7 -0
  83. package/build/lib/helpers.d.ts.map +1 -0
  84. package/build/lib/helpers.js +36 -30
  85. package/build/lib/helpers.js.map +1 -1
  86. package/build/lib/logger.d.ts +3 -0
  87. package/build/lib/logger.d.ts.map +1 -0
  88. package/build/lib/logger.js +5 -11
  89. package/build/lib/logger.js.map +1 -1
  90. package/build/lib/method-map.d.ts +389 -0
  91. package/build/lib/method-map.d.ts.map +1 -0
  92. package/build/lib/method-map.js +11 -18
  93. package/build/lib/method-map.js.map +1 -1
  94. package/build/lib/types.d.ts +45 -0
  95. package/build/lib/types.d.ts.map +1 -0
  96. package/build/lib/types.js +3 -0
  97. package/build/lib/types.js.map +1 -0
  98. package/build/lib/uiautomator2.d.ts +45 -0
  99. package/build/lib/uiautomator2.d.ts.map +1 -0
  100. package/build/lib/uiautomator2.js +334 -297
  101. package/build/lib/uiautomator2.js.map +1 -1
  102. package/build/lib/utils.d.ts +10 -0
  103. package/build/lib/utils.d.ts.map +1 -0
  104. package/build/lib/utils.js +23 -16
  105. package/build/lib/utils.js.map +1 -1
  106. package/build/tsconfig.tsbuildinfo +1 -0
  107. package/index.js +5 -3
  108. package/lib/commands/actions.js +115 -101
  109. package/lib/commands/alert.js +36 -44
  110. package/lib/commands/app-strings.js +79 -58
  111. package/lib/commands/battery.js +27 -28
  112. package/lib/commands/element.js +231 -134
  113. package/lib/commands/find.js +40 -21
  114. package/lib/commands/general.js +271 -336
  115. package/lib/commands/gestures.js +252 -366
  116. package/lib/commands/index.js +11 -31
  117. package/lib/commands/mixins.ts +167 -0
  118. package/lib/commands/screenshot.js +80 -76
  119. package/lib/commands/touch.js +64 -31
  120. package/lib/commands/types.ts +473 -0
  121. package/lib/commands/viewport.js +43 -31
  122. package/lib/constraints.ts +53 -0
  123. package/lib/css-converter.js +9 -1
  124. package/lib/{driver.js → driver.ts} +383 -225
  125. package/lib/execute-method-map.ts +573 -0
  126. package/lib/method-map.ts +11 -0
  127. package/lib/types.ts +59 -0
  128. package/lib/uiautomator2.js +21 -2
  129. package/lib/utils.js +2 -2
  130. package/npm-shrinkwrap.json +396 -528
  131. package/package.json +96 -70
  132. package/build/lib/desired-caps.js +0 -72
  133. package/build/lib/desired-caps.js.map +0 -1
  134. package/lib/desired-caps.js +0 -70
  135. package/lib/method-map.js +0 -11
@@ -1,20 +1,18 @@
1
1
  "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
- Object.defineProperty(exports, "__esModule", {
5
- value: true
6
- });
7
- exports.default = exports.UiAutomator2Server = exports.SERVER_TEST_PACKAGE_ID = exports.SERVER_PACKAGE_ID = exports.INSTRUMENTATION_TARGET = void 0;
8
- require("source-map-support/register");
9
- var _lodash = _interopRequireDefault(require("lodash"));
10
- var _driver = require("appium/driver");
11
- var _asyncbox = require("asyncbox");
12
- var _appiumUiautomator2Server = require("appium-uiautomator2-server");
13
- var _support = require("appium/support");
14
- var _bluebird = _interopRequireDefault(require("bluebird"));
15
- var _helpers = _interopRequireDefault(require("./helpers"));
16
- var _axios = _interopRequireDefault(require("axios"));
17
- var _path = _interopRequireDefault(require("path"));
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SERVER_TEST_PACKAGE_ID = exports.SERVER_PACKAGE_ID = exports.INSTRUMENTATION_TARGET = exports.UiAutomator2Server = void 0;
7
+ const lodash_1 = __importDefault(require("lodash"));
8
+ const driver_1 = require("appium/driver");
9
+ const asyncbox_1 = require("asyncbox");
10
+ const appium_uiautomator2_server_1 = require("appium-uiautomator2-server");
11
+ const support_1 = require("appium/support");
12
+ const bluebird_1 = __importDefault(require("bluebird"));
13
+ const helpers_1 = __importDefault(require("./helpers"));
14
+ const axios_1 = __importDefault(require("axios"));
15
+ const path_1 = __importDefault(require("path"));
18
16
  const REQD_PARAMS = ['adb', 'tmpDir', 'host', 'systemPort', 'devicePort', 'disableWindowAnimation'];
19
17
  const SERVER_LAUNCH_TIMEOUT = 30000;
20
18
  const SERVER_INSTALL_RETRIES = 20;
@@ -25,303 +23,342 @@ const SERVER_TEST_PACKAGE_ID = `${SERVER_PACKAGE_ID}.test`;
25
23
  exports.SERVER_TEST_PACKAGE_ID = SERVER_TEST_PACKAGE_ID;
26
24
  const INSTRUMENTATION_TARGET = `${SERVER_TEST_PACKAGE_ID}/androidx.test.runner.AndroidJUnitRunner`;
27
25
  exports.INSTRUMENTATION_TARGET = INSTRUMENTATION_TARGET;
28
- const instrumentationLogger = _support.logger.getLogger('Instrumentation');
29
- class UIA2Proxy extends _driver.JWProxy {
30
- async proxyCommand(url, method, body = null) {
31
- if (this.didInstrumentationExit) {
32
- throw new _driver.errors.InvalidContextError(`'${method} ${url}' cannot be proxied to UiAutomator2 server because ` + 'the instrumentation process is not running (probably crashed). ' + 'Check the server log and/or the logcat output for more details');
26
+ const instrumentationLogger = support_1.logger.getLogger('Instrumentation');
27
+ class UIA2Proxy extends driver_1.JWProxy {
28
+ async proxyCommand(url, method, body = null) {
29
+ if (this.didInstrumentationExit) {
30
+ throw new driver_1.errors.InvalidContextError(`'${method} ${url}' cannot be proxied to UiAutomator2 server because ` +
31
+ 'the instrumentation process is not running (probably crashed). ' +
32
+ 'Check the server log and/or the logcat output for more details');
33
+ }
34
+ return await super.proxyCommand(url, method, body);
33
35
  }
34
- return await super.proxyCommand(url, method, body);
35
- }
36
36
  }
37
37
  class UiAutomator2Server {
38
- constructor(log, opts = {}) {
39
- for (let req of REQD_PARAMS) {
40
- if (!opts || !_support.util.hasValue(opts[req])) {
41
- throw new Error(`Option '${req}' is required!`);
42
- }
43
- this[req] = opts[req];
44
- }
45
- this.log = log;
46
- this.disableSuppressAccessibilityService = opts.disableSuppressAccessibilityService;
47
- const proxyOpts = {
48
- log,
49
- server: this.host,
50
- port: this.systemPort,
51
- keepAlive: true
52
- };
53
- if (opts.readTimeout && opts.readTimeout > 0) {
54
- proxyOpts.timeout = opts.readTimeout;
55
- }
56
- this.jwproxy = new UIA2Proxy(proxyOpts);
57
- this.proxyReqRes = this.jwproxy.proxyReqRes.bind(this.jwproxy);
58
- this.proxyCommand = this.jwproxy.command.bind(this.jwproxy);
59
- this.jwproxy.didInstrumentationExit = false;
60
- }
61
- async prepareServerPackage(appPath, appId, tmpRoot) {
62
- const resultInfo = {
63
- wasSigned: false,
64
- installState: this.adb.APP_INSTALL_STATE.NOT_INSTALLED,
65
- appPath,
66
- appId
67
- };
68
- if (await this.adb.checkApkCert(resultInfo.appPath, appId)) {
69
- resultInfo.wasSigned = true;
70
- } else {
71
- if (!(await _helpers.default.isWriteable(appPath))) {
72
- this.log.warn(`Server package at '${appPath}' is not writeable. ` + `Will copy it into the temporary location at '${tmpRoot}' as a workaround. ` + `Consider making this file writeable manually in order to improve the performance of session startup.`);
73
- const dstPath = _path.default.resolve(tmpRoot, _path.default.basename(appPath));
74
- await _support.fs.copyFile(appPath, dstPath);
75
- resultInfo.appPath = dstPath;
76
- }
77
- await _helpers.default.signApp(this.adb, resultInfo.appPath);
78
- }
79
- if (appId === SERVER_TEST_PACKAGE_ID && (await this.adb.isAppInstalled(appId))) {
80
- resultInfo.installState = this.adb.APP_INSTALL_STATE.SAME_VERSION_INSTALLED;
81
- } else if (appId === SERVER_PACKAGE_ID) {
82
- resultInfo.installState = await this.adb.getApplicationInstallState(resultInfo.appPath, appId);
83
- }
84
- return resultInfo;
85
- }
86
- async installServerApk(installTimeout = SERVER_INSTALL_RETRIES * 1000) {
87
- const tmpRoot = await _support.tempDir.openDir();
88
- try {
89
- const packagesInfo = await _bluebird.default.all([{
90
- appPath: _appiumUiautomator2Server.SERVER_APK_PATH,
91
- appId: SERVER_PACKAGE_ID
92
- }, {
93
- appPath: _appiumUiautomator2Server.TEST_APK_PATH,
94
- appId: SERVER_TEST_PACKAGE_ID
95
- }].map(({
96
- appPath,
97
- appId
98
- }) => this.prepareServerPackage(appPath, appId, tmpRoot)));
99
- this.log.debug(`Server packages status: ${JSON.stringify(packagesInfo)}`);
100
- const shouldUninstallServerPackages = packagesInfo.some(({
101
- wasSigned
102
- }) => !wasSigned) || packagesInfo.some(({
103
- installState
104
- }) => installState === this.adb.APP_INSTALL_STATE.NOT_INSTALLED) && !packagesInfo.every(({
105
- installState
106
- }) => installState === this.adb.APP_INSTALL_STATE.NOT_INSTALLED);
107
- const shouldInstallServerPackages = shouldUninstallServerPackages || packagesInfo.some(({
108
- installState
109
- }) => [this.adb.APP_INSTALL_STATE.NOT_INSTALLED, this.adb.APP_INSTALL_STATE.OLDER_VERSION_INSTALLED].includes(installState));
110
- this.log.info(`Server packages are ${shouldInstallServerPackages ? '' : 'not '}going to be (re)installed`);
111
- if (shouldInstallServerPackages && shouldUninstallServerPackages) {
112
- this.log.info('Full packages reinstall is going to be performed');
113
- }
114
- if (shouldUninstallServerPackages) {
115
- const silentUninstallPkg = async pkgId => {
116
- try {
117
- await this.adb.uninstallApk(pkgId);
118
- } catch (err) {
119
- this.log.info(`Cannot uninstall '${pkgId}': ${err.message}`);
120
- }
121
- };
122
- await _bluebird.default.all(packagesInfo.map(({
123
- appId
124
- }) => silentUninstallPkg(appId)));
125
- }
126
- if (shouldInstallServerPackages) {
127
- const installPkg = async pkgPath => {
128
- await this.adb.install(pkgPath, {
129
- noIncremental: true,
130
- replace: true,
131
- timeout: installTimeout,
132
- timeoutCapName: 'uiautomator2ServerInstallTimeout'
133
- });
38
+ constructor(log, opts = {}) {
39
+ for (let req of REQD_PARAMS) {
40
+ if (!opts || !support_1.util.hasValue(opts[req])) {
41
+ throw new Error(`Option '${req}' is required!`);
42
+ }
43
+ this[req] = opts[req];
44
+ }
45
+ this.log = log;
46
+ this.disableSuppressAccessibilityService = opts.disableSuppressAccessibilityService;
47
+ const proxyOpts = {
48
+ log,
49
+ server: this.host,
50
+ port: this.systemPort,
51
+ keepAlive: true,
134
52
  };
135
- await _bluebird.default.all(packagesInfo.map(({
136
- appPath
137
- }) => installPkg(appPath)));
138
- }
139
- } finally {
140
- await _support.fs.rimraf(tmpRoot);
53
+ if (opts.readTimeout && opts.readTimeout > 0) {
54
+ proxyOpts.timeout = opts.readTimeout;
55
+ }
56
+ this.jwproxy = new UIA2Proxy(proxyOpts);
57
+ this.proxyReqRes = this.jwproxy.proxyReqRes.bind(this.jwproxy);
58
+ this.proxyCommand = this.jwproxy.command.bind(this.jwproxy);
59
+ this.jwproxy.didInstrumentationExit = false;
141
60
  }
142
- await this.verifyServicesAvailability();
143
- }
144
- async verifyServicesAvailability() {
145
- this.log.debug(`Waiting up to ${SERVICES_LAUNCH_TIMEOUT}ms for services to be available`);
146
- let isPmServiceAvailable = false;
147
- let pmOutput = '';
148
- let pmError = null;
149
- try {
150
- await (0, _asyncbox.waitForCondition)(async () => {
151
- if (!isPmServiceAvailable) {
152
- pmError = null;
153
- pmOutput = '';
154
- try {
155
- pmOutput = await this.adb.shell(['pm', 'list', 'instrumentation']);
156
- } catch (e) {
157
- pmError = e;
158
- }
159
- if (pmOutput.includes('Could not access the Package Manager')) {
160
- pmError = new Error(`Problem running Package Manager: ${pmOutput}`);
161
- pmOutput = '';
162
- } else if (pmOutput.includes(INSTRUMENTATION_TARGET)) {
163
- pmOutput = '';
164
- this.log.debug(`Instrumentation target '${INSTRUMENTATION_TARGET}' is available`);
165
- isPmServiceAvailable = true;
166
- } else if (!pmError) {
167
- pmError = new Error('The instrumentation target is not listed by Package Manager');
168
- }
61
+ async prepareServerPackage(appPath, appId, tmpRoot) {
62
+ const resultInfo = {
63
+ wasSigned: false,
64
+ installState: this.adb.APP_INSTALL_STATE.NOT_INSTALLED,
65
+ appPath,
66
+ appId,
67
+ };
68
+ if (await this.adb.checkApkCert(resultInfo.appPath, appId)) {
69
+ resultInfo.wasSigned = true;
169
70
  }
170
- return isPmServiceAvailable;
171
- }, {
172
- waitMs: SERVICES_LAUNCH_TIMEOUT,
173
- intervalMs: 1000
174
- });
175
- } catch (err) {
176
- this.log.error(`Unable to find instrumentation target '${INSTRUMENTATION_TARGET}': ${(pmError || {}).message}`);
177
- if (pmOutput) {
178
- this.log.debug('Available targets:');
179
- for (const line of pmOutput.split('\n')) {
180
- this.log.debug(` ${line.replace('instrumentation:', '')}`);
71
+ else {
72
+ if (!await helpers_1.default.isWriteable(appPath)) {
73
+ this.log.warn(`Server package at '${appPath}' is not writeable. ` +
74
+ `Will copy it into the temporary location at '${tmpRoot}' as a workaround. ` +
75
+ `Consider making this file writeable manually in order to improve the performance of session startup.`);
76
+ const dstPath = path_1.default.resolve(tmpRoot, path_1.default.basename(appPath));
77
+ await support_1.fs.copyFile(appPath, dstPath);
78
+ resultInfo.appPath = dstPath;
79
+ }
80
+ await helpers_1.default.signApp(this.adb, resultInfo.appPath);
181
81
  }
182
- }
183
- }
184
- }
185
- async startSession(caps) {
186
- await this.cleanupAutomationLeftovers();
187
- if (caps.skipServerInstallation) {
188
- this.log.info(`'skipServerInstallation' is set. Attempting to use UIAutomator2 server from the device`);
189
- } else {
190
- this.log.info(`Starting UIAutomator2 server ${_appiumUiautomator2Server.version}`);
191
- this.log.info(`Using UIAutomator2 server from '${_appiumUiautomator2Server.SERVER_APK_PATH}' and test from '${_appiumUiautomator2Server.TEST_APK_PATH}'`);
82
+ if (appId === SERVER_TEST_PACKAGE_ID && await this.adb.isAppInstalled(appId)) {
83
+ // There is no point in getting the state for the test server,
84
+ // since it does not contain any version info
85
+ resultInfo.installState = this.adb.APP_INSTALL_STATE.SAME_VERSION_INSTALLED;
86
+ }
87
+ else if (appId === SERVER_PACKAGE_ID) {
88
+ resultInfo.installState = await this.adb.getApplicationInstallState(resultInfo.appPath, appId);
89
+ }
90
+ return resultInfo;
192
91
  }
193
- const timeout = caps.uiautomator2ServerLaunchTimeout || SERVER_LAUNCH_TIMEOUT;
194
- const timer = new _support.timing.Timer().start();
195
- let retries = 0;
196
- const maxRetries = 2;
197
- const delayBetweenRetries = 3000;
198
- while (retries < maxRetries) {
199
- this.log.info(`Waiting up to ${timeout}ms for UiAutomator2 to be online...`);
200
- this.jwproxy.didInstrumentationExit = false;
201
- await this.startInstrumentationProcess();
202
- if (!this.jwproxy.didInstrumentationExit) {
92
+ /**
93
+ * Installs the apks on to the device or emulator.
94
+ *
95
+ * @param {number} installTimeout - Installation timeout
96
+ */
97
+ async installServerApk(installTimeout = SERVER_INSTALL_RETRIES * 1000) {
98
+ const tmpRoot = await support_1.tempDir.openDir();
203
99
  try {
204
- await (0, _asyncbox.waitForCondition)(async () => {
205
- try {
206
- await this.jwproxy.command('/status', 'GET');
207
- return true;
208
- } catch (err) {
209
- return this.jwproxy.didInstrumentationExit;
100
+ const packagesInfo = await bluebird_1.default.all([
101
+ {
102
+ appPath: appium_uiautomator2_server_1.SERVER_APK_PATH,
103
+ appId: SERVER_PACKAGE_ID,
104
+ }, {
105
+ appPath: appium_uiautomator2_server_1.TEST_APK_PATH,
106
+ appId: SERVER_TEST_PACKAGE_ID,
107
+ },
108
+ ].map(({ appPath, appId }) => this.prepareServerPackage(appPath, appId, tmpRoot)));
109
+ this.log.debug(`Server packages status: ${JSON.stringify(packagesInfo)}`);
110
+ // We want to enforce uninstall in case the current server package has not been signed properly
111
+ // or if any of server packages is not installed, while the other does
112
+ const shouldUninstallServerPackages = packagesInfo.some(({ wasSigned }) => !wasSigned)
113
+ || (packagesInfo.some(({ installState }) => installState === this.adb.APP_INSTALL_STATE.NOT_INSTALLED)
114
+ && !packagesInfo.every(({ installState }) => installState === this.adb.APP_INSTALL_STATE.NOT_INSTALLED));
115
+ // Install must always follow uninstall. Also, perform the install if
116
+ // any of server packages is not installed or is outdated
117
+ const shouldInstallServerPackages = shouldUninstallServerPackages || packagesInfo.some(({ installState }) => [
118
+ this.adb.APP_INSTALL_STATE.NOT_INSTALLED,
119
+ this.adb.APP_INSTALL_STATE.OLDER_VERSION_INSTALLED,
120
+ ].includes(installState));
121
+ this.log.info(`Server packages are ${shouldInstallServerPackages ? '' : 'not '}going to be (re)installed`);
122
+ if (shouldInstallServerPackages && shouldUninstallServerPackages) {
123
+ this.log.info('Full packages reinstall is going to be performed');
124
+ }
125
+ if (shouldUninstallServerPackages) {
126
+ const silentUninstallPkg = async (pkgId) => {
127
+ try {
128
+ await this.adb.uninstallApk(pkgId);
129
+ }
130
+ catch (err) {
131
+ this.log.info(`Cannot uninstall '${pkgId}': ${err.message}`);
132
+ }
133
+ };
134
+ await bluebird_1.default.all(packagesInfo.map(({ appId }) => silentUninstallPkg(appId)));
135
+ }
136
+ if (shouldInstallServerPackages) {
137
+ const installPkg = async (pkgPath) => {
138
+ await this.adb.install(pkgPath, {
139
+ noIncremental: true,
140
+ replace: true,
141
+ timeout: installTimeout,
142
+ timeoutCapName: 'uiautomator2ServerInstallTimeout'
143
+ });
144
+ };
145
+ await bluebird_1.default.all(packagesInfo.map(({ appPath }) => installPkg(appPath)));
210
146
  }
211
- }, {
212
- waitMs: timeout,
213
- intervalMs: 1000
214
- });
215
- } catch (err) {
216
- this.log.errorAndThrow(`The instrumentation process cannot be initialized within ${timeout}ms timeout. ` + 'Make sure the application under test does not crash and investigate the logcat output. ' + `You could also try to increase the value of 'uiautomator2ServerLaunchTimeout' capability`);
217
147
  }
218
- }
219
- if (!this.jwproxy.didInstrumentationExit) {
220
- break;
221
- }
222
- retries++;
223
- if (retries >= maxRetries) {
224
- this.log.errorAndThrow('The instrumentation process cannot be initialized. ' + 'Make sure the application under test does not crash and investigate the logcat output.');
225
- }
226
- this.log.warn(`The instrumentation process has been unexpectedly terminated. ` + `Retrying UiAutomator2 startup (#${retries} of ${maxRetries - 1})`);
227
- await this.cleanupAutomationLeftovers(true);
228
- await _bluebird.default.delay(delayBetweenRetries);
229
- }
230
- this.log.debug(`The initialization of the instrumentation process took ` + `${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
231
- await this.jwproxy.command('/session', 'POST', {
232
- capabilities: {
233
- firstMatch: [caps],
234
- alwaysMatch: {}
235
- }
236
- });
237
- }
238
- async startInstrumentationProcess() {
239
- const cmd = ['am', 'instrument', '-w'];
240
- if (this.disableWindowAnimation) {
241
- cmd.push('--no-window-animation');
148
+ finally {
149
+ await support_1.fs.rimraf(tmpRoot);
150
+ }
151
+ await this.verifyServicesAvailability();
242
152
  }
243
- if (_lodash.default.isBoolean(this.disableSuppressAccessibilityService)) {
244
- cmd.push('-e', 'DISABLE_SUPPRESS_ACCESSIBILITY_SERVICES', this.disableSuppressAccessibilityService);
153
+ async verifyServicesAvailability() {
154
+ this.log.debug(`Waiting up to ${SERVICES_LAUNCH_TIMEOUT}ms for services to be available`);
155
+ let isPmServiceAvailable = false;
156
+ let pmOutput = '';
157
+ let pmError = null;
158
+ try {
159
+ await (0, asyncbox_1.waitForCondition)(async () => {
160
+ if (!isPmServiceAvailable) {
161
+ pmError = null;
162
+ pmOutput = '';
163
+ try {
164
+ pmOutput = await this.adb.shell(['pm', 'list', 'instrumentation']);
165
+ }
166
+ catch (e) {
167
+ pmError = e;
168
+ }
169
+ if (pmOutput.includes('Could not access the Package Manager')) {
170
+ pmError = new Error(`Problem running Package Manager: ${pmOutput}`);
171
+ pmOutput = ''; // remove output, so it is not printed below
172
+ }
173
+ else if (pmOutput.includes(INSTRUMENTATION_TARGET)) {
174
+ pmOutput = ''; // remove output, so it is not printed below
175
+ this.log.debug(`Instrumentation target '${INSTRUMENTATION_TARGET}' is available`);
176
+ // eslint-disable-next-line require-atomic-updates
177
+ isPmServiceAvailable = true;
178
+ }
179
+ else if (!pmError) {
180
+ pmError = new Error('The instrumentation target is not listed by Package Manager');
181
+ }
182
+ }
183
+ return isPmServiceAvailable;
184
+ }, {
185
+ waitMs: SERVICES_LAUNCH_TIMEOUT,
186
+ intervalMs: 1000,
187
+ });
188
+ }
189
+ catch (err) {
190
+ // @ts-ignore It is ok if the attribute does not exist
191
+ this.log.error(`Unable to find instrumentation target '${INSTRUMENTATION_TARGET}': ${(pmError || {}).message}`);
192
+ if (pmOutput) {
193
+ this.log.debug('Available targets:');
194
+ for (const line of pmOutput.split('\n')) {
195
+ this.log.debug(` ${line.replace('instrumentation:', '')}`);
196
+ }
197
+ }
198
+ }
245
199
  }
246
- cmd.push('-e', 'disableAnalytics', true);
247
- cmd.push(INSTRUMENTATION_TARGET);
248
- const instrumentationProcess = this.adb.createSubProcess(['shell', ...cmd]);
249
- instrumentationProcess.on('output', (stdout, stderr) => {
250
- const output = _lodash.default.trim(stdout || stderr);
251
- if (output) {
252
- instrumentationLogger.debug(output);
253
- }
254
- });
255
- instrumentationProcess.on('exit', code => {
256
- instrumentationLogger.debug(`The process has exited with code ${code}`);
257
- this.jwproxy.didInstrumentationExit = true;
258
- });
259
- await instrumentationProcess.start(0);
260
- }
261
- async deleteSession() {
262
- this.log.debug('Deleting UiAutomator2 server session');
263
- try {
264
- await this.jwproxy.command('/', 'DELETE');
265
- } catch (err) {
266
- this.log.warn(`Did not get confirmation UiAutomator2 deleteSession worked; ` + `Error was: ${err}`);
200
+ async startSession(caps) {
201
+ await this.cleanupAutomationLeftovers();
202
+ if (caps.skipServerInstallation) {
203
+ this.log.info(`'skipServerInstallation' is set. Attempting to use UIAutomator2 server from the device`);
204
+ }
205
+ else {
206
+ this.log.info(`Starting UIAutomator2 server ${appium_uiautomator2_server_1.version}`);
207
+ this.log.info(`Using UIAutomator2 server from '${appium_uiautomator2_server_1.SERVER_APK_PATH}' and test from '${appium_uiautomator2_server_1.TEST_APK_PATH}'`);
208
+ }
209
+ const timeout = caps.uiautomator2ServerLaunchTimeout || SERVER_LAUNCH_TIMEOUT;
210
+ const timer = new support_1.timing.Timer().start();
211
+ let retries = 0;
212
+ const maxRetries = 2;
213
+ const delayBetweenRetries = 3000;
214
+ while (retries < maxRetries) {
215
+ this.log.info(`Waiting up to ${timeout}ms for UiAutomator2 to be online...`);
216
+ this.jwproxy.didInstrumentationExit = false;
217
+ await this.startInstrumentationProcess();
218
+ if (!this.jwproxy.didInstrumentationExit) {
219
+ try {
220
+ await (0, asyncbox_1.waitForCondition)(async () => {
221
+ try {
222
+ await this.jwproxy.command('/status', 'GET');
223
+ return true;
224
+ }
225
+ catch (err) {
226
+ // short circuit to retry or fail fast
227
+ return this.jwproxy.didInstrumentationExit;
228
+ }
229
+ }, {
230
+ waitMs: timeout,
231
+ intervalMs: 1000,
232
+ });
233
+ }
234
+ catch (err) {
235
+ this.log.errorAndThrow(`The instrumentation process cannot be initialized within ${timeout}ms timeout. `
236
+ + 'Make sure the application under test does not crash and investigate the logcat output. '
237
+ + `You could also try to increase the value of 'uiautomator2ServerLaunchTimeout' capability`);
238
+ }
239
+ }
240
+ if (!this.jwproxy.didInstrumentationExit) {
241
+ break;
242
+ }
243
+ retries++;
244
+ if (retries >= maxRetries) {
245
+ this.log.errorAndThrow('The instrumentation process cannot be initialized. '
246
+ + 'Make sure the application under test does not crash and investigate the logcat output.');
247
+ }
248
+ this.log.warn(`The instrumentation process has been unexpectedly terminated. `
249
+ + `Retrying UiAutomator2 startup (#${retries} of ${maxRetries - 1})`);
250
+ await this.cleanupAutomationLeftovers(true);
251
+ await bluebird_1.default.delay(delayBetweenRetries);
252
+ }
253
+ this.log.debug(`The initialization of the instrumentation process took `
254
+ + `${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
255
+ await this.jwproxy.command('/session', 'POST', {
256
+ capabilities: {
257
+ firstMatch: [caps],
258
+ alwaysMatch: {},
259
+ }
260
+ });
267
261
  }
268
- }
269
- async cleanupAutomationLeftovers(strictCleanup = false) {
270
- this.log.debug(`Performing ${strictCleanup ? 'strict' : 'shallow'} cleanup of automation leftovers`);
271
- const axiosTimeout = 500;
272
- const waitStop = async () => {
273
- const timeout = 3000;
274
- try {
275
- await (0, _asyncbox.waitForCondition)(async () => {
276
- try {
277
- await (0, _axios.default)({
278
- url: `http://${this.host}:${this.systemPort}/status`,
279
- timeout: axiosTimeout
280
- });
281
- } catch (err) {
282
- return true;
283
- }
284
- }, {
285
- waitMs: timeout,
286
- intervalMs: 100
262
+ async startInstrumentationProcess() {
263
+ const cmd = ['am', 'instrument', '-w'];
264
+ if (this.disableWindowAnimation) {
265
+ cmd.push('--no-window-animation');
266
+ }
267
+ if (lodash_1.default.isBoolean(this.disableSuppressAccessibilityService)) {
268
+ cmd.push('-e', 'DISABLE_SUPPRESS_ACCESSIBILITY_SERVICES', `${this.disableSuppressAccessibilityService}`);
269
+ }
270
+ // Disable Google analytics to prevent possible fatal exception
271
+ cmd.push('-e', 'disableAnalytics', 'true');
272
+ cmd.push(INSTRUMENTATION_TARGET);
273
+ const instrumentationProcess = this.adb.createSubProcess(['shell', ...cmd]);
274
+ instrumentationProcess.on('output', (stdout, stderr) => {
275
+ const output = lodash_1.default.trim(stdout || stderr);
276
+ if (output) {
277
+ instrumentationLogger.debug(output);
278
+ }
279
+ });
280
+ instrumentationProcess.on('exit', (code) => {
281
+ instrumentationLogger.debug(`The process has exited with code ${code}`);
282
+ this.jwproxy.didInstrumentationExit = true;
287
283
  });
288
- } catch (err) {
289
- this.log.warn(`The ${SERVER_TEST_PACKAGE_ID} process might fail to stop within ${timeout}ms timeout.`);
290
- }
291
- };
292
- try {
293
- const {
294
- value
295
- } = (await (0, _axios.default)({
296
- url: `http://${this.host}:${this.systemPort}/sessions`,
297
- timeout: axiosTimeout
298
- })).data;
299
- const activeSessionIds = value.map(({
300
- id
301
- }) => id).filter(Boolean);
302
- if (activeSessionIds.length) {
303
- this.log.debug(`The following obsolete sessions are still running: ${JSON.stringify(activeSessionIds)}`);
304
- this.log.debug(`Cleaning up ${_support.util.pluralize('obsolete session', activeSessionIds.length, true)}`);
305
- await _bluebird.default.all(activeSessionIds.map(id => _axios.default.delete(`http://${this.host}:${this.systemPort}/session/${id}`)));
306
- await _bluebird.default.delay(1000);
307
- } else {
308
- this.log.debug('No obsolete sessions have been detected');
309
- }
310
- } catch (e) {
311
- this.log.debug(`No obsolete sessions have been detected (${e.message})`);
284
+ await instrumentationProcess.start(0);
312
285
  }
313
- try {
314
- await this.adb.forceStop(SERVER_TEST_PACKAGE_ID);
315
- } catch (ignore) {}
316
- if (strictCleanup) {
317
- try {
318
- await this.adb.killProcessesByName('uiautomator');
319
- } catch (ignore) {}
286
+ async deleteSession() {
287
+ this.log.debug('Deleting UiAutomator2 server session');
288
+ // rely on jwproxy's intelligence to know what we're talking about and
289
+ // delete the current session
290
+ try {
291
+ await this.jwproxy.command('/', 'DELETE');
292
+ }
293
+ catch (err) {
294
+ this.log.warn(`Did not get confirmation UiAutomator2 deleteSession worked; ` +
295
+ `Error was: ${err}`);
296
+ }
297
+ }
298
+ async cleanupAutomationLeftovers(strictCleanup = false) {
299
+ this.log.debug(`Performing ${strictCleanup ? 'strict' : 'shallow'} cleanup of automation leftovers`);
300
+ const axiosTimeout = 500;
301
+ const waitStop = async () => {
302
+ // Wait for the process stop by sending a status request to the port.
303
+ // We observed the process stop could be delayed, thus causing unexpected crashes
304
+ // in the middle of the session preparation process. It caused an invalid session error response
305
+ // by the uia2 server, but that was because the process stop's delay.
306
+ const timeout = 3000;
307
+ try {
308
+ await (0, asyncbox_1.waitForCondition)(async () => {
309
+ try {
310
+ await (0, axios_1.default)({
311
+ url: `http://${this.host}:${this.systemPort}/status`,
312
+ timeout: axiosTimeout,
313
+ });
314
+ }
315
+ catch (err) {
316
+ return true;
317
+ }
318
+ }, {
319
+ waitMs: timeout,
320
+ intervalMs: 100,
321
+ });
322
+ }
323
+ catch (err) {
324
+ this.log.warn(`The ${SERVER_TEST_PACKAGE_ID} process might fail to stop within ${timeout}ms timeout.`);
325
+ }
326
+ };
327
+ try {
328
+ const { value } = (await (0, axios_1.default)({
329
+ url: `http://${this.host}:${this.systemPort}/sessions`,
330
+ timeout: axiosTimeout,
331
+ })).data;
332
+ const activeSessionIds = value.map(({ id }) => id).filter(Boolean);
333
+ if (activeSessionIds.length) {
334
+ this.log.debug(`The following obsolete sessions are still running: ${JSON.stringify(activeSessionIds)}`);
335
+ this.log.debug(`Cleaning up ${support_1.util.pluralize('obsolete session', activeSessionIds.length, true)}`);
336
+ await bluebird_1.default.all(activeSessionIds
337
+ .map((id) => axios_1.default.delete(`http://${this.host}:${this.systemPort}/session/${id}`)));
338
+ // Let all sessions to be properly terminated before continuing
339
+ await bluebird_1.default.delay(1000);
340
+ }
341
+ else {
342
+ this.log.debug('No obsolete sessions have been detected');
343
+ }
344
+ }
345
+ catch (e) {
346
+ this.log.debug(`No obsolete sessions have been detected (${e.message})`);
347
+ }
348
+ try {
349
+ await this.adb.forceStop(SERVER_TEST_PACKAGE_ID);
350
+ }
351
+ catch (ignore) { }
352
+ if (strictCleanup) {
353
+ // https://github.com/appium/appium/issues/10749
354
+ try {
355
+ await this.adb.killProcessesByName('uiautomator');
356
+ }
357
+ catch (ignore) { }
358
+ }
359
+ await waitStop();
320
360
  }
321
- await waitStop();
322
- }
323
361
  }
324
362
  exports.UiAutomator2Server = UiAutomator2Server;
325
- var _default = UiAutomator2Server;
326
- exports.default = _default;
327
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbG9kYXNoIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfZHJpdmVyIiwiX2FzeW5jYm94IiwiX2FwcGl1bVVpYXV0b21hdG9yMlNlcnZlciIsIl9zdXBwb3J0IiwiX2JsdWViaXJkIiwiX2hlbHBlcnMiLCJfYXhpb3MiLCJfcGF0aCIsIlJFUURfUEFSQU1TIiwiU0VSVkVSX0xBVU5DSF9USU1FT1VUIiwiU0VSVkVSX0lOU1RBTExfUkVUUklFUyIsIlNFUlZJQ0VTX0xBVU5DSF9USU1FT1VUIiwiU0VSVkVSX1BBQ0tBR0VfSUQiLCJleHBvcnRzIiwiU0VSVkVSX1RFU1RfUEFDS0FHRV9JRCIsIklOU1RSVU1FTlRBVElPTl9UQVJHRVQiLCJpbnN0cnVtZW50YXRpb25Mb2dnZXIiLCJsb2dnZXIiLCJnZXRMb2dnZXIiLCJVSUEyUHJveHkiLCJKV1Byb3h5IiwicHJveHlDb21tYW5kIiwidXJsIiwibWV0aG9kIiwiYm9keSIsImRpZEluc3RydW1lbnRhdGlvbkV4aXQiLCJlcnJvcnMiLCJJbnZhbGlkQ29udGV4dEVycm9yIiwiVWlBdXRvbWF0b3IyU2VydmVyIiwiY29uc3RydWN0b3IiLCJsb2ciLCJvcHRzIiwicmVxIiwidXRpbCIsImhhc1ZhbHVlIiwiRXJyb3IiLCJkaXNhYmxlU3VwcHJlc3NBY2Nlc3NpYmlsaXR5U2VydmljZSIsInByb3h5T3B0cyIsInNlcnZlciIsImhvc3QiLCJwb3J0Iiwic3lzdGVtUG9ydCIsImtlZXBBbGl2ZSIsInJlYWRUaW1lb3V0IiwidGltZW91dCIsImp3cHJveHkiLCJwcm94eVJlcVJlcyIsImJpbmQiLCJjb21tYW5kIiwicHJlcGFyZVNlcnZlclBhY2thZ2UiLCJhcHBQYXRoIiwiYXBwSWQiLCJ0bXBSb290IiwicmVzdWx0SW5mbyIsIndhc1NpZ25lZCIsImluc3RhbGxTdGF0ZSIsImFkYiIsIkFQUF9JTlNUQUxMX1NUQVRFIiwiTk9UX0lOU1RBTExFRCIsImNoZWNrQXBrQ2VydCIsImhlbHBlcnMiLCJpc1dyaXRlYWJsZSIsIndhcm4iLCJkc3RQYXRoIiwicGF0aCIsInJlc29sdmUiLCJiYXNlbmFtZSIsImZzIiwiY29weUZpbGUiLCJzaWduQXBwIiwiaXNBcHBJbnN0YWxsZWQiLCJTQU1FX1ZFUlNJT05fSU5TVEFMTEVEIiwiZ2V0QXBwbGljYXRpb25JbnN0YWxsU3RhdGUiLCJpbnN0YWxsU2VydmVyQXBrIiwiaW5zdGFsbFRpbWVvdXQiLCJ0ZW1wRGlyIiwib3BlbkRpciIsInBhY2thZ2VzSW5mbyIsIkIiLCJhbGwiLCJhcGtQYXRoIiwidGVzdEFwa1BhdGgiLCJtYXAiLCJkZWJ1ZyIsIkpTT04iLCJzdHJpbmdpZnkiLCJzaG91bGRVbmluc3RhbGxTZXJ2ZXJQYWNrYWdlcyIsInNvbWUiLCJldmVyeSIsInNob3VsZEluc3RhbGxTZXJ2ZXJQYWNrYWdlcyIsIk9MREVSX1ZFUlNJT05fSU5TVEFMTEVEIiwiaW5jbHVkZXMiLCJpbmZvIiwic2lsZW50VW5pbnN0YWxsUGtnIiwicGtnSWQiLCJ1bmluc3RhbGxBcGsiLCJlcnIiLCJtZXNzYWdlIiwiaW5zdGFsbFBrZyIsInBrZ1BhdGgiLCJpbnN0YWxsIiwibm9JbmNyZW1lbnRhbCIsInJlcGxhY2UiLCJ0aW1lb3V0Q2FwTmFtZSIsInJpbXJhZiIsInZlcmlmeVNlcnZpY2VzQXZhaWxhYmlsaXR5IiwiaXNQbVNlcnZpY2VBdmFpbGFibGUiLCJwbU91dHB1dCIsInBtRXJyb3IiLCJ3YWl0Rm9yQ29uZGl0aW9uIiwic2hlbGwiLCJlIiwid2FpdE1zIiwiaW50ZXJ2YWxNcyIsImVycm9yIiwibGluZSIsInNwbGl0Iiwic3RhcnRTZXNzaW9uIiwiY2FwcyIsImNsZWFudXBBdXRvbWF0aW9uTGVmdG92ZXJzIiwic2tpcFNlcnZlckluc3RhbGxhdGlvbiIsInNlcnZlclZlcnNpb24iLCJ1aWF1dG9tYXRvcjJTZXJ2ZXJMYXVuY2hUaW1lb3V0IiwidGltZXIiLCJ0aW1pbmciLCJUaW1lciIsInN0YXJ0IiwicmV0cmllcyIsIm1heFJldHJpZXMiLCJkZWxheUJldHdlZW5SZXRyaWVzIiwic3RhcnRJbnN0cnVtZW50YXRpb25Qcm9jZXNzIiwiZXJyb3JBbmRUaHJvdyIsImRlbGF5IiwiZ2V0RHVyYXRpb24iLCJhc01pbGxpU2Vjb25kcyIsInRvRml4ZWQiLCJjYXBhYmlsaXRpZXMiLCJmaXJzdE1hdGNoIiwiYWx3YXlzTWF0Y2giLCJjbWQiLCJkaXNhYmxlV2luZG93QW5pbWF0aW9uIiwicHVzaCIsIl8iLCJpc0Jvb2xlYW4iLCJpbnN0cnVtZW50YXRpb25Qcm9jZXNzIiwiY3JlYXRlU3ViUHJvY2VzcyIsIm9uIiwic3Rkb3V0Iiwic3RkZXJyIiwib3V0cHV0IiwidHJpbSIsImNvZGUiLCJkZWxldGVTZXNzaW9uIiwic3RyaWN0Q2xlYW51cCIsImF4aW9zVGltZW91dCIsIndhaXRTdG9wIiwiYXhpb3MiLCJ2YWx1ZSIsImRhdGEiLCJhY3RpdmVTZXNzaW9uSWRzIiwiaWQiLCJmaWx0ZXIiLCJCb29sZWFuIiwibGVuZ3RoIiwicGx1cmFsaXplIiwiZGVsZXRlIiwiZm9yY2VTdG9wIiwiaWdub3JlIiwia2lsbFByb2Nlc3Nlc0J5TmFtZSIsIl9kZWZhdWx0IiwiZGVmYXVsdCJdLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi91aWF1dG9tYXRvcjIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IEpXUHJveHksIGVycm9ycyB9IGZyb20gJ2FwcGl1bS9kcml2ZXInO1xuaW1wb3J0IHsgd2FpdEZvckNvbmRpdGlvbiB9IGZyb20gJ2FzeW5jYm94JztcbmltcG9ydCB7XG4gIFNFUlZFUl9BUEtfUEFUSCBhcyBhcGtQYXRoLFxuICBURVNUX0FQS19QQVRIIGFzIHRlc3RBcGtQYXRoLFxuICB2ZXJzaW9uIGFzIHNlcnZlclZlcnNpb25cbn0gZnJvbSAnYXBwaXVtLXVpYXV0b21hdG9yMi1zZXJ2ZXInO1xuaW1wb3J0IHtcbiAgdXRpbCwgbG9nZ2VyLCB0ZW1wRGlyLCBmcywgdGltaW5nXG59IGZyb20gJ2FwcGl1bS9zdXBwb3J0JztcbmltcG9ydCBCIGZyb20gJ2JsdWViaXJkJztcbmltcG9ydCBoZWxwZXJzIGZyb20gJy4vaGVscGVycyc7XG5pbXBvcnQgYXhpb3MgZnJvbSAnYXhpb3MnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5cbmNvbnN0IFJFUURfUEFSQU1TID0gWydhZGInLCAndG1wRGlyJywgJ2hvc3QnLCAnc3lzdGVtUG9ydCcsICdkZXZpY2VQb3J0JywgJ2Rpc2FibGVXaW5kb3dBbmltYXRpb24nXTtcbmNvbnN0IFNFUlZFUl9MQVVOQ0hfVElNRU9VVCA9IDMwMDAwO1xuY29uc3QgU0VSVkVSX0lOU1RBTExfUkVUUklFUyA9IDIwO1xuY29uc3QgU0VSVklDRVNfTEFVTkNIX1RJTUVPVVQgPSAzMDAwMDtcbmNvbnN0IFNFUlZFUl9QQUNLQUdFX0lEID0gJ2lvLmFwcGl1bS51aWF1dG9tYXRvcjIuc2VydmVyJztcbmNvbnN0IFNFUlZFUl9URVNUX1BBQ0tBR0VfSUQgPSBgJHtTRVJWRVJfUEFDS0FHRV9JRH0udGVzdGA7XG5jb25zdCBJTlNUUlVNRU5UQVRJT05fVEFSR0VUID0gYCR7U0VSVkVSX1RFU1RfUEFDS0FHRV9JRH0vYW5kcm9pZHgudGVzdC5ydW5uZXIuQW5kcm9pZEpVbml0UnVubmVyYDtcbmNvbnN0IGluc3RydW1lbnRhdGlvbkxvZ2dlciA9IGxvZ2dlci5nZXRMb2dnZXIoJ0luc3RydW1lbnRhdGlvbicpO1xuXG5jbGFzcyBVSUEyUHJveHkgZXh0ZW5kcyBKV1Byb3h5IHtcbiAgYXN5bmMgcHJveHlDb21tYW5kICh1cmwsIG1ldGhvZCwgYm9keSA9IG51bGwpIHtcbiAgICBpZiAodGhpcy5kaWRJbnN0cnVtZW50YXRpb25FeGl0KSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRDb250ZXh0RXJyb3IoXG4gICAgICAgIGAnJHttZXRob2R9ICR7dXJsfScgY2Fubm90IGJlIHByb3hpZWQgdG8gVWlBdXRvbWF0b3IyIHNlcnZlciBiZWNhdXNlIGAgK1xuICAgICAgICAndGhlIGluc3RydW1lbnRhdGlvbiBwcm9jZXNzIGlzIG5vdCBydW5uaW5nIChwcm9iYWJseSBjcmFzaGVkKS4gJyArXG4gICAgICAgICdDaGVjayB0aGUgc2VydmVyIGxvZyBhbmQvb3IgdGhlIGxvZ2NhdCBvdXRwdXQgZm9yIG1vcmUgZGV0YWlscycpO1xuICAgIH1cbiAgICByZXR1cm4gYXdhaXQgc3VwZXIucHJveHlDb21tYW5kKHVybCwgbWV0aG9kLCBib2R5KTtcbiAgfVxufVxuXG5jbGFzcyBVaUF1dG9tYXRvcjJTZXJ2ZXIge1xuICBjb25zdHJ1Y3RvciAobG9nLCBvcHRzID0ge30pIHtcbiAgICBmb3IgKGxldCByZXEgb2YgUkVRRF9QQVJBTVMpIHtcbiAgICAgIGlmICghb3B0cyB8fCAhdXRpbC5oYXNWYWx1ZShvcHRzW3JlcV0pKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgT3B0aW9uICcke3JlcX0nIGlzIHJlcXVpcmVkIWApO1xuICAgICAgfVxuICAgICAgdGhpc1tyZXFdID0gb3B0c1tyZXFdO1xuICAgIH1cbiAgICB0aGlzLmxvZyA9IGxvZztcbiAgICB0aGlzLmRpc2FibGVTdXBwcmVzc0FjY2Vzc2liaWxpdHlTZXJ2aWNlID0gb3B0cy5kaXNhYmxlU3VwcHJlc3NBY2Nlc3NpYmlsaXR5U2VydmljZTtcbiAgICBjb25zdCBwcm94eU9wdHMgPSB7XG4gICAgICBsb2csXG4gICAgICBzZXJ2ZXI6IHRoaXMuaG9zdCxcbiAgICAgIHBvcnQ6IHRoaXMuc3lzdGVtUG9ydCxcbiAgICAgIGtlZXBBbGl2ZTogdHJ1ZSxcbiAgICB9O1xuICAgIGlmIChvcHRzLnJlYWRUaW1lb3V0ICYmIG9wdHMucmVhZFRpbWVvdXQgPiAwKSB7XG4gICAgICBwcm94eU9wdHMudGltZW91dCA9IG9wdHMucmVhZFRpbWVvdXQ7XG4gICAgfVxuICAgIHRoaXMuandwcm94eSA9IG5ldyBVSUEyUHJveHkocHJveHlPcHRzKTtcbiAgICB0aGlzLnByb3h5UmVxUmVzID0gdGhpcy5qd3Byb3h5LnByb3h5UmVxUmVzLmJpbmQodGhpcy5qd3Byb3h5KTtcbiAgICB0aGlzLnByb3h5Q29tbWFuZCA9IHRoaXMuandwcm94eS5jb21tYW5kLmJpbmQodGhpcy5qd3Byb3h5KTtcbiAgICB0aGlzLmp3cHJveHkuZGlkSW5zdHJ1bWVudGF0aW9uRXhpdCA9IGZhbHNlO1xuICB9XG5cbiAgYXN5bmMgcHJlcGFyZVNlcnZlclBhY2thZ2UoYXBwUGF0aCwgYXBwSWQsIHRtcFJvb3QpIHtcbiAgICBjb25zdCByZXN1bHRJbmZvID0ge1xuICAgICAgd2FzU2lnbmVkOiBmYWxzZSxcbiAgICAgIGluc3RhbGxTdGF0ZTogdGhpcy5hZGIuQVBQX0lOU1RBTExfU1RBVEUuTk9UX0lOU1RBTExFRCxcbiAgICAgIGFwcFBhdGgsXG4gICAgICBhcHBJZCxcbiAgICB9O1xuXG4gICAgaWYgKGF3YWl0IHRoaXMuYWRiLmNoZWNrQXBrQ2VydChyZXN1bHRJbmZvLmFwcFBhdGgsIGFwcElkKSkge1xuICAgICAgcmVzdWx0SW5mby53YXNTaWduZWQgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIWF3YWl0IGhlbHBlcnMuaXNXcml0ZWFibGUoYXBwUGF0aCkpIHtcbiAgICAgICAgdGhpcy5sb2cud2FybihcbiAgICAgICAgICBgU2VydmVyIHBhY2thZ2UgYXQgJyR7YXBwUGF0aH0nIGlzIG5vdCB3cml0ZWFibGUuIGAgK1xuICAgICAgICAgIGBXaWxsIGNvcHkgaXQgaW50byB0aGUgdGVtcG9yYXJ5IGxvY2F0aW9uIGF0ICcke3RtcFJvb3R9JyBhcyBhIHdvcmthcm91bmQuIGAgK1xuICAgICAgICAgIGBDb25zaWRlciBtYWtpbmcgdGhpcyBmaWxlIHdyaXRlYWJsZSBtYW51YWxseSBpbiBvcmRlciB0byBpbXByb3ZlIHRoZSBwZXJmb3JtYW5jZSBvZiBzZXNzaW9uIHN0YXJ0dXAuYFxuICAgICAgICApO1xuICAgICAgICBjb25zdCBkc3RQYXRoID0gcGF0aC5yZXNvbHZlKHRtcFJvb3QsIHBhdGguYmFzZW5hbWUoYXBwUGF0aCkpO1xuICAgICAgICBhd2FpdCBmcy5jb3B5RmlsZShhcHBQYXRoLCBkc3RQYXRoKTtcbiAgICAgICAgcmVzdWx0SW5mby5hcHBQYXRoID0gZHN0UGF0aDtcbiAgICAgIH1cbiAgICAgIGF3YWl0IGhlbHBlcnMuc2lnbkFwcCh0aGlzLmFkYiwgcmVzdWx0SW5mby5hcHBQYXRoKTtcbiAgICB9XG5cbiAgICBpZiAoYXBwSWQgPT09IFNFUlZFUl9URVNUX1BBQ0tBR0VfSUQgJiYgYXdhaXQgdGhpcy5hZGIuaXNBcHBJbnN0YWxsZWQoYXBwSWQpKSB7XG4gICAgICAvLyBUaGVyZSBpcyBubyBwb2ludCBpbiBnZXR0aW5nIHRoZSBzdGF0ZSBmb3IgdGhlIHRlc3Qgc2VydmVyLFxuICAgICAgLy8gc2luY2UgaXQgZG9lcyBub3QgY29udGFpbiBhbnkgdmVyc2lvbiBpbmZvXG4gICAgICByZXN1bHRJbmZvLmluc3RhbGxTdGF0ZSA9IHRoaXMuYWRiLkFQUF9JTlNUQUxMX1NUQVRFLlNBTUVfVkVSU0lPTl9JTlNUQUxMRUQ7XG4gICAgfSBlbHNlIGlmIChhcHBJZCA9PT0gU0VSVkVSX1BBQ0tBR0VfSUQpIHtcbiAgICAgIHJlc3VsdEluZm8uaW5zdGFsbFN0YXRlID0gYXdhaXQgdGhpcy5hZGIuZ2V0QXBwbGljYXRpb25JbnN0YWxsU3RhdGUocmVzdWx0SW5mby5hcHBQYXRoLCBhcHBJZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdEluZm87XG4gIH1cblxuICAvKipcbiAgICogSW5zdGFsbHMgdGhlIGFwa3Mgb24gdG8gdGhlIGRldmljZSBvciBlbXVsYXRvci5cbiAgICpcbiAgICogQHBhcmFtIHtudW1iZXJ9IGluc3RhbGxUaW1lb3V0IC0gSW5zdGFsbGF0aW9uIHRpbWVvdXRcbiAgICovXG4gIGFzeW5jIGluc3RhbGxTZXJ2ZXJBcGsgKGluc3RhbGxUaW1lb3V0ID0gU0VSVkVSX0lOU1RBTExfUkVUUklFUyAqIDEwMDApIHtcbiAgICBjb25zdCB0bXBSb290ID0gYXdhaXQgdGVtcERpci5vcGVuRGlyKCk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHBhY2thZ2VzSW5mbyA9IGF3YWl0IEIuYWxsKFxuICAgICAgICBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYXBwUGF0aDogYXBrUGF0aCxcbiAgICAgICAgICAgIGFwcElkOiBTRVJWRVJfUEFDS0FHRV9JRCxcbiAgICAgICAgICB9LCB7XG4gICAgICAgICAgICBhcHBQYXRoOiB0ZXN0QXBrUGF0aCxcbiAgICAgICAgICAgIGFwcElkOiBTRVJWRVJfVEVTVF9QQUNLQUdFX0lELFxuICAgICAgICAgIH0sXG4gICAgICAgIF0ubWFwKCh7YXBwUGF0aCwgYXBwSWR9KSA9PiB0aGlzLnByZXBhcmVTZXJ2ZXJQYWNrYWdlKGFwcFBhdGgsIGFwcElkLCB0bXBSb290KSlcbiAgICAgICk7XG5cbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXJ2ZXIgcGFja2FnZXMgc3RhdHVzOiAke0pTT04uc3RyaW5naWZ5KHBhY2thZ2VzSW5mbyl9YCk7XG4gICAgICAvLyBXZSB3YW50IHRvIGVuZm9yY2UgdW5pbnN0YWxsIGluIGNhc2UgdGhlIGN1cnJlbnQgc2VydmVyIHBhY2thZ2UgaGFzIG5vdCBiZWVuIHNpZ25lZCBwcm9wZXJseVxuICAgICAgLy8gb3IgaWYgYW55IG9mIHNlcnZlciBwYWNrYWdlcyBpcyBub3QgaW5zdGFsbGVkLCB3aGlsZSB0aGUgb3RoZXIgZG9lc1xuICAgICAgY29uc3Qgc2hvdWxkVW5pbnN0YWxsU2VydmVyUGFja2FnZXMgPSBwYWNrYWdlc0luZm8uc29tZSgoe3dhc1NpZ25lZH0pID0+ICF3YXNTaWduZWQpXG4gICAgICAgIHx8IChwYWNrYWdlc0luZm8uc29tZSgoe2luc3RhbGxTdGF0ZX0pID0+IGluc3RhbGxTdGF0ZSA9PT0gdGhpcy5hZGIuQVBQX0lOU1RBTExfU1RBVEUuTk9UX0lOU1RBTExFRClcbiAgICAgICAgICAgICYmICFwYWNrYWdlc0luZm8uZXZlcnkoKHtpbnN0YWxsU3RhdGV9KSA9PiBpbnN0YWxsU3RhdGUgPT09IHRoaXMuYWRiLkFQUF9JTlNUQUxMX1NUQVRFLk5PVF9JTlNUQUxMRUQpKTtcbiAgICAgIC8vIEluc3RhbGwgbXVzdCBhbHdheXMgZm9sbG93IHVuaW5zdGFsbC4gQWxzbywgcGVyZm9ybSB0aGUgaW5zdGFsbCBpZlxuICAgICAgLy8gYW55IG9mIHNlcnZlciBwYWNrYWdlcyBpcyBub3QgaW5zdGFsbGVkIG9yIGlzIG91dGRhdGVkXG4gICAgICBjb25zdCBzaG91bGRJbnN0YWxsU2VydmVyUGFja2FnZXMgPSBzaG91bGRVbmluc3RhbGxTZXJ2ZXJQYWNrYWdlcyB8fCBwYWNrYWdlc0luZm8uc29tZSgoe2luc3RhbGxTdGF0ZX0pID0+IFtcbiAgICAgICAgdGhpcy5hZGIuQVBQX0lOU1RBTExfU1RBVEUuTk9UX0lOU1RBTExFRCxcbiAgICAgICAgdGhpcy5hZGIuQVBQX0lOU1RBTExfU1RBVEUuT0xERVJfVkVSU0lPTl9JTlNUQUxMRUQsXG4gICAgICBdLmluY2x1ZGVzKGluc3RhbGxTdGF0ZSkpO1xuICAgICAgdGhpcy5sb2cuaW5mbyhgU2VydmVyIHBhY2thZ2VzIGFyZSAke3Nob3VsZEluc3RhbGxTZXJ2ZXJQYWNrYWdlcyA/ICcnIDogJ25vdCAnfWdvaW5nIHRvIGJlIChyZSlpbnN0YWxsZWRgKTtcbiAgICAgIGlmIChzaG91bGRJbnN0YWxsU2VydmVyUGFja2FnZXMgJiYgc2hvdWxkVW5pbnN0YWxsU2VydmVyUGFja2FnZXMpIHtcbiAgICAgICAgdGhpcy5sb2cuaW5mbygnRnVsbCBwYWNrYWdlcyByZWluc3RhbGwgaXMgZ29pbmcgdG8gYmUgcGVyZm9ybWVkJyk7XG4gICAgICB9XG4gICAgICBpZiAoc2hvdWxkVW5pbnN0YWxsU2VydmVyUGFja2FnZXMpIHtcbiAgICAgICAgY29uc3Qgc2lsZW50VW5pbnN0YWxsUGtnID0gYXN5bmMgKHBrZ0lkKSA9PiB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuYWRiLnVuaW5zdGFsbEFwayhwa2dJZCk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICB0aGlzLmxvZy5pbmZvKGBDYW5ub3QgdW5pbnN0YWxsICcke3BrZ0lkfSc6ICR7ZXJyLm1lc3NhZ2V9YCk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBhd2FpdCBCLmFsbChwYWNrYWdlc0luZm8ubWFwKCh7YXBwSWR9KSA9PiBzaWxlbnRVbmluc3RhbGxQa2coYXBwSWQpKSk7XG4gICAgICB9XG4gICAgICBpZiAoc2hvdWxkSW5zdGFsbFNlcnZlclBhY2thZ2VzKSB7XG4gICAgICAgIGNvbnN0IGluc3RhbGxQa2cgPSBhc3luYyAocGtnUGF0aCkgPT4ge1xuICAgICAgICAgIGF3YWl0IHRoaXMuYWRiLmluc3RhbGwocGtnUGF0aCwge1xuICAgICAgICAgICAgbm9JbmNyZW1lbnRhbDogdHJ1ZSxcbiAgICAgICAgICAgIHJlcGxhY2U6IHRydWUsXG4gICAgICAgICAgICB0aW1lb3V0OiBpbnN0YWxsVGltZW91dCxcbiAgICAgICAgICAgIHRpbWVvdXRDYXBOYW1lOiAndWlhdXRvbWF0b3IyU2VydmVySW5zdGFsbFRpbWVvdXQnXG4gICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIGF3YWl0IEIuYWxsKHBhY2thZ2VzSW5mby5tYXAoKHthcHBQYXRofSkgPT4gaW5zdGFsbFBrZyhhcHBQYXRoKSkpO1xuICAgICAgfVxuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCBmcy5yaW1yYWYodG1wUm9vdCk7XG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy52ZXJpZnlTZXJ2aWNlc0F2YWlsYWJpbGl0eSgpO1xuICB9XG5cbiAgYXN5bmMgdmVyaWZ5U2VydmljZXNBdmFpbGFiaWxpdHkgKCkge1xuICAgIHRoaXMubG9nLmRlYnVnKGBXYWl0aW5nIHVwIHRvICR7U0VSVklDRVNfTEFVTkNIX1RJTUVPVVR9bXMgZm9yIHNlcnZpY2VzIHRvIGJlIGF2YWlsYWJsZWApO1xuICAgIGxldCBpc1BtU2VydmljZUF2YWlsYWJsZSA9IGZhbHNlO1xuICAgIGxldCBwbU91dHB1dCA9ICcnO1xuICAgIGxldCBwbUVycm9yID0gbnVsbDtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgd2FpdEZvckNvbmRpdGlvbihhc3luYyAoKSA9PiB7XG4gICAgICAgIGlmICghaXNQbVNlcnZpY2VBdmFpbGFibGUpIHtcbiAgICAgICAgICBwbUVycm9yID0gbnVsbDtcbiAgICAgICAgICBwbU91dHB1dCA9ICcnO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBwbU91dHB1dCA9IGF3YWl0IHRoaXMuYWRiLnNoZWxsKFsncG0nLCAnbGlzdCcsICdpbnN0cnVtZW50YXRpb24nXSk7XG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcG1FcnJvciA9IGU7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChwbU91dHB1dC5pbmNsdWRlcygnQ291bGQgbm90IGFjY2VzcyB0aGUgUGFja2FnZSBNYW5hZ2VyJykpIHtcbiAgICAgICAgICAgIHBtRXJyb3IgPSBuZXcgRXJyb3IoYFByb2JsZW0gcnVubmluZyBQYWNrYWdlIE1hbmFnZXI6ICR7cG1PdXRwdXR9YCk7XG4gICAgICAgICAgICBwbU91dHB1dCA9ICcnOyAvLyByZW1vdmUgb3V0cHV0LCBzbyBpdCBpcyBub3QgcHJpbnRlZCBiZWxvd1xuICAgICAgICAgIH0gZWxzZSBpZiAocG1PdXRwdXQuaW5jbHVkZXMoSU5TVFJVTUVOVEFUSU9OX1RBUkdFVCkpIHtcbiAgICAgICAgICAgIHBtT3V0cHV0ID0gJyc7IC8vIHJlbW92ZSBvdXRwdXQsIHNvIGl0IGlzIG5vdCBwcmludGVkIGJlbG93XG4gICAgICAgICAgICB0aGlzLmxvZy5kZWJ1ZyhgSW5zdHJ1bWVudGF0aW9uIHRhcmdldCAnJHtJTlNUUlVNRU5UQVRJT05fVEFSR0VUfScgaXMgYXZhaWxhYmxlYCk7XG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVxdWlyZS1hdG9taWMtdXBkYXRlc1xuICAgICAgICAgICAgaXNQbVNlcnZpY2VBdmFpbGFibGUgPSB0cnVlO1xuICAgICAgICAgIH0gZWxzZSBpZiAoIXBtRXJyb3IpIHtcbiAgICAgICAgICAgIHBtRXJyb3IgPSBuZXcgRXJyb3IoJ1RoZSBpbnN0cnVtZW50YXRpb24gdGFyZ2V0IGlzIG5vdCBsaXN0ZWQgYnkgUGFja2FnZSBNYW5hZ2VyJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpc1BtU2VydmljZUF2YWlsYWJsZTtcbiAgICAgIH0sIHtcbiAgICAgICAgd2FpdE1zOiBTRVJWSUNFU19MQVVOQ0hfVElNRU9VVCxcbiAgICAgICAgaW50ZXJ2YWxNczogMTAwMCxcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgdGhpcy5sb2cuZXJyb3IoYFVuYWJsZSB0byBmaW5kIGluc3RydW1lbnRhdGlvbiB0YXJnZXQgJyR7SU5TVFJVTUVOVEFUSU9OX1RBUkdFVH0nOiAkeyhwbUVycm9yIHx8IHt9KS5tZXNzYWdlfWApO1xuICAgICAgaWYgKHBtT3V0cHV0KSB7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKCdBdmFpbGFibGUgdGFyZ2V0czonKTtcbiAgICAgICAgZm9yIChjb25zdCBsaW5lIG9mIHBtT3V0cHV0LnNwbGl0KCdcXG4nKSkge1xuICAgICAgICAgIHRoaXMubG9nLmRlYnVnKGAgICAgJHtsaW5lLnJlcGxhY2UoJ2luc3RydW1lbnRhdGlvbjonLCAnJyl9YCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBhc3luYyBzdGFydFNlc3Npb24gKGNhcHMpIHtcbiAgICBhd2FpdCB0aGlzLmNsZWFudXBBdXRvbWF0aW9uTGVmdG92ZXJzKCk7XG4gICAgaWYgKGNhcHMuc2tpcFNlcnZlckluc3RhbGxhdGlvbikge1xuICAgICAgdGhpcy5sb2cuaW5mbyhgJ3NraXBTZXJ2ZXJJbnN0YWxsYXRpb24nIGlzIHNldC4gQXR0ZW1wdGluZyB0byB1c2UgVUlBdXRvbWF0b3IyIHNlcnZlciBmcm9tIHRoZSBkZXZpY2VgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5sb2cuaW5mbyhgU3RhcnRpbmcgVUlBdXRvbWF0b3IyIHNlcnZlciAke3NlcnZlclZlcnNpb259YCk7XG4gICAgICB0aGlzLmxvZy5pbmZvKGBVc2luZyBVSUF1dG9tYXRvcjIgc2VydmVyIGZyb20gJyR7YXBrUGF0aH0nIGFuZCB0ZXN0IGZyb20gJyR7dGVzdEFwa1BhdGh9J2ApO1xuICAgIH1cblxuICAgIGNvbnN0IHRpbWVvdXQgPSBjYXBzLnVpYXV0b21hdG9yMlNlcnZlckxhdW5jaFRpbWVvdXQgfHwgU0VSVkVSX0xBVU5DSF9USU1FT1VUO1xuICAgIGNvbnN0IHRpbWVyID0gbmV3IHRpbWluZy5UaW1lcigpLnN0YXJ0KCk7XG4gICAgbGV0IHJldHJpZXMgPSAwO1xuICAgIGNvbnN0IG1heFJldHJpZXMgPSAyO1xuICAgIGNvbnN0IGRlbGF5QmV0d2VlblJldHJpZXMgPSAzMDAwO1xuICAgIHdoaWxlIChyZXRyaWVzIDwgbWF4UmV0cmllcykge1xuICAgICAgdGhpcy5sb2cuaW5mbyhgV2FpdGluZyB1cCB0byAke3RpbWVvdXR9bXMgZm9yIFVpQXV0b21hdG9yMiB0byBiZSBvbmxpbmUuLi5gKTtcbiAgICAgIHRoaXMuandwcm94eS5kaWRJbnN0cnVtZW50YXRpb25FeGl0ID0gZmFsc2U7XG4gICAgICBhd2FpdCB0aGlzLnN0YXJ0SW5zdHJ1bWVudGF0aW9uUHJvY2VzcygpO1xuICAgICAgaWYgKCF0aGlzLmp3cHJveHkuZGlkSW5zdHJ1bWVudGF0aW9uRXhpdCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHdhaXRGb3JDb25kaXRpb24oYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgYXdhaXQgdGhpcy5qd3Byb3h5LmNvbW1hbmQoJy9zdGF0dXMnLCAnR0VUJyk7XG4gICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgIC8vIHNob3J0IGNpcmN1aXQgdG8gcmV0cnkgb3IgZmFpbCBmYXN0XG4gICAgICAgICAgICAgIHJldHVybiB0aGlzLmp3cHJveHkuZGlkSW5zdHJ1bWVudGF0aW9uRXhpdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LCB7XG4gICAgICAgICAgICB3YWl0TXM6IHRpbWVvdXQsXG4gICAgICAgICAgICBpbnRlcnZhbE1zOiAxMDAwLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICB0aGlzLmxvZy5lcnJvckFuZFRocm93KGBUaGUgaW5zdHJ1bWVudGF0aW9uIHByb2Nlc3MgY2Fubm90IGJlIGluaXRpYWxpemVkIHdpdGhpbiAke3RpbWVvdXR9bXMgdGltZW91dC4gYFxuICAgICAgICAgICAgKyAnTWFrZSBzdXJlIHRoZSBhcHBsaWNhdGlvbiB1bmRlciB0ZXN0IGRvZXMgbm90IGNyYXNoIGFuZCBpbnZlc3RpZ2F0ZSB0aGUgbG9nY2F0IG91dHB1dC4gJ1xuICAgICAgICAgICAgKyBgWW91IGNvdWxkIGFsc28gdHJ5IHRvIGluY3JlYXNlIHRoZSB2YWx1ZSBvZiAndWlhdXRvbWF0b3IyU2VydmVyTGF1bmNoVGltZW91dCcgY2FwYWJpbGl0eWApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoIXRoaXMuandwcm94eS5kaWRJbnN0cnVtZW50YXRpb25FeGl0KSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICByZXRyaWVzKys7XG4gICAgICBpZiAocmV0cmllcyA+PSBtYXhSZXRyaWVzKSB7XG4gICAgICAgIHRoaXMubG9nLmVycm9yQW5kVGhyb3coJ1RoZSBpbnN0cnVtZW50YXRpb24gcHJvY2VzcyBjYW5ub3QgYmUgaW5pdGlhbGl6ZWQuICdcbiAgICAgICAgICArICdNYWtlIHN1cmUgdGhlIGFwcGxpY2F0aW9uIHVuZGVyIHRlc3QgZG9lcyBub3QgY3Jhc2ggYW5kIGludmVzdGlnYXRlIHRoZSBsb2djYXQgb3V0cHV0LicpO1xuICAgICAgfVxuICAgICAgdGhpcy5sb2cud2FybihgVGhlIGluc3RydW1lbnRhdGlvbiBwcm9jZXNzIGhhcyBiZWVuIHVuZXhwZWN0ZWRseSB0ZXJtaW5hdGVkLiBgXG4gICAgICAgICsgYFJldHJ5aW5nIFVpQXV0b21hdG9yMiBzdGFydHVwICgjJHtyZXRyaWVzfSBvZiAke21heFJldHJpZXMgLSAxfSlgKTtcbiAgICAgIGF3YWl0IHRoaXMuY2xlYW51cEF1dG9tYXRpb25MZWZ0b3ZlcnModHJ1ZSk7XG4gICAgICBhd2FpdCBCLmRlbGF5KGRlbGF5QmV0d2VlblJldHJpZXMpO1xuICAgIH1cblxuICAgIHRoaXMubG9nLmRlYnVnKGBUaGUgaW5pdGlhbGl6YXRpb24gb2YgdGhlIGluc3RydW1lbnRhdGlvbiBwcm9jZXNzIHRvb2sgYFxuICAgICAgKyBgJHt0aW1lci5nZXREdXJhdGlvbigpLmFzTWlsbGlTZWNvbmRzLnRvRml4ZWQoMCl9bXNgKTtcbiAgICBhd2FpdCB0aGlzLmp3cHJveHkuY29tbWFuZCgnL3Nlc3Npb24nLCAnUE9TVCcsIHtcbiAgICAgIGNhcGFiaWxpdGllczoge1xuICAgICAgICBmaXJzdE1hdGNoOiBbY2Fwc10sXG4gICAgICAgIGFsd2F5c01hdGNoOiB7fSxcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIHN0YXJ0SW5zdHJ1bWVudGF0aW9uUHJvY2VzcyAoKSB7XG4gICAgY29uc3QgY21kID0gWydhbScsICdpbnN0cnVtZW50JywgJy13J107XG4gICAgaWYgKHRoaXMuZGlzYWJsZVdpbmRvd0FuaW1hdGlvbikge1xuICAgICAgY21kLnB1c2goJy0tbm8td2luZG93LWFuaW1hdGlvbicpO1xuICAgIH1cbiAgICBpZiAoXy5pc0Jvb2xlYW4odGhpcy5kaXNhYmxlU3VwcHJlc3NBY2Nlc3NpYmlsaXR5U2VydmljZSkpIHtcbiAgICAgIGNtZC5wdXNoKCctZScsICdESVNBQkxFX1NVUFBSRVNTX0FDQ0VTU0lCSUxJVFlfU0VSVklDRVMnLCB0aGlzLmRpc2FibGVTdXBwcmVzc0FjY2Vzc2liaWxpdHlTZXJ2aWNlKTtcbiAgICB9XG4gICAgLy8gRGlzYWJsZSBHb29nbGUgYW5hbHl0aWNzIHRvIHByZXZlbnQgcG9zc2libGUgZmF0YWwgZXhjZXB0aW9uXG4gICAgY21kLnB1c2goJy1lJywgJ2Rpc2FibGVBbmFseXRpY3MnLCB0cnVlKTtcbiAgICBjbWQucHVzaChJTlNUUlVNRU5UQVRJT05fVEFSR0VUKTtcbiAgICBjb25zdCBpbnN0cnVtZW50YXRpb25Qcm9jZXNzID0gdGhpcy5hZGIuY3JlYXRlU3ViUHJvY2VzcyhbJ3NoZWxsJywgLi4uY21kXSk7XG4gICAgaW5zdHJ1bWVudGF0aW9uUHJvY2Vzcy5vbignb3V0cHV0JywgKHN0ZG91dCwgc3RkZXJyKSA9PiB7XG4gICAgICBjb25zdCBvdXRwdXQgPSBfLnRyaW0oc3Rkb3V0IHx8IHN0ZGVycik7XG4gICAgICBpZiAob3V0cHV0KSB7XG4gICAgICAgIGluc3RydW1lbnRhdGlvbkxvZ2dlci5kZWJ1ZyhvdXRwdXQpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGluc3RydW1lbnRhdGlvblByb2Nlc3Mub24oJ2V4aXQnLCAoY29kZSkgPT4ge1xuICAgICAgaW5zdHJ1bWVudGF0aW9uTG9nZ2VyLmRlYnVnKGBUaGUgcHJvY2VzcyBoYXMgZXhpdGVkIHdpdGggY29kZSAke2NvZGV9YCk7XG4gICAgICB0aGlzLmp3cHJveHkuZGlkSW5zdHJ1bWVudGF0aW9uRXhpdCA9IHRydWU7XG4gICAgfSk7XG4gICAgYXdhaXQgaW5zdHJ1bWVudGF0aW9uUHJvY2Vzcy5zdGFydCgwKTtcbiAgfVxuXG4gIGFzeW5jIGRlbGV0ZVNlc3Npb24gKCkge1xuICAgIHRoaXMubG9nLmRlYnVnKCdEZWxldGluZyBVaUF1dG9tYXRvcjIgc2VydmVyIHNlc3Npb24nKTtcbiAgICAvLyByZWx5IG9uIGp3cHJveHkncyBpbnRlbGxpZ2VuY2UgdG8ga25vdyB3aGF0IHdlJ3JlIHRhbGtpbmcgYWJvdXQgYW5kXG4gICAgLy8gZGVsZXRlIHRoZSBjdXJyZW50IHNlc3Npb25cbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5qd3Byb3h5LmNvbW1hbmQoJy8nLCAnREVMRVRFJyk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aGlzLmxvZy53YXJuKGBEaWQgbm90IGdldCBjb25maXJtYXRpb24gVWlBdXRvbWF0b3IyIGRlbGV0ZVNlc3Npb24gd29ya2VkOyBgICtcbiAgICAgICAgICBgRXJyb3Igd2FzOiAke2Vycn1gKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBjbGVhbnVwQXV0b21hdGlvbkxlZnRvdmVycyAoc3RyaWN0Q2xlYW51cCA9IGZhbHNlKSB7XG4gICAgdGhpcy5sb2cuZGVidWcoYFBlcmZvcm1pbmcgJHtzdHJpY3RDbGVhbnVwID8gJ3N0cmljdCcgOiAnc2hhbGxvdyd9IGNsZWFudXAgb2YgYXV0b21hdGlvbiBsZWZ0b3ZlcnNgKTtcblxuICAgIGNvbnN0IGF4aW9zVGltZW91dCA9IDUwMDtcblxuICAgIGNvbnN0IHdhaXRTdG9wID0gYXN5bmMgKCkgPT4ge1xuICAgICAgLy8gV2FpdCBmb3IgdGhlIHByb2Nlc3Mgc3RvcCBieSBzZW5kaW5nIGEgc3RhdHVzIHJlcXVlc3QgdG8gdGhlIHBvcnQuXG4gICAgICAvLyBXZSBvYnNlcnZlZCB0aGUgcHJvY2VzcyBzdG9wIGNvdWxkIGJlIGRlbGF5ZWQsIHRodXMgY2F1c2luZyB1bmV4cGVjdGVkIGNyYXNoZXNcbiAgICAgIC8vIGluIHRoZSBtaWRkbGUgb2YgdGhlIHNlc3Npb24gcHJlcGFyYXRpb24gcHJvY2Vzcy4gSXQgY2F1c2VkIGFuIGludmFsaWQgc2Vzc2lvbiBlcnJvciByZXNwb25zZVxuICAgICAgLy8gYnkgdGhlIHVpYTIgc2VydmVyLCBidXQgdGhhdCB3YXMgYmVjYXVzZSB0aGUgcHJvY2VzcyBzdG9wJ3MgZGVsYXkuXG4gICAgICBjb25zdCB0aW1lb3V0ID0gMzAwMDtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHdhaXRGb3JDb25kaXRpb24oYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBheGlvcyh7XG4gICAgICAgICAgICAgIHVybDogYGh0dHA6Ly8ke3RoaXMuaG9zdH06JHt0aGlzLnN5c3RlbVBvcnR9L3N0YXR1c2AsXG4gICAgICAgICAgICAgIHRpbWVvdXQ6IGF4aW9zVGltZW91dCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgd2FpdE1zOiB0aW1lb3V0LFxuICAgICAgICAgIGludGVydmFsTXM6IDEwMCxcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgdGhpcy5sb2cud2FybihgVGhlICR7U0VSVkVSX1RFU1RfUEFDS0FHRV9JRH0gcHJvY2VzcyBtaWdodCBmYWlsIHRvIHN0b3Agd2l0aGluICR7dGltZW91dH1tcyB0aW1lb3V0LmApO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB0cnkge1xuICAgICAgY29uc3Qge3ZhbHVlfSA9IChhd2FpdCBheGlvcyh7XG4gICAgICAgIHVybDogYGh0dHA6Ly8ke3RoaXMuaG9zdH06JHt0aGlzLnN5c3RlbVBvcnR9L3Nlc3Npb25zYCxcbiAgICAgICAgdGltZW91dDogYXhpb3NUaW1lb3V0LFxuICAgICAgfSkpLmRhdGE7XG4gICAgICBjb25zdCBhY3RpdmVTZXNzaW9uSWRzID0gdmFsdWUubWFwKCh7aWR9KSA9PiBpZCkuZmlsdGVyKEJvb2xlYW4pO1xuICAgICAgaWYgKGFjdGl2ZVNlc3Npb25JZHMubGVuZ3RoKSB7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKGBUaGUgZm9sbG93aW5nIG9ic29sZXRlIHNlc3Npb25zIGFyZSBzdGlsbCBydW5uaW5nOiAke0pTT04uc3RyaW5naWZ5KGFjdGl2ZVNlc3Npb25JZHMpfWApO1xuICAgICAgICB0aGlzLmxvZy5kZWJ1ZyhgQ2xlYW5pbmcgdXAgJHt1dGlsLnBsdXJhbGl6ZSgnb2Jzb2xldGUgc2Vzc2lvbicsIGFjdGl2ZVNlc3Npb25JZHMubGVuZ3RoLCB0cnVlKX1gKTtcbiAgICAgICAgYXdhaXQgQi5hbGwoYWN0aXZlU2Vzc2lvbklkc1xuICAgICAgICAgIC5tYXAoKGlkKSA9PiBheGlvcy5kZWxldGUoYGh0dHA6Ly8ke3RoaXMuaG9zdH06JHt0aGlzLnN5c3RlbVBvcnR9L3Nlc3Npb24vJHtpZH1gKSlcbiAgICAgICAgKTtcbiAgICAgICAgLy8gTGV0IGFsbCBzZXNzaW9ucyB0byBiZSBwcm9wZXJseSB0ZXJtaW5hdGVkIGJlZm9yZSBjb250aW51aW5nXG4gICAgICAgIGF3YWl0IEIuZGVsYXkoMTAwMCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmxvZy5kZWJ1ZygnTm8gb2Jzb2xldGUgc2Vzc2lvbnMgaGF2ZSBiZWVuIGRldGVjdGVkJyk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYE5vIG9ic29sZXRlIHNlc3Npb25zIGhhdmUgYmVlbiBkZXRlY3RlZCAoJHtlLm1lc3NhZ2V9KWApO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmFkYi5mb3JjZVN0b3AoU0VSVkVSX1RFU1RfUEFDS0FHRV9JRCk7XG4gICAgfSBjYXRjaCAoaWdub3JlKSB7fVxuICAgIGlmIChzdHJpY3RDbGVhbnVwKSB7XG4gICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vYXBwaXVtL2FwcGl1bS9pc3N1ZXMvMTA3NDlcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRoaXMuYWRiLmtpbGxQcm9jZXNzZXNCeU5hbWUoJ3VpYXV0b21hdG9yJyk7XG4gICAgICB9IGNhdGNoIChpZ25vcmUpIHt9XG4gICAgfVxuICAgIGF3YWl0IHdhaXRTdG9wKCk7XG4gIH1cbn1cblxuZXhwb3J0IHsgVWlBdXRvbWF0b3IyU2VydmVyLCBJTlNUUlVNRU5UQVRJT05fVEFSR0VULCBTRVJWRVJfUEFDS0FHRV9JRCwgU0VSVkVSX1RFU1RfUEFDS0FHRV9JRCB9O1xuZXhwb3J0IGRlZmF1bHQgVWlBdXRvbWF0b3IyU2VydmVyO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQUFBLElBQUFBLE9BQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLE9BQUEsR0FBQUQsT0FBQTtBQUNBLElBQUFFLFNBQUEsR0FBQUYsT0FBQTtBQUNBLElBQUFHLHlCQUFBLEdBQUFILE9BQUE7QUFLQSxJQUFBSSxRQUFBLEdBQUFKLE9BQUE7QUFHQSxJQUFBSyxTQUFBLEdBQUFOLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBTSxRQUFBLEdBQUFQLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBTyxNQUFBLEdBQUFSLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBUSxLQUFBLEdBQUFULHNCQUFBLENBQUFDLE9BQUE7QUFFQSxNQUFNUyxXQUFXLEdBQUcsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLHdCQUF3QixDQUFDO0FBQ25HLE1BQU1DLHFCQUFxQixHQUFHLEtBQUs7QUFDbkMsTUFBTUMsc0JBQXNCLEdBQUcsRUFBRTtBQUNqQyxNQUFNQyx1QkFBdUIsR0FBRyxLQUFLO0FBQ3JDLE1BQU1DLGlCQUFpQixHQUFHLCtCQUErQjtBQUFDQyxPQUFBLENBQUFELGlCQUFBLEdBQUFBLGlCQUFBO0FBQzFELE1BQU1FLHNCQUFzQixHQUFJLEdBQUVGLGlCQUFrQixPQUFNO0FBQUNDLE9BQUEsQ0FBQUMsc0JBQUEsR0FBQUEsc0JBQUE7QUFDM0QsTUFBTUMsc0JBQXNCLEdBQUksR0FBRUQsc0JBQXVCLDBDQUF5QztBQUFDRCxPQUFBLENBQUFFLHNCQUFBLEdBQUFBLHNCQUFBO0FBQ25HLE1BQU1DLHFCQUFxQixHQUFHQyxlQUFNLENBQUNDLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQztBQUVqRSxNQUFNQyxTQUFTLFNBQVNDLGVBQU8sQ0FBQztFQUM5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
363
+ exports.default = UiAutomator2Server;
364
+ //# sourceMappingURL=uiautomator2.js.map