appium-uiautomator2-driver 2.29.11 → 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 +7 -0
  2. package/build/index.d.ts +4 -0
  3. package/build/index.d.ts.map +1 -0
  4. package/build/index.js +8 -15
  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 -62
  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 -26
  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 -57
  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 -16
  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 -159
  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 -25
  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 -215
  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 -193
  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 -22
  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 -62
  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 -38
  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 -35
  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 -175
  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 -482
  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 +7 -9
  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 -29
  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 -10
  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 -17
  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 +340 -299
  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 +363 -492
  131. package/package.json +95 -69
  132. package/build/lib/desired-caps.js +0 -71
  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,323 +1,364 @@
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;
21
19
  const SERVICES_LAUNCH_TIMEOUT = 30000;
22
- const SERVER_PACKAGE_ID = exports.SERVER_PACKAGE_ID = 'io.appium.uiautomator2.server';
23
- const SERVER_TEST_PACKAGE_ID = exports.SERVER_TEST_PACKAGE_ID = `${SERVER_PACKAGE_ID}.test`;
24
- const INSTRUMENTATION_TARGET = exports.INSTRUMENTATION_TARGET = `${SERVER_TEST_PACKAGE_ID}/androidx.test.runner.AndroidJUnitRunner`;
25
- const instrumentationLogger = _support.logger.getLogger('Instrumentation');
26
- class UIA2Proxy extends _driver.JWProxy {
27
- async proxyCommand(url, method, body = null) {
28
- if (this.didInstrumentationExit) {
29
- 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');
20
+ const SERVER_PACKAGE_ID = 'io.appium.uiautomator2.server';
21
+ exports.SERVER_PACKAGE_ID = SERVER_PACKAGE_ID;
22
+ const SERVER_TEST_PACKAGE_ID = `${SERVER_PACKAGE_ID}.test`;
23
+ exports.SERVER_TEST_PACKAGE_ID = SERVER_TEST_PACKAGE_ID;
24
+ const INSTRUMENTATION_TARGET = `${SERVER_TEST_PACKAGE_ID}/androidx.test.runner.AndroidJUnitRunner`;
25
+ exports.INSTRUMENTATION_TARGET = INSTRUMENTATION_TARGET;
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);
30
35
  }
31
- return await super.proxyCommand(url, method, body);
32
- }
33
36
  }
34
37
  class UiAutomator2Server {
35
- constructor(log, opts = {}) {
36
- for (let req of REQD_PARAMS) {
37
- if (!opts || !_support.util.hasValue(opts[req])) {
38
- throw new Error(`Option '${req}' is required!`);
39
- }
40
- this[req] = opts[req];
41
- }
42
- this.log = log;
43
- this.disableSuppressAccessibilityService = opts.disableSuppressAccessibilityService;
44
- const proxyOpts = {
45
- log,
46
- server: this.host,
47
- port: this.systemPort,
48
- keepAlive: true
49
- };
50
- if (opts.readTimeout && opts.readTimeout > 0) {
51
- proxyOpts.timeout = opts.readTimeout;
52
- }
53
- this.jwproxy = new UIA2Proxy(proxyOpts);
54
- this.proxyReqRes = this.jwproxy.proxyReqRes.bind(this.jwproxy);
55
- this.proxyCommand = this.jwproxy.command.bind(this.jwproxy);
56
- this.jwproxy.didInstrumentationExit = false;
57
- }
58
- async prepareServerPackage(appPath, appId, tmpRoot) {
59
- const resultInfo = {
60
- wasSigned: false,
61
- installState: this.adb.APP_INSTALL_STATE.NOT_INSTALLED,
62
- appPath,
63
- appId
64
- };
65
- if (await this.adb.checkApkCert(resultInfo.appPath, appId)) {
66
- resultInfo.wasSigned = true;
67
- } else {
68
- if (!(await _helpers.default.isWriteable(appPath))) {
69
- 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.`);
70
- const dstPath = _path.default.resolve(tmpRoot, _path.default.basename(appPath));
71
- await _support.fs.copyFile(appPath, dstPath);
72
- resultInfo.appPath = dstPath;
73
- }
74
- await _helpers.default.signApp(this.adb, resultInfo.appPath);
75
- }
76
- if (appId === SERVER_TEST_PACKAGE_ID && (await this.adb.isAppInstalled(appId))) {
77
- resultInfo.installState = this.adb.APP_INSTALL_STATE.SAME_VERSION_INSTALLED;
78
- } else if (appId === SERVER_PACKAGE_ID) {
79
- resultInfo.installState = await this.adb.getApplicationInstallState(resultInfo.appPath, appId);
80
- }
81
- return resultInfo;
82
- }
83
- async installServerApk(installTimeout = SERVER_INSTALL_RETRIES * 1000) {
84
- const tmpRoot = await _support.tempDir.openDir();
85
- try {
86
- const packagesInfo = await _bluebird.default.all([{
87
- appPath: _appiumUiautomator2Server.SERVER_APK_PATH,
88
- appId: SERVER_PACKAGE_ID
89
- }, {
90
- appPath: _appiumUiautomator2Server.TEST_APK_PATH,
91
- appId: SERVER_TEST_PACKAGE_ID
92
- }].map(({
93
- appPath,
94
- appId
95
- }) => this.prepareServerPackage(appPath, appId, tmpRoot)));
96
- this.log.debug(`Server packages status: ${JSON.stringify(packagesInfo)}`);
97
- const shouldUninstallServerPackages = packagesInfo.some(({
98
- wasSigned
99
- }) => !wasSigned) || packagesInfo.some(({
100
- installState
101
- }) => installState === this.adb.APP_INSTALL_STATE.NOT_INSTALLED) && !packagesInfo.every(({
102
- installState
103
- }) => installState === this.adb.APP_INSTALL_STATE.NOT_INSTALLED);
104
- const shouldInstallServerPackages = shouldUninstallServerPackages || packagesInfo.some(({
105
- installState
106
- }) => [this.adb.APP_INSTALL_STATE.NOT_INSTALLED, this.adb.APP_INSTALL_STATE.OLDER_VERSION_INSTALLED].includes(installState));
107
- this.log.info(`Server packages are ${shouldInstallServerPackages ? '' : 'not '}going to be (re)installed`);
108
- if (shouldInstallServerPackages && shouldUninstallServerPackages) {
109
- this.log.info('Full packages reinstall is going to be performed');
110
- }
111
- if (shouldUninstallServerPackages) {
112
- const silentUninstallPkg = async pkgId => {
113
- try {
114
- await this.adb.uninstallApk(pkgId);
115
- } catch (err) {
116
- this.log.info(`Cannot uninstall '${pkgId}': ${err.message}`);
117
- }
118
- };
119
- await _bluebird.default.all(packagesInfo.map(({
120
- appId
121
- }) => silentUninstallPkg(appId)));
122
- }
123
- if (shouldInstallServerPackages) {
124
- const installPkg = async pkgPath => {
125
- await this.adb.install(pkgPath, {
126
- noIncremental: true,
127
- replace: true,
128
- timeout: installTimeout,
129
- timeoutCapName: 'uiautomator2ServerInstallTimeout'
130
- });
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,
131
52
  };
132
- await _bluebird.default.all(packagesInfo.map(({
133
- appPath
134
- }) => installPkg(appPath)));
135
- }
136
- } finally {
137
- 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;
138
60
  }
139
- await this.verifyServicesAvailability();
140
- }
141
- async verifyServicesAvailability() {
142
- this.log.debug(`Waiting up to ${SERVICES_LAUNCH_TIMEOUT}ms for services to be available`);
143
- let isPmServiceAvailable = false;
144
- let pmOutput = '';
145
- let pmError = null;
146
- try {
147
- await (0, _asyncbox.waitForCondition)(async () => {
148
- if (!isPmServiceAvailable) {
149
- pmError = null;
150
- pmOutput = '';
151
- try {
152
- pmOutput = await this.adb.shell(['pm', 'list', 'instrumentation']);
153
- } catch (e) {
154
- pmError = e;
155
- }
156
- if (pmOutput.includes('Could not access the Package Manager')) {
157
- pmError = new Error(`Problem running Package Manager: ${pmOutput}`);
158
- pmOutput = '';
159
- } else if (pmOutput.includes(INSTRUMENTATION_TARGET)) {
160
- pmOutput = '';
161
- this.log.debug(`Instrumentation target '${INSTRUMENTATION_TARGET}' is available`);
162
- isPmServiceAvailable = true;
163
- } else if (!pmError) {
164
- pmError = new Error('The instrumentation target is not listed by Package Manager');
165
- }
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;
166
70
  }
167
- return isPmServiceAvailable;
168
- }, {
169
- waitMs: SERVICES_LAUNCH_TIMEOUT,
170
- intervalMs: 1000
171
- });
172
- } catch (err) {
173
- this.log.error(`Unable to find instrumentation target '${INSTRUMENTATION_TARGET}': ${(pmError || {}).message}`);
174
- if (pmOutput) {
175
- this.log.debug('Available targets:');
176
- for (const line of pmOutput.split('\n')) {
177
- 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);
178
81
  }
179
- }
180
- }
181
- }
182
- async startSession(caps) {
183
- await this.cleanupAutomationLeftovers();
184
- if (caps.skipServerInstallation) {
185
- this.log.info(`'skipServerInstallation' is set. Attempting to use UIAutomator2 server from the device`);
186
- } else {
187
- this.log.info(`Starting UIAutomator2 server ${_appiumUiautomator2Server.version}`);
188
- 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;
189
91
  }
190
- const timeout = caps.uiautomator2ServerLaunchTimeout || SERVER_LAUNCH_TIMEOUT;
191
- const timer = new _support.timing.Timer().start();
192
- let retries = 0;
193
- const maxRetries = 2;
194
- const delayBetweenRetries = 3000;
195
- while (retries < maxRetries) {
196
- this.log.info(`Waiting up to ${timeout}ms for UiAutomator2 to be online...`);
197
- this.jwproxy.didInstrumentationExit = false;
198
- await this.startInstrumentationProcess();
199
- 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();
200
99
  try {
201
- await (0, _asyncbox.waitForCondition)(async () => {
202
- try {
203
- await this.jwproxy.command('/status', 'GET');
204
- return true;
205
- } catch (err) {
206
- 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)));
207
146
  }
208
- }, {
209
- waitMs: timeout,
210
- intervalMs: 1000
211
- });
212
- } catch (err) {
213
- 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`);
214
147
  }
215
- }
216
- if (!this.jwproxy.didInstrumentationExit) {
217
- break;
218
- }
219
- retries++;
220
- if (retries >= maxRetries) {
221
- this.log.errorAndThrow('The instrumentation process cannot be initialized. ' + 'Make sure the application under test does not crash and investigate the logcat output.');
222
- }
223
- this.log.warn(`The instrumentation process has been unexpectedly terminated. ` + `Retrying UiAutomator2 startup (#${retries} of ${maxRetries - 1})`);
224
- await this.cleanupAutomationLeftovers(true);
225
- await _bluebird.default.delay(delayBetweenRetries);
226
- }
227
- this.log.debug(`The initialization of the instrumentation process took ` + `${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
228
- await this.jwproxy.command('/session', 'POST', {
229
- capabilities: {
230
- firstMatch: [caps],
231
- alwaysMatch: {}
232
- }
233
- });
234
- }
235
- async startInstrumentationProcess() {
236
- const cmd = ['am', 'instrument', '-w'];
237
- if (this.disableWindowAnimation) {
238
- cmd.push('--no-window-animation');
148
+ finally {
149
+ await support_1.fs.rimraf(tmpRoot);
150
+ }
151
+ await this.verifyServicesAvailability();
239
152
  }
240
- if (_lodash.default.isBoolean(this.disableSuppressAccessibilityService)) {
241
- 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
+ }
242
199
  }
243
- cmd.push('-e', 'disableAnalytics', true);
244
- cmd.push(INSTRUMENTATION_TARGET);
245
- const instrumentationProcess = this.adb.createSubProcess(['shell', ...cmd]);
246
- instrumentationProcess.on('output', (stdout, stderr) => {
247
- const output = _lodash.default.trim(stdout || stderr);
248
- if (output) {
249
- instrumentationLogger.debug(output);
250
- }
251
- });
252
- instrumentationProcess.on('exit', code => {
253
- instrumentationLogger.debug(`The process has exited with code ${code}`);
254
- this.jwproxy.didInstrumentationExit = true;
255
- });
256
- await instrumentationProcess.start(0);
257
- }
258
- async deleteSession() {
259
- this.log.debug('Deleting UiAutomator2 server session');
260
- try {
261
- await this.jwproxy.command('/', 'DELETE');
262
- } catch (err) {
263
- 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
+ });
264
261
  }
265
- }
266
- async cleanupAutomationLeftovers(strictCleanup = false) {
267
- this.log.debug(`Performing ${strictCleanup ? 'strict' : 'shallow'} cleanup of automation leftovers`);
268
- const axiosTimeout = 500;
269
- const waitStop = async () => {
270
- const timeout = 3000;
271
- try {
272
- await (0, _asyncbox.waitForCondition)(async () => {
273
- try {
274
- await (0, _axios.default)({
275
- url: `http://${this.host}:${this.systemPort}/status`,
276
- timeout: axiosTimeout
277
- });
278
- } catch (err) {
279
- return true;
280
- }
281
- }, {
282
- waitMs: timeout,
283
- 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;
284
283
  });
