appium-uiautomator2-driver 2.29.11 → 2.31.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.
- package/CHANGELOG.md +14 -0
- package/build/index.d.ts +4 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +8 -15
- package/build/index.js.map +1 -0
- package/build/lib/commands/actions.d.ts +2 -0
- package/build/lib/commands/actions.d.ts.map +1 -0
- package/build/lib/commands/actions.js +67 -62
- package/build/lib/commands/actions.js.map +1 -1
- package/build/lib/commands/alert.d.ts +2 -0
- package/build/lib/commands/alert.d.ts.map +1 -0
- package/build/lib/commands/alert.js +28 -26
- package/build/lib/commands/alert.js.map +1 -1
- package/build/lib/commands/app-strings.d.ts +3 -0
- package/build/lib/commands/app-strings.d.ts.map +1 -0
- package/build/lib/commands/app-strings.js +86 -57
- package/build/lib/commands/app-strings.js.map +1 -1
- package/build/lib/commands/battery.d.ts +2 -0
- package/build/lib/commands/battery.d.ts.map +1 -0
- package/build/lib/commands/battery.js +26 -16
- package/build/lib/commands/battery.js.map +1 -1
- package/build/lib/commands/element.d.ts +2 -0
- package/build/lib/commands/element.d.ts.map +1 -0
- package/build/lib/commands/element.js +140 -159
- package/build/lib/commands/element.js.map +1 -1
- package/build/lib/commands/find.d.ts +2 -0
- package/build/lib/commands/find.d.ts.map +1 -0
- package/build/lib/commands/find.js +39 -25
- package/build/lib/commands/find.js.map +1 -1
- package/build/lib/commands/general.d.ts +4 -0
- package/build/lib/commands/general.d.ts.map +1 -0
- package/build/lib/commands/general.js +209 -215
- package/build/lib/commands/general.js.map +1 -1
- package/build/lib/commands/gestures.d.ts +2 -0
- package/build/lib/commands/gestures.d.ts.map +1 -0
- package/build/lib/commands/gestures.js +206 -193
- package/build/lib/commands/gestures.js.map +1 -1
- package/build/lib/commands/index.d.ts +2 -0
- package/build/lib/commands/index.d.ts.map +1 -0
- package/build/lib/commands/index.js +13 -22
- package/build/lib/commands/index.js.map +1 -1
- package/build/lib/commands/mixins.d.ts +87 -0
- package/build/lib/commands/mixins.d.ts.map +1 -0
- package/build/lib/commands/mixins.js +26 -0
- package/build/lib/commands/mixins.js.map +1 -0
- package/build/lib/commands/screenshot.d.ts +2 -0
- package/build/lib/commands/screenshot.d.ts.map +1 -0
- package/build/lib/commands/screenshot.js +77 -62
- package/build/lib/commands/screenshot.js.map +1 -1
- package/build/lib/commands/touch.d.ts +2 -0
- package/build/lib/commands/touch.d.ts.map +1 -0
- package/build/lib/commands/touch.js +48 -38
- package/build/lib/commands/touch.js.map +1 -1
- package/build/lib/commands/types.d.ts +452 -0
- package/build/lib/commands/types.d.ts.map +1 -0
- package/build/lib/commands/types.js +3 -0
- package/build/lib/commands/types.js.map +1 -0
- package/build/lib/commands/viewport.d.ts +2 -0
- package/build/lib/commands/viewport.d.ts.map +1 -0
- package/build/lib/commands/viewport.js +37 -35
- package/build/lib/commands/viewport.js.map +1 -1
- package/build/lib/constraints.d.ts +325 -0
- package/build/lib/constraints.d.ts.map +1 -0
- package/build/lib/constraints.js +51 -0
- package/build/lib/constraints.js.map +1 -0
- package/build/lib/css-converter.d.ts +45 -0
- package/build/lib/css-converter.d.ts.map +1 -0
- package/build/lib/css-converter.js +272 -175
- package/build/lib/css-converter.js.map +1 -1
- package/build/lib/driver.d.ts +904 -0
- package/build/lib/driver.d.ts.map +1 -0
- package/build/lib/driver.js +726 -485
- package/build/lib/driver.js.map +1 -1
- package/build/lib/execute-method-map.d.ts +477 -0
- package/build/lib/execute-method-map.d.ts.map +1 -0
- package/build/lib/execute-method-map.js +542 -0
- package/build/lib/execute-method-map.js.map +1 -0
- package/build/lib/extensions.d.ts +3 -0
- package/build/lib/extensions.d.ts.map +1 -0
- package/build/lib/extensions.js +7 -9
- package/build/lib/extensions.js.map +1 -1
- package/build/lib/helpers.d.ts +7 -0
- package/build/lib/helpers.d.ts.map +1 -0
- package/build/lib/helpers.js +36 -29
- package/build/lib/helpers.js.map +1 -1
- package/build/lib/logger.d.ts +3 -0
- package/build/lib/logger.d.ts.map +1 -0
- package/build/lib/logger.js +5 -10
- package/build/lib/logger.js.map +1 -1
- package/build/lib/method-map.d.ts +389 -0
- package/build/lib/method-map.d.ts.map +1 -0
- package/build/lib/method-map.js +11 -17
- package/build/lib/method-map.js.map +1 -1
- package/build/lib/types.d.ts +44 -0
- package/build/lib/types.d.ts.map +1 -0
- package/build/lib/types.js +3 -0
- package/build/lib/types.js.map +1 -0
- package/build/lib/uiautomator2.d.ts +45 -0
- package/build/lib/uiautomator2.d.ts.map +1 -0
- package/build/lib/uiautomator2.js +340 -299
- package/build/lib/uiautomator2.js.map +1 -1
- package/build/lib/utils.d.ts +10 -0
- package/build/lib/utils.d.ts.map +1 -0
- package/build/lib/utils.js +23 -16
- package/build/lib/utils.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -0
- package/index.js +5 -3
- package/lib/commands/actions.js +115 -101
- package/lib/commands/alert.js +36 -44
- package/lib/commands/app-strings.js +79 -58
- package/lib/commands/battery.js +27 -28
- package/lib/commands/element.js +231 -134
- package/lib/commands/find.js +40 -21
- package/lib/commands/general.js +262 -336
- package/lib/commands/gestures.js +252 -366
- package/lib/commands/index.js +11 -31
- package/lib/commands/mixins.ts +169 -0
- package/lib/commands/screenshot.js +80 -76
- package/lib/commands/touch.js +64 -31
- package/lib/commands/types.ts +473 -0
- package/lib/commands/viewport.js +43 -31
- package/lib/constraints.ts +53 -0
- package/lib/css-converter.js +9 -1
- package/lib/{driver.js → driver.ts} +374 -239
- package/lib/execute-method-map.ts +573 -0
- package/lib/method-map.ts +11 -0
- package/lib/types.ts +57 -0
- package/lib/uiautomator2.js +21 -2
- package/lib/utils.js +2 -2
- package/npm-shrinkwrap.json +395 -528
- package/package.json +96 -70
- package/build/lib/desired-caps.js +0 -71
- package/build/lib/desired-caps.js.map +0 -1
- package/lib/desired-caps.js +0 -70
- package/lib/method-map.js +0 -11
|
@@ -1,323 +1,364 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
require("
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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 =
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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
|
-
|
|
217
|
-
|
|
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
|
-
|
|
241
|
-
|
|
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
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
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
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
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
|
-
|
|
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
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
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
|
-
|
|
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
|