285
- } catch (err) {
286
- this.log.warn(`The ${SERVER_TEST_PACKAGE_ID} process might fail to stop within ${timeout}ms timeout.`);
287
- }
288
- };
289
- try {
290
- const {
291
- value
292
- } = (await (0, _axios.default)({
293
- url: `http://${this.host}:${this.systemPort}/sessions`,
294
- timeout: axiosTimeout
295
- })).data;
296
- const activeSessionIds = value.map(({
297
- id
298
- }) => id).filter(Boolean);
299
- if (activeSessionIds.length) {
300
- this.log.debug(`The following obsolete sessions are still running: ${JSON.stringify(activeSessionIds)}`);
301
- this.log.debug(`Cleaning up ${_support.util.pluralize('obsolete session', activeSessionIds.length, true)}`);
302
- await _bluebird.default.all(activeSessionIds.map(id => _axios.default.delete(`http://${this.host}:${this.systemPort}/session/${id}`)));
303
- await _bluebird.default.delay(1000);
304
- } else {
305
- this.log.debug('No obsolete sessions have been detected');
306
- }
307
- } catch (e) {
308
- this.log.debug(`No obsolete sessions have been detected (${e.message})`);
284
+ await instrumentationProcess.start(0);
309
285
  }
310
- try {
311
- await this.adb.forceStop(SERVER_TEST_PACKAGE_ID);
312
- } catch (ignore) {}
313
- if (strictCleanup) {
314
- try {
315
- await this.adb.killProcessesByName('uiautomator');
316
- } 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();
317
360
  }
318
- await waitStop();
319
- }
320
361
  }
321
362
  exports.UiAutomator2Server = UiAutomator2Server;
322
- var _default = exports.default = UiAutomator2Server;
323
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbG9kYXNoIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfZHJpdmVyIiwiX2FzeW5jYm94IiwiX2FwcGl1bVVpYXV0b21hdG9yMlNlcnZlciIsIl9zdXBwb3J0IiwiX2JsdWViaXJkIiwiX2hlbHBlcnMiLCJfYXhpb3MiLCJfcGF0aCIsIlJFUURfUEFSQU1TIiwiU0VSVkVSX0xBVU5DSF9USU1FT1VUIiwiU0VSVkVSX0lOU1RBTExfUkVUUklFUyIsIlNFUlZJQ0VTX0xBVU5DSF9USU1FT1VUIiwiU0VSVkVSX1BBQ0tBR0VfSUQiLCJleHBvcnRzIiwiU0VSVkVSX1RFU1RfUEFDS0FHRV9JRCIsIklOU1RSVU1FTlRBVElPTl9UQVJHRVQiLCJpbnN0cnVtZW50YXRpb25Mb2dnZXIiLCJsb2dnZXIiLCJnZXRMb2dnZXIiLCJVSUEyUHJveHkiLCJKV1Byb3h5IiwicHJveHlDb21tYW5kIiwidXJsIiwibWV0aG9kIiwiYm9keSIsImRpZEluc3RydW1lbnRhdGlvbkV4aXQiLCJlcnJvcnMiLCJJbnZhbGlkQ29udGV4dEVycm9yIiwiVWlBdXRvbWF0b3IyU2VydmVyIiwiY29uc3RydWN0b3IiLCJsb2ciLCJvcHRzIiwicmVxIiwidXRpbCIsImhhc1ZhbHVlIiwiRXJyb3IiLCJkaXNhYmxlU3VwcHJlc3NBY2Nlc3NpYmlsaXR5U2VydmljZSIsInByb3h5T3B0cyIsInNlcnZlciIsImhvc3QiLCJwb3J0Iiwic3lzdGVtUG9ydCIsImtlZXBBbGl2ZSIsInJlYWRUaW1lb3V0IiwidGltZW91dCIsImp3cHJveHkiLCJwcm94eVJlcVJlcyIsImJpbmQiLCJjb21tYW5kIiwicHJlcGFyZVNlcnZlclBhY2thZ2UiLCJhcHBQYXRoIiwiYXBwSWQiLCJ0bXBSb290IiwicmVzdWx0SW5mbyIsIndhc1NpZ25lZCIsImluc3RhbGxTdGF0ZSIsImFkYiIsIkFQUF9JTlNUQUxMX1NUQVRFIiwiTk9UX0lOU1RBTExFRCIsImNoZWNrQXBrQ2VydCIsImhlbHBlcnMiLCJpc1dyaXRlYWJsZSIsIndhcm4iLCJkc3RQYXRoIiwicGF0aCIsInJlc29sdmUiLCJiYXNlbmFtZSIsImZzIiwiY29weUZpbGUiLCJzaWduQXBwIiwiaXNBcHBJbnN0YWxsZWQiLCJTQU1FX1ZFUlNJT05fSU5TVEFMTEVEIiwiZ2V0QXBwbGljYXRpb25JbnN0YWxsU3RhdGUiLCJpbnN0YWxsU2VydmVyQXBrIiwiaW5zdGFsbFRpbWVvdXQiLCJ0ZW1wRGlyIiwib3BlbkRpciIsInBhY2thZ2VzSW5mbyIsIkIiLCJhbGwiLCJhcGtQYXRoIiwidGVzdEFwa1BhdGgiLCJtYXAiLCJkZWJ1ZyIsIkpTT04iLCJzdHJpbmdpZnkiLCJzaG91bGRVbmluc3RhbGxTZXJ2ZXJQYWNrYWdlcyIsInNvbWUiLCJldmVyeSIsInNob3VsZEluc3RhbGxTZXJ2ZXJQYWNrYWdlcyIsIk9MREVSX1ZFUlNJT05fSU5TVEFMTEVEIiwiaW5jbHVkZXMiLCJpbmZvIiwic2lsZW50VW5pbnN0YWxsUGtnIiwicGtnSWQiLCJ1bmluc3RhbGxBcGsiLCJlcnIiLCJtZXNzYWdlIiwiaW5zdGFsbFBrZyIsInBrZ1BhdGgiLCJpbnN0YWxsIiwibm9JbmNyZW1lbnRhbCIsInJlcGxhY2UiLCJ0aW1lb3V0Q2FwTmFtZSIsInJpbXJhZiIsInZlcmlmeVNlcnZpY2VzQXZhaWxhYmlsaXR5IiwiaXNQbVNlcnZpY2VBdmFpbGFibGUiLCJwbU91dHB1dCIsInBtRXJyb3IiLCJ3YWl0Rm9yQ29uZGl0aW9uIiwic2hlbGwiLCJlIiwid2FpdE1zIiwiaW50ZXJ2YWxNcyIsImVycm9yIiwibGluZSIsInNwbGl0Iiwic3RhcnRTZXNzaW9uIiwiY2FwcyIsImNsZWFudXBBdXRvbWF0aW9uTGVmdG92ZXJzIiwic2tpcFNlcnZlckluc3RhbGxhdGlvbiIsInNlcnZlclZlcnNpb24iLCJ1aWF1dG9tYXRvcjJTZXJ2ZXJMYXVuY2hUaW1lb3V0IiwidGltZXIiLCJ0aW1pbmciLCJUaW1lciIsInN0YXJ0IiwicmV0cmllcyIsIm1heFJldHJpZXMiLCJkZWxheUJldHdlZW5SZXRyaWVzIiwic3RhcnRJbnN0cnVtZW50YXRpb25Qcm9jZXNzIiwiZXJyb3JBbmRUaHJvdyIsImRlbGF5IiwiZ2V0RHVyYXRpb24iLCJhc01pbGxpU2Vjb25kcyIsInRvRml4ZWQiLCJjYXBhYmlsaXRpZXMiLCJmaXJzdE1hdGNoIiwiYWx3YXlzTWF0Y2giLCJjbWQiLCJkaXNhYmxlV2luZG93QW5pbWF0aW9uIiwicHVzaCIsIl8iLCJpc0Jvb2xlYW4iLCJpbnN0cnVtZW50YXRpb25Qcm9jZXNzIiwiY3JlYXRlU3ViUHJvY2VzcyIsIm9uIiwic3Rkb3V0Iiwic3RkZXJyIiwib3V0cHV0IiwidHJpbSIsImNvZGUiLCJkZWxldGVTZXNzaW9uIiwic3RyaWN0Q2xlYW51cCIsImF4aW9zVGltZW91dCIsIndhaXRTdG9wIiwiYXhpb3MiLCJ2YWx1ZSIsImRhdGEiLCJhY3RpdmVTZXNzaW9uSWRzIiwiaWQiLCJmaWx0ZXIiLCJCb29sZWFuIiwibGVuZ3RoIiwicGx1cmFsaXplIiwiZGVsZXRlIiwiZm9yY2VTdG9wIiwiaWdub3JlIiwia2lsbFByb2Nlc3Nlc0J5TmFtZSIsIl9kZWZhdWx0IiwiZGVmYXVsdCJdLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi91aWF1dG9tYXRvcjIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IEpXUHJveHksIGVycm9ycyB9IGZyb20gJ2FwcGl1bS9kcml2ZXInO1xuaW1wb3J0IHsgd2FpdEZvckNvbmRpdGlvbiB9IGZyb20gJ2FzeW5jYm94JztcbmltcG9ydCB7XG4gIFNFUlZFUl9BUEtfUEFUSCBhcyBhcGtQYXRoLFxuICBURVNUX0FQS19QQVRIIGFzIHRlc3RBcGtQYXRoLFxuICB2ZXJzaW9uIGFzIHNlcnZlclZlcnNpb25cbn0gZnJvbSAnYXBwaXVtLXVpYXV0b21hdG9yMi1zZXJ2ZXInO1xuaW1wb3J0IHtcbiAgdXRpbCwgbG9nZ2VyLCB0ZW1wRGlyLCBmcywgdGltaW5nXG59IGZyb20gJ2FwcGl1bS9zdXBwb3J0JztcbmltcG9ydCBCIGZyb20gJ2JsdWViaXJkJztcbmltcG9ydCBoZWxwZXJzIGZyb20gJy4vaGVscGVycyc7XG5pbXBvcnQgYXhpb3MgZnJvbSAnYXhpb3MnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5cbmNvbnN0IFJFUURfUEFSQU1TID0gWydhZGInLCAndG1wRGlyJywgJ2hvc3QnLCAnc3lzdGVtUG9ydCcsICdkZXZpY2VQb3J0JywgJ2Rpc2FibGVXaW5kb3dBbmltYXRpb24nXTtcbmNvbnN0IFNFUlZFUl9MQVVOQ0hfVElNRU9VVCA9IDMwMDAwO1xuY29uc3QgU0VSVkVSX0lOU1RBTExfUkVUUklFUyA9IDIwO1xuY29uc3QgU0VSVklDRVNfTEFVTkNIX1RJTUVPVVQgPSAzMDAwMDtcbmNvbnN0IFNFUlZFUl9QQUNLQUdFX0lEID0gJ2lvLmFwcGl1bS51aWF1dG9tYXRvcjIuc2VydmVyJztcbmNvbnN0IFNFUlZFUl9URVNUX1BBQ0tBR0VfSUQgPSBgJHtTRVJWRVJfUEFDS0FHRV9JRH0udGVzdGA7XG5jb25zdCBJTlNUUlVNRU5UQVRJT05fVEFSR0VUID0gYCR7U0VSVkVSX1RFU1RfUEFDS0FHRV9JRH0vYW5kcm9pZHgudGVzdC5ydW5uZXIuQW5kcm9pZEpVbml0UnVubmVyYDtcbmNvbnN0IGluc3RydW1lbnRhdGlvbkxvZ2dlciA9IGxvZ2dlci5nZXRMb2dnZXIoJ0luc3RydW1lbnRhdGlvbicpO1xuXG5jbGFzcyBVSUEyUHJveHkgZXh0ZW5kcyBKV1Byb3h5IHtcbiAgYXN5bmMgcHJveHlDb21tYW5kICh1cmwsIG1ldGhvZCwgYm9keSA9IG51bGwpIHtcbiAgICBpZiAodGhpcy5kaWRJbnN0cnVtZW50YXRpb25FeGl0KSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRDb250ZXh0RXJyb3IoXG4gICAgICAgIGAnJHttZXRob2R9ICR7dXJsfScgY2Fubm90IGJlIHByb3hpZWQgdG8gVWlBdXRvbWF0b3IyIHNlcnZlciBiZWNhdXNlIGAgK1xuICAgICAgICAndGhlIGluc3RydW1lbnRhdGlvbiBwcm9jZXNzIGlzIG5vdCBydW5uaW5nIChwcm9iYWJseSBjcmFzaGVkKS4gJyArXG4gICAgICAgICdDaGVjayB0aGUgc2VydmVyIGxvZyBhbmQvb3IgdGhlIGxvZ2NhdCBvdXRwdXQgZm9yIG1vcmUgZGV0YWlscycpO1xuICAgIH1cbiAgICByZXR1cm4gYXdhaXQgc3VwZXIucHJveHlDb21tYW5kKHVybCwgbWV0aG9kLCBib2R5KTtcbiAgfVxufVxuXG5jbGFzcyBVaUF1dG9tYXRvcjJTZXJ2ZXIge1xuICBjb25zdHJ1Y3RvciAobG9nLCBvcHRzID0ge30pIHtcbiAgICBmb3IgKGxldCByZXEgb2YgUkVRRF9QQVJBTVMpIHtcbiAgICAgIGlmICghb3B0cyB8fCAhdXRpbC5oYXNWYWx1ZShvcHRzW3JlcV0pKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgT3B0aW9uICcke3JlcX0nIGlzIHJlcXVpcmVkIWApO1xuICAgICAgfVxuICAgICAgdGhpc1tyZXFdID0gb3B0c1tyZXFdO1xuICAgIH1cbiAgICB0aGlzLmxvZyA9IGxvZztcbiAgICB0aGlzLmRpc2FibGVTdXBwcmVzc0FjY2Vzc2liaWxpdHlTZXJ2aWNlID0gb3B0cy5kaXNhYmxlU3VwcHJlc3NBY2Nlc3NpYmlsaXR5U2VydmljZTtcbiAgICBjb25zdCBwcm94eU9wdHMgPSB7XG4gICAgICBsb2csXG4gICAgICBzZXJ2ZXI6IHRoaXMuaG9zdCxcbiAgICAgIHBvcnQ6IHRoaXMuc3lzdGVtUG9ydCxcbiAgICAgIGtlZXBBbGl2ZTogdHJ1ZSxcbiAgICB9O1xuICAgIGlmIChvcHRzLnJlYWRUaW1lb3V0ICYmIG9wdHMucmVhZFRpbWVvdXQgPiAwKSB7XG4gICAgICBwcm94eU9wdHMudGltZW91dCA9IG9wdHMucmVhZFRpbWVvdXQ7XG4gICAgfVxuICAgIHRoaXMuandwcm94eSA9IG5ldyBVSUEyUHJveHkocHJveHlPcHRzKTtcbiAgICB0aGlzLnByb3h5UmVxUmVzID0gdGhpcy5qd3Byb3h5LnByb3h5UmVxUmVzLmJpbmQodGhpcy5qd3Byb3h5KTtcbiAgICB0aGlzLnByb3h5Q29tbWFuZCA9IHRoaXMuandwcm94eS5jb21tYW5kLmJpbmQodGhpcy5qd3Byb3h5KTtcbiAgICB0aGlzLmp3cHJveHkuZGlkSW5zdHJ1bWVudGF0aW9uRXhpdCA9IGZhbHNlO1xuICB9XG5cbiAgYXN5bmMgcHJlcGFyZVNlcnZlclBhY2thZ2UoYXBwUGF0aCwgYXBwSWQsIHRtcFJvb3QpIHtcbiAgICBjb25zdCByZXN1bHRJbmZvID0ge1xuICAgICAgd2FzU2lnbmVkOiBmYWxzZSxcbiAgICAgIGluc3RhbGxTdGF0ZTogdGhpcy5hZGIuQVBQX0lOU1RBTExfU1RBVEUuTk9UX0lOU1RBTExFRCxcbiAgICAgIGFwcFBhdGgsXG4gICAgICBhcHBJZCxcbiAgICB9O1xuXG4gICAgaWYgKGF3YWl0IHRoaXMuYWRiLmNoZWNrQXBrQ2VydChyZXN1bHRJbmZvLmFwcFBhdGgsIGFwcElkKSkge1xuICAgICAgcmVzdWx0SW5mby53YXNTaWduZWQgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIWF3YWl0IGhlbHBlcnMuaXNXcml0ZWFibGUoYXBwUGF0aCkpIHtcbiAgICAgICAgdGhpcy5sb2cud2FybihcbiAgICAgICAgICBgU2VydmVyIHBhY2thZ2UgYXQgJyR7YXBwUGF0aH0nIGlzIG5vdCB3cml0ZWFibGUuIGAgK1xuICAgICAgICAgIGBXaWxsIGNvcHkgaXQgaW50byB0aGUgdGVtcG9yYXJ5IGxvY2F0aW9uIGF0ICcke3RtcFJvb3R9JyBhcyBhIHdvcmthcm91bmQuIGAgK1xuICAgICAgICAgIGBDb25zaWRlciBtYWtpbmcgdGhpcyBmaWxlIHdyaXRlYWJsZSBtYW51YWxseSBpbiBvcmRlciB0byBpbXByb3ZlIHRoZSBwZXJmb3JtYW5jZSBvZiBzZXNzaW9uIHN0YXJ0dXAuYFxuICAgICAgICApO1xuICAgICAgICBjb25zdCBkc3RQYXRoID0gcGF0aC5yZXNvbHZlKHRtcFJvb3QsIHBhdGguYmFzZW5hbWUoYXBwUGF0aCkpO1xuICAgICAgICBhd2FpdCBmcy5jb3B5RmlsZShhcHBQYXRoLCBkc3RQYXRoKTtcbiAgICAgICAgcmVzdWx0SW5mby5hcHBQYXRoID0gZHN0UGF0aDtcbiAgICAgIH1cbiAgICAgIGF3YWl0IGhlbHBlcnMuc2lnbkFwcCh0aGlzLmFkYiwgcmVzdWx0SW5mby5hcHBQYXRoKTtcbiAgICB9XG5cbiAgICBpZiAoYXBwSWQgPT09IFNFUlZFUl9URVNUX1BBQ0tBR0VfSUQgJiYgYXdhaXQgdGhpcy5hZGIuaXNBcHBJbnN0YWxsZWQoYXBwSWQpKSB7XG4gICAgICAvLyBUaGVyZSBpcyBubyBwb2ludCBpbiBnZXR0aW5nIHRoZSBzdGF0ZSBmb3IgdGhlIHRlc3Qgc2VydmVyLFxuICAgICAgLy8gc2luY2UgaXQgZG9lcyBub3QgY29udGFpbiBhbnkgdmVyc2lvbiBpbmZvXG4gICAgICByZXN1bHRJbmZvLmluc3RhbGxTdGF0ZSA9IHRoaXMuYWRiLkFQUF9JTlNUQUxMX1NUQVRFLlNBTUVfVkVSU0lPTl9JTlNUQUxMRUQ7XG4gICAgfSBlbHNlIGlmIChhcHBJZCA9PT0gU0VSVkVSX1BBQ0tBR0VfSUQpIHtcbiAgICAgIHJlc3VsdEluZm8uaW5zdGFsbFN0YXRlID0gYXdhaXQgdGhpcy5hZGIuZ2V0QXBwbGljYXRpb25JbnN0YWxsU3RhdGUocmVzdWx0SW5mby5hcHBQYXRoLCBhcHBJZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdEluZm87XG4gIH1cblxuICAvKipcbiAgICogSW5zdGFsbHMgdGhlIGFwa3Mgb24gdG8gdGhlIGRldmljZSBvciBlbXVsYXRvci5cbiAgICpcbiAgICogQHBhcmFtIHtudW1iZXJ9IGluc3RhbGxUaW1lb3V0IC0gSW5zdGFsbGF0aW9uIHRpbWVvdXRcbiAgICovXG4gIGFzeW5jIGluc3RhbGxTZXJ2ZXJBcGsgKGluc3RhbGxUaW1lb3V0ID0gU0VSVkVSX0lOU1RBTExfUkVUUklFUyAqIDEwMDApIHtcbiAgICBjb25zdCB0bXBSb290ID0gYXdhaXQgdGVtcERpci5vcGVuRGlyKCk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHBhY2thZ2VzSW5mbyA9IGF3YWl0IEIuYWxsKFxuICAgICAgICBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYXBwUGF0aDogYXBrUGF0aCxcbiAgICAgICAgICAgIGFwcElkOiBTRVJWRVJfUEFDS0FHRV9JRCxcbiAgICAgICAgICB9LCB7XG4gICAgICAgICAgICBhcHBQYXRoOiB0ZXN0QXBrUGF0aCxcbiAgICAgICAgICAgIGFwcElkOiBTRVJWRVJfVEVTVF9QQUNLQUdFX0lELFxuICAgICAgICAgIH0sXG4gICAgICAgIF0ubWFwKCh7YXBwUGF0aCwgYXBwSWR9KSA9PiB0aGlzLnByZXBhcmVTZXJ2ZXJQYWNrYWdlKGFwcFBhdGgsIGFwcElkLCB0bXBSb290KSlcbiAgICAgICk7XG5cbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXJ2ZXIgcGFja2FnZXMgc3RhdHVzOiAke0pTT04uc3RyaW5naWZ5KHBhY2thZ2VzSW5mbyl9YCk7XG4gICAgICAvLyBXZSB3YW50IHRvIGVuZm9yY2UgdW5pbnN0YWxsIGluIGNhc2UgdGhlIGN1cnJlbnQgc2VydmVyIHBhY2thZ2UgaGFzIG5vdCBiZWVuIHNpZ25lZCBwcm9wZXJseVxuICAgICAgLy8gb3IgaWYgYW55IG9mIHNlcnZlciBwYWNrYWdlcyBpcyBub3QgaW5zdGFsbGVkLCB3aGlsZSB0aGUgb3RoZXIgZG9lc1xuICAgICAgY29uc3Qgc2hvdWxkVW5pbnN0YWxsU2VydmVyUGFja2FnZXMgPSBwYWNrYWdlc0luZm8uc29tZSgoe3dhc1NpZ25lZH0pID0+ICF3YXNTaWduZWQpXG4gICAgICAgIHx8IChwYWNrYWdlc0luZm8uc29tZSgoe2luc3RhbGxTdGF0ZX0pID0+IGluc3RhbGxTdGF0ZSA9PT0gdGhpcy5hZGIuQVBQX0lOU1RBTExfU1RBVEUuTk9UX0lOU1RBTExFRClcbiAgICAgICAgICAgICYmICFwYWNrYWdlc0luZm8uZXZlcnkoKHtpbnN0YWxsU3RhdGV9KSA9PiBpbnN0YWxsU3RhdGUgPT09IHRoaXMuYWRiLkFQUF9JTlNUQUxMX1NUQVRFLk5PVF9JTlNUQUxMRUQpKTtcbiAgICAgIC8vIEluc3RhbGwgbXVzdCBhbHdheXMgZm9sbG93IHVuaW5zdGFsbC4gQWxzbywgcGVyZm9ybSB0aGUgaW5zdGFsbCBpZlxuICAgICAgLy8gYW55IG9mIHNlcnZlciBwYWNrYWdlcyBpcyBub3QgaW5zdGFsbGVkIG9yIGlzIG91dGRhdGVkXG4gICAgICBjb25zdCBzaG91bGRJbnN0YWxsU2VydmVyUGFja2FnZXMgPSBzaG91bGRVbmluc3RhbGxTZXJ2ZXJQYWNrYWdlcyB8fCBwYWNrYWdlc0luZm8uc29tZSgoe2luc3RhbGxTdGF0ZX0pID0+IFtcbiAgICAgICAgdGhpcy5hZGIuQVBQX0lOU1RBTExfU1RBVEUuTk9UX0lOU1RBTExFRCxcbiAgICAgICAgdGhpcy5hZGIuQVBQX0lOU1RBTExfU1RBVEUuT0xERVJfVkVSU0lPTl9JTlNUQUxMRUQsXG4gICAgICBdLmluY2x1ZGVzKGluc3RhbGxTdGF0ZSkpO1xuICAgICAgdGhpcy5sb2cuaW5mbyhgU2VydmVyIHBhY2thZ2VzIGFyZSAke3Nob3VsZEluc3RhbGxTZXJ2ZXJQYWNrYWdlcyA/ICcnIDogJ25vdCAnfWdvaW5nIHRvIGJlIChyZSlpbnN0YWxsZWRgKTtcbiAgICAgIGlmIChzaG91bGRJbnN0YWxsU2VydmVyUGFja2FnZXMgJiYgc2hvdWxkVW5pbnN0YWxsU2VydmVyUGFja2FnZXMpIHtcbiAgICAgICAgdGhpcy5sb2cuaW5mbygnRnVsbCBwYWNrYWdlcyByZWluc3RhbGwgaXMgZ29pbmcgdG8gYmUgcGVyZm9ybWVkJyk7XG4gICAgICB9XG4gICAgICBpZiAoc2hvdWxkVW5pbnN0YWxsU2VydmVyUGFja2FnZXMpIHtcbiAgICAgICAgY29uc3Qgc2lsZW50VW5pbnN0YWxsUGtnID0gYXN5bmMgKHBrZ0lkKSA9PiB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuYWRiLnVuaW5zdGFsbEFwayhwa2dJZCk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICB0aGlzLmxvZy5pbmZvKGBDYW5ub3QgdW5pbnN0YWxsICcke3BrZ0lkfSc6ICR7ZXJyLm1lc3NhZ2V9YCk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBhd2FpdCBCLmFsbChwYWNrYWdlc0luZm8ubWFwKCh7YXBwSWR9KSA9PiBzaWxlbnRVbmluc3RhbGxQa2coYXBwSWQpKSk7XG4gICAgICB9XG4gICAgICBpZiAoc2hvdWxkSW5zdGFsbFNlcnZlclBhY2thZ2VzKSB7XG4gICAgICAgIGNvbnN0IGluc3RhbGxQa2cgPSBhc3luYyAocGtnUGF0aCkgPT4ge1xuICAgICAgICAgIGF3YWl0IHRoaXMuYWRiLmluc3RhbGwocGtnUGF0aCwge1xuICAgICAgICAgICAgbm9JbmNyZW1lbnRhbDogdHJ1ZSxcbiAgICAgICAgICAgIHJlcGxhY2U6IHRydWUsXG4gICAgICAgICAgICB0aW1lb3V0OiBpbnN0YWxsVGltZW91dCxcbiAgICAgICAgICAgIHRpbWVvdXRDYXBOYW1lOiAndWlhdXRvbWF0b3IyU2VydmVySW5zdGFsbFRpbWVvdXQnXG4gICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIGF3YWl0IEIuYWxsKHBhY2thZ2VzSW5mby5tYXAoKHthcHBQYXRofSkgPT4gaW5zdGFsbFBrZyhhcHBQYXRoKSkpO1xuICAgICAgfVxuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCBmcy5yaW1yYWYodG1wUm9vdCk7XG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy52ZXJpZnlTZXJ2aWNlc0F2YWlsYWJpbGl0eSgpO1xuICB9XG5cbiAgYXN5bmMgdmVyaWZ5U2VydmljZXNBdmFpbGFiaWxpdHkgKCkge1xuICAgIHRoaXMubG9nLmRlYnVnKGBXYWl0aW5nIHVwIHRvICR7U0VSVklDRVNfTEFVTkNIX1RJTUVPVVR9bXMgZm9yIHNlcnZpY2VzIHRvIGJlIGF2YWlsYWJsZWApO1xuICAgIGxldCBpc1BtU2VydmljZUF2YWlsYWJsZSA9IGZhbHNlO1xuICAgIGxldCBwbU91dHB1dCA9ICcnO1xuICAgIGxldCBwbUVycm9yID0gbnVsbDtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgd2FpdEZvckNvbmRpdGlvbihhc3luYyAoKSA9PiB7XG4gICAgICAgIGlmICghaXNQbVNlcnZpY2VBdmFpbGFibGUpIHtcbiAgICAgICAgICBwbUVycm9yID0gbnVsbDtcbiAgICAgICAgICBwbU91dHB1dCA9ICcnO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBwbU91dHB1dCA9IGF3YWl0IHRoaXMuYWRiLnNoZWxsKFsncG0nLCAnbGlzdCcsICdpbnN0cnVtZW50YXRpb24nXSk7XG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcG1FcnJvciA9IGU7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChwbU91dHB1dC5pbmNsdWRlcygnQ291bGQgbm90IGFjY2VzcyB0aGUgUGFja2FnZSBNYW5hZ2VyJykpIHtcbiAgICAgICAgICAgIHBtRXJyb3IgPSBuZXcgRXJyb3IoYFByb2JsZW0gcnVubmluZyBQYWNrYWdlIE1hbmFnZXI6ICR7cG1PdXRwdXR9YCk7XG4gICAgICAgICAgICBwbU91dHB1dCA9ICcnOyAvLyByZW1vdmUgb3V0cHV0LCBzbyBpdCBpcyBub3QgcHJpbnRlZCBiZWxvd1xuICAgICAgICAgIH0gZWxzZSBpZiAocG1PdXRwdXQuaW5jbHVkZXMoSU5TVFJVTUVOVEFUSU9OX1RBUkdFVCkpIHtcbiAgICAgICAgICAgIHBtT3V0cHV0ID0gJyc7IC8vIHJlbW92ZSBvdXRwdXQsIHNvIGl0IGlzIG5vdCBwcmludGVkIGJlbG93XG4gICAgICAgICAgICB0aGlzLmxvZy5kZWJ1ZyhgSW5zdHJ1bWVudGF0aW9uIHRhcmdldCAnJHtJTlNUUlVNRU5UQVRJT05fVEFSR0VUfScgaXMgYXZhaWxhYmxlYCk7XG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVxdWlyZS1hdG9taWMtdXBkYXRlc1xuICAgICAgICAgICAgaXNQbVNlcnZpY2VBdmFpbGFibGUgPSB0cnVlO1xuICAgICAgICAgIH0gZWxzZSBpZiAoIXBtRXJyb3IpIHtcbiAgICAgICAgICAgIHBtRXJyb3IgPSBuZXcgRXJyb3IoJ1RoZSBpbnN0cnVtZW50YXRpb24gdGFyZ2V0IGlzIG5vdCBsaXN0ZWQgYnkgUGFja2FnZSBNYW5hZ2VyJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpc1BtU2VydmljZUF2YWlsYWJsZTtcbiAgICAgIH0sIHtcbiAgICAgICAgd2FpdE1zOiBTRVJWSUNFU19MQVVOQ0hfVElNRU9VVCxcbiAgICAgICAgaW50ZXJ2YWxNczogMTAwMCxcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgdGhpcy5sb2cuZXJyb3IoYFVuYWJsZSB0byBmaW5kIGluc3RydW1lbnRhdGlvbiB0YXJnZXQgJyR7SU5TVFJVTUVOVEFUSU9OX1RBUkdFVH0nOiAkeyhwbUVycm9yIHx8IHt9KS5tZXNzYWdlfWApO1xuICAgICAgaWYgKHBtT3V0cHV0KSB7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKCdBdmFpbGFibGUgdGFyZ2V0czonKTtcbiAgICAgICAgZm9yIChjb25zdCBsaW5lIG9mIHBtT3V0cHV0LnNwbGl0KCdcXG4nKSkge1xuICAgICAgICAgIHRoaXMubG9nLmRlYnVnKGAgICAgJHtsaW5lLnJlcGxhY2UoJ2luc3RydW1lbnRhdGlvbjonLCAnJyl9YCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBhc3luYyBzdGFydFNlc3Npb24gKGNhcHMpIHtcbiAgICBhd2FpdCB0aGlzLmNsZWFudXBBdXRvbWF0aW9uTGVmdG92ZXJzKCk7XG4gICAgaWYgKGNhcHMuc2tpcFNlcnZlckluc3RhbGxhdGlvbikge1xuICAgICAgdGhpcy5sb2cuaW5mbyhgJ3NraXBTZXJ2ZXJJbnN0YWxsYXRpb24nIGlzIHNldC4gQXR0ZW1wdGluZyB0byB1c2UgVUlBdXRvbWF0b3IyIHNlcnZlciBmcm9tIHRoZSBkZXZpY2VgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5sb2cuaW5mbyhgU3RhcnRpbmcgVUlBdXRvbWF0b3IyIHNlcnZlciAke3NlcnZlclZlcnNpb259YCk7XG4gICAgICB0aGlzLmxvZy5pbmZvKGBVc2luZyBVSUF1dG9tYXRvcjIgc2VydmVyIGZyb20gJyR7YXBrUGF0aH0nIGFuZCB0ZXN0IGZyb20gJyR7dGVzdEFwa1BhdGh9J2ApO1xuICAgIH1cblxuICAgIGNvbnN0IHRpbWVvdXQgPSBjYXBzLnVpYXV0b21hdG9yMlNlcnZlckxhdW5jaFRpbWVvdXQgfHwgU0VSVkVSX0xBVU5DSF9USU1FT1VUO1xuICAgIGNvbnN0IHRpbWVyID0gbmV3IHRpbWluZy5UaW1lcigpLnN0YXJ0KCk7XG4gICAgbGV0IHJldHJpZXMgPSAwO1xuICAgIGNvbnN0IG1heFJldHJpZXMgPSAyO1xuICAgIGNvbnN0IGRlbGF5QmV0d2VlblJldHJpZXMgPSAzMDAwO1xuICAgIHdoaWxlIChyZXRyaWVzIDwgbWF4UmV0cmllcykge1xuICAgICAgdGhpcy5sb2cuaW5mbyhgV2FpdGluZyB1cCB0byAke3RpbWVvdXR9bXMgZm9yIFVpQXV0b21hdG9yMiB0byBiZSBvbmxpbmUuLi5gKTtcbiAgICAgIHRoaXMuandwcm94eS5kaWRJbnN0cnVtZW50YXRpb25FeGl0ID0gZmFsc2U7XG4gICAgICBhd2FpdCB0aGlzLnN0YXJ0SW5zdHJ1bWVudGF0aW9uUHJvY2VzcygpO1xuICAgICAgaWYgKCF0aGlzLmp3cHJveHkuZGlkSW5zdHJ1bWVudGF0aW9uRXhpdCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHdhaXRGb3JDb25kaXRpb24oYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgYXdhaXQgdGhpcy5qd3Byb3h5LmNvbW1hbmQoJy9zdGF0dXMnLCAnR0VUJyk7XG4gICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgIC8vIHNob3J0IGNpcmN1aXQgdG8gcmV0cnkgb3IgZmFpbCBmYXN0XG4gICAgICAgICAgICAgIHJldHVybiB0aGlzLmp3cHJveHkuZGlkSW5zdHJ1bWVudGF0aW9uRXhpdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LCB7XG4gICAgICAgICAgICB3YWl0TXM6IHRpbWVvdXQsXG4gICAgICAgICAgICBpbnRlcnZhbE1zOiAxMDAwLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICB0aGlzLmxvZy5lcnJvckFuZFRocm93KGBUaGUgaW5zdHJ1bWVudGF0aW9uIHByb2Nlc3MgY2Fubm90IGJlIGluaXRpYWxpemVkIHdpdGhpbiAke3RpbWVvdXR9bXMgdGltZW91dC4gYFxuICAgICAgICAgICAgKyAnTWFrZSBzdXJlIHRoZSBhcHBsaWNhdGlvbiB1bmRlciB0ZXN0IGRvZXMgbm90IGNyYXNoIGFuZCBpbnZlc3RpZ2F0ZSB0aGUgbG9nY2F0IG91dHB1dC4gJ1xuICAgICAgICAgICAgKyBgWW91IGNvdWxkIGFsc28gdHJ5IHRvIGluY3JlYXNlIHRoZSB2YWx1ZSBvZiAndWlhdXRvbWF0b3IyU2VydmVyTGF1bmNoVGltZW91dCcgY2FwYWJpbGl0eWApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoIXRoaXMuandwcm94eS5kaWRJbnN0cnVtZW50YXRpb25FeGl0KSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICByZXRyaWVzKys7XG4gICAgICBpZiAocmV0cmllcyA+PSBtYXhSZXRyaWVzKSB7XG4gICAgICAgIHRoaXMubG9nLmVycm9yQW5kVGhyb3coJ1RoZSBpbnN0cnVtZW50YXRpb24gcHJvY2VzcyBjYW5ub3QgYmUgaW5pdGlhbGl6ZWQuICdcbiAgICAgICAgICArICdNYWtlIHN1cmUgdGhlIGFwcGxpY2F0aW9uIHVuZGVyIHRlc3QgZG9lcyBub3QgY3Jhc2ggYW5kIGludmVzdGlnYXRlIHRoZSBsb2djYXQgb3V0cHV0LicpO1xuICAgICAgfVxuICAgICAgdGhpcy5sb2cud2FybihgVGhlIGluc3RydW1lbnRhdGlvbiBwcm9jZXNzIGhhcyBiZWVuIHVuZXhwZWN0ZWRseSB0ZXJtaW5hdGVkLiBgXG4gICAgICAgICsgYFJldHJ5aW5nIFVpQXV0b21hdG9yMiBzdGFydHVwICgjJHtyZXRyaWVzfSBvZiAke21heFJldHJpZXMgLSAxfSlgKTtcbiAgICAgIGF3YWl0IHRoaXMuY2xlYW51cEF1dG9tYXRpb25MZWZ0b3ZlcnModHJ1ZSk7XG4gICAgICBhd2FpdCBCLmRlbGF5KGRlbGF5QmV0d2VlblJldHJpZXMpO1xuICAgIH1cblxuICAgIHRoaXMubG9nLmRlYnVnKGBUaGUgaW5pdGlhbGl6YXRpb24gb2YgdGhlIGluc3RydW1lbnRhdGlvbiBwcm9jZXNzIHRvb2sgYFxuICAgICAgKyBgJHt0aW1lci5nZXREdXJhdGlvbigpLmFzTWlsbGlTZWNvbmRzLnRvRml4ZWQoMCl9bXNgKTtcbiAgICBhd2FpdCB0aGlzLmp3cHJveHkuY29tbWFuZCgnL3Nlc3Npb24nLCAnUE9TVCcsIHtcbiAgICAgIGNhcGFiaWxpdGllczoge1xuICAgICAgICBmaXJzdE1hdGNoOiBbY2Fwc10sXG4gICAgICAgIGFsd2F5c01hdGNoOiB7fSxcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIHN0YXJ0SW5zdHJ1bWVudGF0aW9uUHJvY2VzcyAoKSB7XG4gICAgY29uc3QgY21kID0gWydhbScsICdpbnN0cnVtZW50JywgJy13J107XG4gICAgaWYgKHRoaXMuZGlzYWJsZVdpbmRvd0FuaW1hdGlvbikge1xuICAgICAgY21kLnB1c2goJy0tbm8td2luZG93LWFuaW1hdGlvbicpO1xuICAgIH1cbiAgICBpZiAoXy5pc0Jvb2xlYW4odGhpcy5kaXNhYmxlU3VwcHJlc3NBY2Nlc3NpYmlsaXR5U2VydmljZSkpIHtcbiAgICAgIGNtZC5wdXNoKCctZScsICdESVNBQkxFX1NVUFBSRVNTX0FDQ0VTU0lCSUxJVFlfU0VSVklDRVMnLCB0aGlzLmRpc2FibGVTdXBwcmVzc0FjY2Vzc2liaWxpdHlTZXJ2aWNlKTtcbiAgICB9XG4gICAgLy8gRGlzYWJsZSBHb29nbGUgYW5hbHl0aWNzIHRvIHByZXZlbnQgcG9zc2libGUgZmF0YWwgZXhjZXB0aW9uXG4gICAgY21kLnB1c2goJy1lJywgJ2Rpc2FibGVBbmFseXRpY3MnLCB0cnVlKTtcbiAgICBjbWQucHVzaChJTlNUUlVNRU5UQVRJT05fVEFSR0VUKTtcbiAgICBjb25zdCBpbnN0cnVtZW50YXRpb25Qcm9jZXNzID0gdGhpcy5hZGIuY3JlYXRlU3ViUHJvY2VzcyhbJ3NoZWxsJywgLi4uY21kXSk7XG4gICAgaW5zdHJ1bWVudGF0aW9uUHJvY2Vzcy5vbignb3V0cHV0JywgKHN0ZG91dCwgc3RkZXJyKSA9PiB7XG4gICAgICBjb25zdCBvdXRwdXQgPSBfLnRyaW0oc3Rkb3V0IHx8IHN0ZGVycik7XG4gICAgICBpZiAob3V0cHV0KSB7XG4gICAgICAgIGluc3RydW1lbnRhdGlvbkxvZ2dlci5kZWJ1ZyhvdXRwdXQpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGluc3RydW1lbnRhdGlvblByb2Nlc3Mub24oJ2V4aXQnLCAoY29kZSkgPT4ge1xuICAgICAgaW5zdHJ1bWVudGF0aW9uTG9nZ2VyLmRlYnVnKGBUaGUgcHJvY2VzcyBoYXMgZXhpdGVkIHdpdGggY29kZSAke2NvZGV9YCk7XG4gICAgICB0aGlzLmp3cHJveHkuZGlkSW5zdHJ1bWVudGF0aW9uRXhpdCA9IHRydWU7XG4gICAgfSk7XG4gICAgYXdhaXQgaW5zdHJ1bWVudGF0aW9uUHJvY2Vzcy5zdGFydCgwKTtcbiAgfVxuXG4gIGFzeW5jIGRlbGV0ZVNlc3Npb24gKCkge1xuICAgIHRoaXMubG9nLmRlYnVnKCdEZWxldGluZyBVaUF1dG9tYXRvcjIgc2VydmVyIHNlc3Npb24nKTtcbiAgICAvLyByZWx5IG9uIGp3cHJveHkncyBpbnRlbGxpZ2VuY2UgdG8ga25vdyB3aGF0IHdlJ3JlIHRhbGtpbmcgYWJvdXQgYW5kXG4gICAgLy8gZGVsZXRlIHRoZSBjdXJyZW50IHNlc3Npb25cbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5qd3Byb3h5LmNvbW1hbmQoJy8nLCAnREVMRVRFJyk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aGlzLmxvZy53YXJuKGBEaWQgbm90IGdldCBjb25maXJtYXRpb24gVWlBdXRvbWF0b3IyIGRlbGV0ZVNlc3Npb24gd29ya2VkOyBgICtcbiAgICAgICAgICBgRXJyb3Igd2FzOiAke2Vycn1gKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBjbGVhbnVwQXV0b21hdGlvbkxlZnRvdmVycyAoc3RyaWN0Q2xlYW51cCA9IGZhbHNlKSB7XG4gICAgdGhpcy5sb2cuZGVidWcoYFBlcmZvcm1pbmcgJHtzdHJpY3RDbGVhbnVwID8gJ3N0cmljdCcgOiAnc2hhbGxvdyd9IGNsZWFudXAgb2YgYXV0b21hdGlvbiBsZWZ0b3ZlcnNgKTtcblxuICAgIGNvbnN0IGF4aW9zVGltZW91dCA9IDUwMDtcblxuICAgIGNvbnN0IHdhaXRTdG9wID0gYXN5bmMgKCkgPT4ge1xuICAgICAgLy8gV2FpdCBmb3IgdGhlIHByb2Nlc3Mgc3RvcCBieSBzZW5kaW5nIGEgc3RhdHVzIHJlcXVlc3QgdG8gdGhlIHBvcnQuXG4gICAgICAvLyBXZSBvYnNlcnZlZCB0aGUgcHJvY2VzcyBzdG9wIGNvdWxkIGJlIGRlbGF5ZWQsIHRodXMgY2F1c2luZyB1bmV4cGVjdGVkIGNyYXNoZXNcbiAgICAgIC8vIGluIHRoZSBtaWRkbGUgb2YgdGhlIHNlc3Npb24gcHJlcGFyYXRpb24gcHJvY2Vzcy4gSXQgY2F1c2VkIGFuIGludmFsaWQgc2Vzc2lvbiBlcnJvciByZXNwb25zZVxuICAgICAgLy8gYnkgdGhlIHVpYTIgc2VydmVyLCBidXQgdGhhdCB3YXMgYmVjYXVzZSB0aGUgcHJvY2VzcyBzdG9wJ3MgZGVsYXkuXG4gICAgICBjb25zdCB0aW1lb3V0ID0gMzAwMDtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHdhaXRGb3JDb25kaXRpb24oYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBheGlvcyh7XG4gICAgICAgICAgICAgIHVybDogYGh0dHA6Ly8ke3RoaXMuaG9zdH06JHt0aGlzLnN5c3RlbVBvcnR9L3N0YXR1c2AsXG4gICAgICAgICAgICAgIHRpbWVvdXQ6IGF4aW9zVGltZW91dCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgd2FpdE1zOiB0aW1lb3V0LFxuICAgICAgICAgIGludGVydmFsTXM6IDEwMCxcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgdGhpcy5sb2cud2FybihgVGhlICR7U0VSVkVSX1RFU1RfUEFDS0FHRV9JRH0gcHJvY2VzcyBtaWdodCBmYWlsIHRvIHN0b3Agd2l0aGluICR7dGltZW91dH1tcyB0aW1lb3V0LmApO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB0cnkge1xuICAgICAgY29uc3Qge3ZhbHVlfSA9IChhd2FpdCBheGlvcyh7XG4gICAgICAgIHVybDogYGh0dHA6Ly8ke3RoaXMuaG9zdH06JHt0aGlzLnN5c3RlbVBvcnR9L3Nlc3Npb25zYCxcbiAgICAgICAgdGltZW91dDogYXhpb3NUaW1lb3V0LFxuICAgICAgfSkpLmRhdGE7XG4gICAgICBjb25zdCBhY3RpdmVTZXNzaW9uSWRzID0gdmFsdWUubWFwKCh7aWR9KSA9PiBpZCkuZmlsdGVyKEJvb2xlYW4pO1xuICAgICAgaWYgKGFjdGl2ZVNlc3Npb25JZHMubGVuZ3RoKSB7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKGBUaGUgZm9sbG93aW5nIG9ic29sZXRlIHNlc3Npb25zIGFyZSBzdGlsbCBydW5uaW5nOiAke0pTT04uc3RyaW5naWZ5KGFjdGl2ZVNlc3Npb25JZHMpfWApO1xuICAgICAgICB0aGlzLmxvZy5kZWJ1ZyhgQ2xlYW5pbmcgdXAgJHt1dGlsLnBsdXJhbGl6ZSgnb2Jzb2xldGUgc2Vzc2lvbicsIGFjdGl2ZVNlc3Npb25JZHMubGVuZ3RoLCB0cnVlKX1gKTtcbiAgICAgICAgYXdhaXQgQi5hbGwoYWN0aXZlU2Vzc2lvbklkc1xuICAgICAgICAgIC5tYXAoKGlkKSA9PiBheGlvcy5kZWxldGUoYGh0dHA6Ly8ke3RoaXMuaG9zdH06JHt0aGlzLnN5c3RlbVBvcnR9L3Nlc3Npb24vJHtpZH1gKSlcbiAgICAgICAgKTtcbiAgICAgICAgLy8gTGV0IGFsbCBzZXNzaW9ucyB0byBiZSBwcm9wZXJseSB0ZXJtaW5hdGVkIGJlZm9yZSBjb250aW51aW5nXG4gICAgICAgIGF3YWl0IEIuZGVsYXkoMTAwMCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmxvZy5kZWJ1ZygnTm8gb2Jzb2xldGUgc2Vzc2lvbnMgaGF2ZSBiZWVuIGRldGVjdGVkJyk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYE5vIG9ic29sZXRlIHNlc3Npb25zIGhhdmUgYmVlbiBkZXRlY3RlZCAoJHtlLm1lc3NhZ2V9KWApO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmFkYi5mb3JjZVN0b3AoU0VSVkVSX1RFU1RfUEFDS0FHRV9JRCk7XG4gICAgfSBjYXRjaCAoaWdub3JlKSB7fVxuICAgIGlmIChzdHJpY3RDbGVhbnVwKSB7XG4gICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vYXBwaXVtL2FwcGl1bS9pc3N1ZXMvMTA3NDlcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRoaXMuYWRiLmtpbGxQcm9jZXNzZXNCeU5hbWUoJ3VpYXV0b21hdG9yJyk7XG4gICAgICB9IGNhdGNoIChpZ25vcmUpIHt9XG4gICAgfVxuICAgIGF3YWl0IHdhaXRTdG9wKCk7XG4gIH1cbn1cblxuZXhwb3J0IHsgVWlBdXRvbWF0b3IyU2VydmVyLCBJTlNUUlVNRU5UQVRJT05fVEFSR0VULCBTRVJWRVJfUEFDS0FHRV9JRCwgU0VSVkVSX1RFU1RfUEFDS0FHRV9JRCB9O1xuZXhwb3J0IGRlZmF1bHQgVWlBdXRvbWF0b3IyU2VydmVyO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQUFBLElBQUFBLE9BQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLE9BQUEsR0FBQUQsT0FBQTtBQUNBLElBQUFFLFNBQUEsR0FBQUYsT0FBQTtBQUNBLElBQUFHLHlCQUFBLEdBQUFILE9BQUE7QUFLQSxJQUFBSSxRQUFBLEdBQUFKLE9BQUE7QUFHQSxJQUFBSyxTQUFBLEdBQUFOLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBTSxRQUFBLEdBQUFQLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBTyxNQUFBLEdBQUFSLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBUSxLQUFBLEdBQUFULHNCQUFBLENBQUFDLE9BQUE7QUFFQSxNQUFNUyxXQUFXLEdBQUcsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLHdCQUF3QixDQUFDO0FBQ25HLE1BQU1DLHFCQUFxQixHQUFHLEtBQUs7QUFDbkMsTUFBTUMsc0JBQXNCLEdBQUcsRUFBRTtBQUNqQyxNQUFNQyx1QkFBdUIsR0FBRyxLQUFLO0FBQ3JDLE1BQU1DLGlCQUFpQixHQUFBQyxPQUFBLENBQUFELGlCQUFBLEdBQUcsK0JBQStCO0FBQ3pELE1BQU1FLHNCQUFzQixHQUFBRCxPQUFBLENBQUFDLHNCQUFBLEdBQUksR0FBRUYsaUJBQWtCLE9BQU07QUFDMUQsTUFBTUcsc0JBQXNCLEdBQUFGLE9BQUEsQ0FBQUUsc0JBQUEsR0FBSSxHQUFFRCxzQkFBdUIsMENBQXlDO0FBQ2xHLE1BQU1FLHFCQUFxQixHQUFHQyxlQUFNLENBQUNDLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQztBQUVqRSxNQUFNQyxTQUFTLFNBQVNDLGVBQU8sQ0FBQztFQUM5QixNQUFNQyxZQUFZQSxDQUFFQyxHQUFHLEVBQUVDLE1BQU0s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
363
+ exports.default = UiAutomator2Server;
364
+ //# sourceMappingURL=uiautomator2.js.map