appium-adb 9.10.2 → 9.10.3
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/README.md +1 -1
- package/lib/helpers.js +26 -3
- package/lib/tools/apk-signing.js +3 -4
- package/package.json +39 -26
- package/build/index.js +0 -30
- package/build/lib/adb.js +0 -132
- package/build/lib/helpers.js +0 -957
- package/build/lib/logcat.js +0 -221
- package/build/lib/logger.js +0 -18
- package/build/lib/tools/aab-utils.js +0 -157
- package/build/lib/tools/adb-commands.js +0 -1150
- package/build/lib/tools/adb-emu-commands.js +0 -397
- package/build/lib/tools/android-manifest.js +0 -231
- package/build/lib/tools/apk-signing.js +0 -333
- package/build/lib/tools/apk-utils.js +0 -992
- package/build/lib/tools/apks-utils.js +0 -219
- package/build/lib/tools/index.js +0 -49
- package/build/lib/tools/keyboard-commands.js +0 -71
- package/build/lib/tools/lockmgmt.js +0 -224
- package/build/lib/tools/settings-client-commands.js +0 -362
- package/build/lib/tools/system-calls.js +0 -1064
|
@@ -1,1150 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
-
|
|
5
|
-
Object.defineProperty(exports, "__esModule", {
|
|
6
|
-
value: true
|
|
7
|
-
});
|
|
8
|
-
exports.default = void 0;
|
|
9
|
-
|
|
10
|
-
require("source-map-support/register");
|
|
11
|
-
|
|
12
|
-
var _logger = _interopRequireDefault(require("../logger.js"));
|
|
13
|
-
|
|
14
|
-
var _helpers = require("../helpers.js");
|
|
15
|
-
|
|
16
|
-
var _path = _interopRequireDefault(require("path"));
|
|
17
|
-
|
|
18
|
-
var _lodash = _interopRequireDefault(require("lodash"));
|
|
19
|
-
|
|
20
|
-
var _support = require("@appium/support");
|
|
21
|
-
|
|
22
|
-
var _os = require("os");
|
|
23
|
-
|
|
24
|
-
var _logcat = _interopRequireDefault(require("../logcat"));
|
|
25
|
-
|
|
26
|
-
var _asyncbox = require("asyncbox");
|
|
27
|
-
|
|
28
|
-
var _teen_process = require("teen_process");
|
|
29
|
-
|
|
30
|
-
var _bluebird = _interopRequireDefault(require("bluebird"));
|
|
31
|
-
|
|
32
|
-
const MAX_SHELL_BUFFER_LENGTH = 1000;
|
|
33
|
-
const NOT_CHANGEABLE_PERM_ERROR = /not a changeable permission type/i;
|
|
34
|
-
const IGNORED_PERM_ERRORS = [NOT_CHANGEABLE_PERM_ERROR, /Unknown permission/i];
|
|
35
|
-
const MAX_PGREP_PATTERN_LEN = 15;
|
|
36
|
-
const HIDDEN_API_POLICY_KEYS = ['hidden_api_policy_pre_p_apps', 'hidden_api_policy_p_apps', 'hidden_api_policy'];
|
|
37
|
-
const PID_COLUMN_TITLE = 'PID';
|
|
38
|
-
const PROCESS_NAME_COLUMN_TITLE = 'NAME';
|
|
39
|
-
const PS_TITLE_PATTERN = new RegExp(`^(.*\\b${PID_COLUMN_TITLE}\\b.*\\b${PROCESS_NAME_COLUMN_TITLE}\\b.*)$`, 'm');
|
|
40
|
-
const ADB_INPUT_ESCAPE_PATTERN = /[()<>|;&*\\~^"']/g;
|
|
41
|
-
const methods = {};
|
|
42
|
-
|
|
43
|
-
methods.shellChunks = async function shellChunks(argTransformer, args) {
|
|
44
|
-
const commands = [];
|
|
45
|
-
let cmdChunk = [];
|
|
46
|
-
|
|
47
|
-
for (const arg of args) {
|
|
48
|
-
const nextCmd = argTransformer(arg);
|
|
49
|
-
|
|
50
|
-
if (!_lodash.default.isArray(nextCmd)) {
|
|
51
|
-
throw new Error('Argument transformer must result in an array');
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (_lodash.default.last(nextCmd) !== ';') {
|
|
55
|
-
nextCmd.push(';');
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (nextCmd.join(' ').length + cmdChunk.join(' ').length >= MAX_SHELL_BUFFER_LENGTH) {
|
|
59
|
-
commands.push(cmdChunk);
|
|
60
|
-
cmdChunk = [];
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
cmdChunk = [...cmdChunk, ...nextCmd];
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (!_lodash.default.isEmpty(cmdChunk)) {
|
|
67
|
-
commands.push(cmdChunk);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
_logger.default.debug(`Got the following command chunks to execute: ${JSON.stringify(commands)}`);
|
|
71
|
-
|
|
72
|
-
let lastError = null;
|
|
73
|
-
|
|
74
|
-
for (const cmd of commands) {
|
|
75
|
-
try {
|
|
76
|
-
await this.shell(cmd);
|
|
77
|
-
} catch (e) {
|
|
78
|
-
lastError = e;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (lastError) {
|
|
83
|
-
throw lastError;
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
methods.getAdbWithCorrectAdbPath = async function getAdbWithCorrectAdbPath() {
|
|
88
|
-
this.executable.path = await this.getSdkBinaryPath('adb');
|
|
89
|
-
return this.adb;
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
methods.initAapt = async function initAapt() {
|
|
93
|
-
await this.getSdkBinaryPath('aapt');
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
methods.initAapt2 = async function initAapt2() {
|
|
97
|
-
await this.getSdkBinaryPath('aapt2');
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
methods.initZipAlign = async function initZipAlign() {
|
|
101
|
-
await this.getSdkBinaryPath('zipalign');
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
methods.initBundletool = async function initBundletool() {
|
|
105
|
-
try {
|
|
106
|
-
this.binaries.bundletool = await _support.fs.which('bundletool.jar');
|
|
107
|
-
} catch (err) {
|
|
108
|
-
throw new Error('bundletool.jar binary is expected to be present in PATH. ' + 'Visit https://github.com/google/bundletool for more details.');
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
methods.getApiLevel = async function getApiLevel() {
|
|
113
|
-
if (!_lodash.default.isInteger(this._apiLevel)) {
|
|
114
|
-
try {
|
|
115
|
-
const strOutput = await this.getDeviceProperty('ro.build.version.sdk');
|
|
116
|
-
let apiLevel = parseInt(strOutput.trim(), 10);
|
|
117
|
-
const charCodeQ = 'q'.charCodeAt(0);
|
|
118
|
-
const apiLevelDiff = apiLevel - 28;
|
|
119
|
-
const codename = String.fromCharCode(charCodeQ + apiLevelDiff);
|
|
120
|
-
|
|
121
|
-
if (apiLevelDiff >= 0 && (await this.getPlatformVersion()).toLowerCase() === codename) {
|
|
122
|
-
_logger.default.debug(`Release version is ${codename.toUpperCase()} but found API Level ${apiLevel}. Setting API Level to ${apiLevel + 1}`);
|
|
123
|
-
|
|
124
|
-
apiLevel++;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
this._apiLevel = apiLevel;
|
|
128
|
-
|
|
129
|
-
_logger.default.debug(`Device API level: ${this._apiLevel}`);
|
|
130
|
-
|
|
131
|
-
if (isNaN(this._apiLevel)) {
|
|
132
|
-
throw new Error(`The actual output '${strOutput}' cannot be converted to an integer`);
|
|
133
|
-
}
|
|
134
|
-
} catch (e) {
|
|
135
|
-
throw new Error(`Error getting device API level. Original error: ${e.message}`);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return this._apiLevel;
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
methods.getPlatformVersion = async function getPlatformVersion() {
|
|
143
|
-
_logger.default.info('Getting device platform version');
|
|
144
|
-
|
|
145
|
-
try {
|
|
146
|
-
return await this.getDeviceProperty('ro.build.version.release');
|
|
147
|
-
} catch (e) {
|
|
148
|
-
throw new Error(`Error getting device platform version. Original error: ${e.message}`);
|
|
149
|
-
}
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
methods.isDeviceConnected = async function isDeviceConnected() {
|
|
153
|
-
let devices = await this.getConnectedDevices();
|
|
154
|
-
return devices.length > 0;
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
methods.mkdir = async function mkdir(remotePath) {
|
|
158
|
-
return await this.shell(['mkdir', '-p', remotePath]);
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
methods.isValidClass = function isValidClass(classString) {
|
|
162
|
-
return (0, _helpers.matchComponentName)(classString);
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
methods.resolveLaunchableActivity = async function resolveLaunchableActivity(pkg, opts = {}) {
|
|
166
|
-
const {
|
|
167
|
-
preferCmd = true
|
|
168
|
-
} = opts;
|
|
169
|
-
|
|
170
|
-
if (!preferCmd || (await this.getApiLevel()) < 24) {
|
|
171
|
-
const stdout = await this.shell(['dumpsys', 'package', pkg]);
|
|
172
|
-
const names = (0, _helpers.parseLaunchableActivityNames)(stdout);
|
|
173
|
-
|
|
174
|
-
if (_lodash.default.isEmpty(names)) {
|
|
175
|
-
_logger.default.debug(stdout);
|
|
176
|
-
|
|
177
|
-
throw new Error(`Unable to resolve the launchable activity of '${pkg}'. Is it installed on the device?`);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if (names.length === 1) {
|
|
181
|
-
return names[0];
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const tmpRoot = await _support.tempDir.openDir();
|
|
185
|
-
|
|
186
|
-
try {
|
|
187
|
-
const tmpApp = await this.pullApk(pkg, tmpRoot);
|
|
188
|
-
const {
|
|
189
|
-
apkActivity
|
|
190
|
-
} = await this.packageAndLaunchActivityFromManifest(tmpApp);
|
|
191
|
-
return apkActivity;
|
|
192
|
-
} catch (e) {
|
|
193
|
-
_logger.default.debug(e.stack);
|
|
194
|
-
|
|
195
|
-
_logger.default.warn(`Unable to resolve the launchable activity of '${pkg}'. ` + `The very first match of the dumpsys output is going to be used. ` + `Original error: ${e.message}`);
|
|
196
|
-
|
|
197
|
-
return names[0];
|
|
198
|
-
} finally {
|
|
199
|
-
await _support.fs.rimraf(tmpRoot);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const {
|
|
204
|
-
stdout,
|
|
205
|
-
stderr
|
|
206
|
-
} = await this.shell(['cmd', 'package', 'resolve-activity', '--brief', pkg], {
|
|
207
|
-
outputFormat: this.EXEC_OUTPUT_FORMAT.FULL
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
for (const line of (stdout || '').split('\n').map(_lodash.default.trim)) {
|
|
211
|
-
if (this.isValidClass(line)) {
|
|
212
|
-
return line;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
throw new Error(`Unable to resolve the launchable activity of '${pkg}'. Original error: ${stderr || stdout}`);
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
methods.forceStop = async function forceStop(pkg) {
|
|
220
|
-
return await this.shell(['am', 'force-stop', pkg]);
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
methods.killPackage = async function killPackage(pkg) {
|
|
224
|
-
return await this.shell(['am', 'kill', pkg]);
|
|
225
|
-
};
|
|
226
|
-
|
|
227
|
-
methods.clear = async function clear(pkg) {
|
|
228
|
-
return await this.shell(['pm', 'clear', pkg]);
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
methods.grantAllPermissions = async function grantAllPermissions(pkg, apk) {
|
|
232
|
-
const apiLevel = await this.getApiLevel();
|
|
233
|
-
let targetSdk = 0;
|
|
234
|
-
let dumpsysOutput = null;
|
|
235
|
-
|
|
236
|
-
try {
|
|
237
|
-
if (!apk) {
|
|
238
|
-
dumpsysOutput = await this.shell(['dumpsys', 'package', pkg]);
|
|
239
|
-
targetSdk = await this.targetSdkVersionUsingPKG(pkg, dumpsysOutput);
|
|
240
|
-
} else {
|
|
241
|
-
targetSdk = await this.targetSdkVersionFromManifest(apk);
|
|
242
|
-
}
|
|
243
|
-
} catch (e) {
|
|
244
|
-
_logger.default.warn(`Ran into problem getting target SDK version; ignoring...`);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
if (apiLevel >= 23 && targetSdk >= 23) {
|
|
248
|
-
dumpsysOutput = dumpsysOutput || (await this.shell(['dumpsys', 'package', pkg]));
|
|
249
|
-
const requestedPermissions = await this.getReqPermissions(pkg, dumpsysOutput);
|
|
250
|
-
const grantedPermissions = await this.getGrantedPermissions(pkg, dumpsysOutput);
|
|
251
|
-
|
|
252
|
-
const permissionsToGrant = _lodash.default.difference(requestedPermissions, grantedPermissions);
|
|
253
|
-
|
|
254
|
-
if (_lodash.default.isEmpty(permissionsToGrant)) {
|
|
255
|
-
_logger.default.info(`${pkg} contains no permissions available for granting`);
|
|
256
|
-
} else {
|
|
257
|
-
await this.grantPermissions(pkg, permissionsToGrant);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
methods.grantPermissions = async function grantPermissions(pkg, permissions) {
|
|
263
|
-
_logger.default.debug(`Granting permissions ${JSON.stringify(permissions)} to '${pkg}'`);
|
|
264
|
-
|
|
265
|
-
try {
|
|
266
|
-
await this.shellChunks(perm => ['pm', 'grant', pkg, perm], permissions);
|
|
267
|
-
} catch (e) {
|
|
268
|
-
if (!IGNORED_PERM_ERRORS.some(pattern => pattern.test(e.stderr || e.message))) {
|
|
269
|
-
throw e;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
methods.grantPermission = async function grantPermission(pkg, permission) {
|
|
275
|
-
try {
|
|
276
|
-
await this.shell(['pm', 'grant', pkg, permission]);
|
|
277
|
-
} catch (e) {
|
|
278
|
-
if (!NOT_CHANGEABLE_PERM_ERROR.test(e.stderr || e.message)) {
|
|
279
|
-
throw e;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
methods.revokePermission = async function revokePermission(pkg, permission) {
|
|
285
|
-
try {
|
|
286
|
-
await this.shell(['pm', 'revoke', pkg, permission]);
|
|
287
|
-
} catch (e) {
|
|
288
|
-
if (!NOT_CHANGEABLE_PERM_ERROR.test(e.stderr || e.message)) {
|
|
289
|
-
throw e;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
methods.getGrantedPermissions = async function getGrantedPermissions(pkg, cmdOutput = null) {
|
|
295
|
-
_logger.default.debug('Retrieving granted permissions');
|
|
296
|
-
|
|
297
|
-
const stdout = cmdOutput || (await this.shell(['dumpsys', 'package', pkg]));
|
|
298
|
-
return (0, _helpers.extractMatchingPermissions)(stdout, ['install', 'runtime'], true);
|
|
299
|
-
};
|
|
300
|
-
|
|
301
|
-
methods.getDeniedPermissions = async function getDeniedPermissions(pkg, cmdOutput = null) {
|
|
302
|
-
_logger.default.debug('Retrieving denied permissions');
|
|
303
|
-
|
|
304
|
-
const stdout = cmdOutput || (await this.shell(['dumpsys', 'package', pkg]));
|
|
305
|
-
return (0, _helpers.extractMatchingPermissions)(stdout, ['install', 'runtime'], false);
|
|
306
|
-
};
|
|
307
|
-
|
|
308
|
-
methods.getReqPermissions = async function getReqPermissions(pkg, cmdOutput = null) {
|
|
309
|
-
_logger.default.debug('Retrieving requested permissions');
|
|
310
|
-
|
|
311
|
-
const stdout = cmdOutput || (await this.shell(['dumpsys', 'package', pkg]));
|
|
312
|
-
return (0, _helpers.extractMatchingPermissions)(stdout, ['requested']);
|
|
313
|
-
};
|
|
314
|
-
|
|
315
|
-
methods.getLocationProviders = async function getLocationProviders() {
|
|
316
|
-
let stdout = await this.getSetting('secure', 'location_providers_allowed');
|
|
317
|
-
return stdout.trim().split(',').map(p => p.trim()).filter(Boolean);
|
|
318
|
-
};
|
|
319
|
-
|
|
320
|
-
methods.toggleGPSLocationProvider = async function toggleGPSLocationProvider(enabled) {
|
|
321
|
-
await this.setSetting('secure', 'location_providers_allowed', `${enabled ? '+' : '-'}gps`);
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
methods.setHiddenApiPolicy = async function setHiddenApiPolicy(value, ignoreError = false) {
|
|
325
|
-
try {
|
|
326
|
-
await this.shell(HIDDEN_API_POLICY_KEYS.map(k => `settings put global ${k} ${value}`).join(';'));
|
|
327
|
-
} catch (e) {
|
|
328
|
-
if (!ignoreError) {
|
|
329
|
-
throw e;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
_logger.default.info(`Failed to set setting keys '${HIDDEN_API_POLICY_KEYS}' to '${value}'. Original error: ${e.message}`);
|
|
333
|
-
}
|
|
334
|
-
};
|
|
335
|
-
|
|
336
|
-
methods.setDefaultHiddenApiPolicy = async function setDefaultHiddenApiPolicy(ignoreError = false) {
|
|
337
|
-
try {
|
|
338
|
-
await this.shell(HIDDEN_API_POLICY_KEYS.map(k => `settings delete global ${k}`).join(';'));
|
|
339
|
-
} catch (e) {
|
|
340
|
-
if (!ignoreError) {
|
|
341
|
-
throw e;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
_logger.default.info(`Failed to delete keys '${HIDDEN_API_POLICY_KEYS}'. Original error: ${e.message}`);
|
|
345
|
-
}
|
|
346
|
-
};
|
|
347
|
-
|
|
348
|
-
methods.stopAndClear = async function stopAndClear(pkg) {
|
|
349
|
-
try {
|
|
350
|
-
await this.forceStop(pkg);
|
|
351
|
-
await this.clear(pkg);
|
|
352
|
-
} catch (e) {
|
|
353
|
-
throw new Error(`Cannot stop and clear ${pkg}. Original error: ${e.message}`);
|
|
354
|
-
}
|
|
355
|
-
};
|
|
356
|
-
|
|
357
|
-
methods.availableIMEs = async function availableIMEs() {
|
|
358
|
-
try {
|
|
359
|
-
return (0, _helpers.getIMEListFromOutput)(await this.shell(['ime', 'list', '-a']));
|
|
360
|
-
} catch (e) {
|
|
361
|
-
throw new Error(`Error getting available IME's. Original error: ${e.message}`);
|
|
362
|
-
}
|
|
363
|
-
};
|
|
364
|
-
|
|
365
|
-
methods.enabledIMEs = async function enabledIMEs() {
|
|
366
|
-
try {
|
|
367
|
-
return (0, _helpers.getIMEListFromOutput)(await this.shell(['ime', 'list']));
|
|
368
|
-
} catch (e) {
|
|
369
|
-
throw new Error(`Error getting enabled IME's. Original error: ${e.message}`);
|
|
370
|
-
}
|
|
371
|
-
};
|
|
372
|
-
|
|
373
|
-
methods.enableIME = async function enableIME(imeId) {
|
|
374
|
-
await this.shell(['ime', 'enable', imeId]);
|
|
375
|
-
};
|
|
376
|
-
|
|
377
|
-
methods.disableIME = async function disableIME(imeId) {
|
|
378
|
-
await this.shell(['ime', 'disable', imeId]);
|
|
379
|
-
};
|
|
380
|
-
|
|
381
|
-
methods.setIME = async function setIME(imeId) {
|
|
382
|
-
await this.shell(['ime', 'set', imeId]);
|
|
383
|
-
};
|
|
384
|
-
|
|
385
|
-
methods.defaultIME = async function defaultIME() {
|
|
386
|
-
try {
|
|
387
|
-
let engine = await this.getSetting('secure', 'default_input_method');
|
|
388
|
-
|
|
389
|
-
if (engine === 'null') {
|
|
390
|
-
return null;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
return engine.trim();
|
|
394
|
-
} catch (e) {
|
|
395
|
-
throw new Error(`Error getting default IME. Original error: ${e.message}`);
|
|
396
|
-
}
|
|
397
|
-
};
|
|
398
|
-
|
|
399
|
-
methods.keyevent = async function keyevent(keycode) {
|
|
400
|
-
let code = parseInt(keycode, 10);
|
|
401
|
-
await this.shell(['input', 'keyevent', code]);
|
|
402
|
-
};
|
|
403
|
-
|
|
404
|
-
methods.inputText = async function inputText(text) {
|
|
405
|
-
if (text === '') {
|
|
406
|
-
return;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
const originalStr = `${text}`;
|
|
410
|
-
const escapedText = originalStr.replace(/\$/g, '\\$').replace(/ /g, '%s');
|
|
411
|
-
let args = ['input', 'text', originalStr];
|
|
412
|
-
|
|
413
|
-
if (escapedText !== originalStr || ADB_INPUT_ESCAPE_PATTERN.test(originalStr)) {
|
|
414
|
-
if (_lodash.default.every(['"', `'`], c => originalStr.includes(c))) {
|
|
415
|
-
throw new Error(`Did not know how to escape a string that contains both types of quotes (" and ')`);
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
const q = originalStr.includes('"') ? `'` : '"';
|
|
419
|
-
args = [`input text ${q}${escapedText}${q}`];
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
await this.shell(args);
|
|
423
|
-
};
|
|
424
|
-
|
|
425
|
-
methods.clearTextField = async function clearTextField(length = 100) {
|
|
426
|
-
_logger.default.debug(`Clearing up to ${length} characters`);
|
|
427
|
-
|
|
428
|
-
if (length === 0) {
|
|
429
|
-
return;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
let args = ['input', 'keyevent'];
|
|
433
|
-
|
|
434
|
-
for (let i = 0; i < length; i++) {
|
|
435
|
-
args.push('67', '112');
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
await this.shell(args);
|
|
439
|
-
};
|
|
440
|
-
|
|
441
|
-
methods.lock = async function lock() {
|
|
442
|
-
if (await this.isScreenLocked()) {
|
|
443
|
-
_logger.default.debug('Screen is already locked. Doing nothing.');
|
|
444
|
-
|
|
445
|
-
return;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
_logger.default.debug('Pressing the KEYCODE_POWER button to lock screen');
|
|
449
|
-
|
|
450
|
-
await this.keyevent(26);
|
|
451
|
-
const timeoutMs = 5000;
|
|
452
|
-
|
|
453
|
-
try {
|
|
454
|
-
await (0, _asyncbox.waitForCondition)(async () => await this.isScreenLocked(), {
|
|
455
|
-
waitMs: timeoutMs,
|
|
456
|
-
intervalMs: 500
|
|
457
|
-
});
|
|
458
|
-
} catch (e) {
|
|
459
|
-
throw new Error(`The device screen is still locked after ${timeoutMs}ms timeout`);
|
|
460
|
-
}
|
|
461
|
-
};
|
|
462
|
-
|
|
463
|
-
methods.back = async function back() {
|
|
464
|
-
_logger.default.debug('Pressing the BACK button');
|
|
465
|
-
|
|
466
|
-
await this.keyevent(4);
|
|
467
|
-
};
|
|
468
|
-
|
|
469
|
-
methods.goToHome = async function goToHome() {
|
|
470
|
-
_logger.default.debug('Pressing the HOME button');
|
|
471
|
-
|
|
472
|
-
await this.keyevent(3);
|
|
473
|
-
};
|
|
474
|
-
|
|
475
|
-
methods.getAdbPath = function getAdbPath() {
|
|
476
|
-
return this.executable.path;
|
|
477
|
-
};
|
|
478
|
-
|
|
479
|
-
methods.getScreenOrientation = async function getScreenOrientation() {
|
|
480
|
-
let stdout = await this.shell(['dumpsys', 'input']);
|
|
481
|
-
return (0, _helpers.getSurfaceOrientation)(stdout);
|
|
482
|
-
};
|
|
483
|
-
|
|
484
|
-
methods.sendTelnetCommand = async function sendTelnetCommand(command) {
|
|
485
|
-
return await this.execEmuConsoleCommand(command, {
|
|
486
|
-
port: await this.getEmulatorPort()
|
|
487
|
-
});
|
|
488
|
-
};
|
|
489
|
-
|
|
490
|
-
methods.isAirplaneModeOn = async function isAirplaneModeOn() {
|
|
491
|
-
let stdout = await this.getSetting('global', 'airplane_mode_on');
|
|
492
|
-
return parseInt(stdout, 10) !== 0;
|
|
493
|
-
};
|
|
494
|
-
|
|
495
|
-
methods.setAirplaneMode = async function setAirplaneMode(on) {
|
|
496
|
-
await this.setSetting('global', 'airplane_mode_on', on ? 1 : 0);
|
|
497
|
-
};
|
|
498
|
-
|
|
499
|
-
methods.broadcastAirplaneMode = async function broadcastAirplaneMode(on) {
|
|
500
|
-
await this.shell(['am', 'broadcast', '-a', 'android.intent.action.AIRPLANE_MODE', '--ez', 'state', on ? 'true' : 'false']);
|
|
501
|
-
};
|
|
502
|
-
|
|
503
|
-
methods.isWifiOn = async function isWifiOn() {
|
|
504
|
-
let stdout = await this.getSetting('global', 'wifi_on');
|
|
505
|
-
return parseInt(stdout, 10) !== 0;
|
|
506
|
-
};
|
|
507
|
-
|
|
508
|
-
methods.isDataOn = async function isDataOn() {
|
|
509
|
-
let stdout = await this.getSetting('global', 'mobile_data');
|
|
510
|
-
return parseInt(stdout, 10) !== 0;
|
|
511
|
-
};
|
|
512
|
-
|
|
513
|
-
methods.setWifiAndData = async function setWifiAndData({
|
|
514
|
-
wifi,
|
|
515
|
-
data
|
|
516
|
-
}, isEmulator = false) {
|
|
517
|
-
if (_support.util.hasValue(wifi)) {
|
|
518
|
-
await this.setWifiState(wifi, isEmulator);
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
if (_support.util.hasValue(data)) {
|
|
522
|
-
await this.setDataState(data, isEmulator);
|
|
523
|
-
}
|
|
524
|
-
};
|
|
525
|
-
|
|
526
|
-
methods.isAnimationOn = async function isAnimationOn() {
|
|
527
|
-
let animator_duration_scale = await this.getSetting('global', 'animator_duration_scale');
|
|
528
|
-
let transition_animation_scale = await this.getSetting('global', 'transition_animation_scale');
|
|
529
|
-
let window_animation_scale = await this.getSetting('global', 'window_animation_scale');
|
|
530
|
-
return _lodash.default.some([animator_duration_scale, transition_animation_scale, window_animation_scale], setting => setting !== '0.0');
|
|
531
|
-
};
|
|
532
|
-
|
|
533
|
-
methods.rimraf = async function rimraf(path) {
|
|
534
|
-
await this.shell(['rm', '-rf', path]);
|
|
535
|
-
};
|
|
536
|
-
|
|
537
|
-
methods.push = async function push(localPath, remotePath, opts) {
|
|
538
|
-
await this.mkdir(_path.default.posix.dirname(remotePath));
|
|
539
|
-
await this.adbExec(['push', localPath, remotePath], opts);
|
|
540
|
-
};
|
|
541
|
-
|
|
542
|
-
methods.pull = async function pull(remotePath, localPath, opts = {}) {
|
|
543
|
-
var _opts$timeout;
|
|
544
|
-
|
|
545
|
-
await this.adbExec(['pull', remotePath, localPath], { ...opts,
|
|
546
|
-
timeout: (_opts$timeout = opts.timeout) !== null && _opts$timeout !== void 0 ? _opts$timeout : 60000
|
|
547
|
-
});
|
|
548
|
-
};
|
|
549
|
-
|
|
550
|
-
methods.processExists = async function processExists(processName) {
|
|
551
|
-
return !_lodash.default.isEmpty(await this.getPIDsByName(processName));
|
|
552
|
-
};
|
|
553
|
-
|
|
554
|
-
methods.getForwardList = async function getForwardList() {
|
|
555
|
-
_logger.default.debug(`List forwarding ports`);
|
|
556
|
-
|
|
557
|
-
const connections = await this.adbExec(['forward', '--list']);
|
|
558
|
-
return connections.split(_os.EOL).filter(line => Boolean(line.trim()));
|
|
559
|
-
};
|
|
560
|
-
|
|
561
|
-
methods.forwardPort = async function forwardPort(systemPort, devicePort) {
|
|
562
|
-
_logger.default.debug(`Forwarding system: ${systemPort} to device: ${devicePort}`);
|
|
563
|
-
|
|
564
|
-
await this.adbExec(['forward', `tcp:${systemPort}`, `tcp:${devicePort}`]);
|
|
565
|
-
};
|
|
566
|
-
|
|
567
|
-
methods.removePortForward = async function removePortForward(systemPort) {
|
|
568
|
-
_logger.default.debug(`Removing forwarded port socket connection: ${systemPort} `);
|
|
569
|
-
|
|
570
|
-
await this.adbExec(['forward', `--remove`, `tcp:${systemPort}`]);
|
|
571
|
-
};
|
|
572
|
-
|
|
573
|
-
methods.getReverseList = async function getReverseList() {
|
|
574
|
-
_logger.default.debug(`List reverse forwarding ports`);
|
|
575
|
-
|
|
576
|
-
const connections = await this.adbExec(['reverse', '--list']);
|
|
577
|
-
return connections.split(_os.EOL).filter(line => Boolean(line.trim()));
|
|
578
|
-
};
|
|
579
|
-
|
|
580
|
-
methods.reversePort = async function reversePort(devicePort, systemPort) {
|
|
581
|
-
_logger.default.debug(`Forwarding device: ${devicePort} to system: ${systemPort}`);
|
|
582
|
-
|
|
583
|
-
await this.adbExec(['reverse', `tcp:${devicePort}`, `tcp:${systemPort}`]);
|
|
584
|
-
};
|
|
585
|
-
|
|
586
|
-
methods.removePortReverse = async function removePortReverse(devicePort) {
|
|
587
|
-
_logger.default.debug(`Removing reverse forwarded port socket connection: ${devicePort} `);
|
|
588
|
-
|
|
589
|
-
await this.adbExec(['reverse', `--remove`, `tcp:${devicePort}`]);
|
|
590
|
-
};
|
|
591
|
-
|
|
592
|
-
methods.forwardAbstractPort = async function forwardAbstractPort(systemPort, devicePort) {
|
|
593
|
-
_logger.default.debug(`Forwarding system: ${systemPort} to abstract device: ${devicePort}`);
|
|
594
|
-
|
|
595
|
-
await this.adbExec(['forward', `tcp:${systemPort}`, `localabstract:${devicePort}`]);
|
|
596
|
-
};
|
|
597
|
-
|
|
598
|
-
methods.ping = async function ping() {
|
|
599
|
-
let stdout = await this.shell(['echo', 'ping']);
|
|
600
|
-
|
|
601
|
-
if (stdout.indexOf('ping') === 0) {
|
|
602
|
-
return true;
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
throw new Error(`ADB ping failed, returned ${stdout}`);
|
|
606
|
-
};
|
|
607
|
-
|
|
608
|
-
methods.restart = async function restart() {
|
|
609
|
-
try {
|
|
610
|
-
await this.stopLogcat();
|
|
611
|
-
await this.restartAdb();
|
|
612
|
-
await this.waitForDevice(60);
|
|
613
|
-
await this.startLogcat(this._logcatStartupParams);
|
|
614
|
-
} catch (e) {
|
|
615
|
-
throw new Error(`Restart failed. Original error: ${e.message}`);
|
|
616
|
-
}
|
|
617
|
-
};
|
|
618
|
-
|
|
619
|
-
methods.startLogcat = async function startLogcat(opts = {}) {
|
|
620
|
-
if (!_lodash.default.isEmpty(this.logcat)) {
|
|
621
|
-
throw new Error("Trying to start logcat capture but it's already started!");
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
this.logcat = new _logcat.default({
|
|
625
|
-
adb: this.executable,
|
|
626
|
-
debug: false,
|
|
627
|
-
debugTrace: false,
|
|
628
|
-
clearDeviceLogsOnStart: !!this.clearDeviceLogsOnStart
|
|
629
|
-
});
|
|
630
|
-
await this.logcat.startCapture(opts);
|
|
631
|
-
this._logcatStartupParams = opts;
|
|
632
|
-
};
|
|
633
|
-
|
|
634
|
-
methods.stopLogcat = async function stopLogcat() {
|
|
635
|
-
if (_lodash.default.isEmpty(this.logcat)) {
|
|
636
|
-
return;
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
try {
|
|
640
|
-
await this.logcat.stopCapture();
|
|
641
|
-
} finally {
|
|
642
|
-
this.logcat = null;
|
|
643
|
-
}
|
|
644
|
-
};
|
|
645
|
-
|
|
646
|
-
methods.getLogcatLogs = function getLogcatLogs() {
|
|
647
|
-
if (_lodash.default.isEmpty(this.logcat)) {
|
|
648
|
-
throw new Error("Can't get logcat logs since logcat hasn't started");
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
return this.logcat.getLogs();
|
|
652
|
-
};
|
|
653
|
-
|
|
654
|
-
methods.setLogcatListener = function setLogcatListener(listener) {
|
|
655
|
-
if (_lodash.default.isEmpty(this.logcat)) {
|
|
656
|
-
throw new Error("Logcat process hasn't been started");
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
this.logcat.on('output', listener);
|
|
660
|
-
};
|
|
661
|
-
|
|
662
|
-
methods.removeLogcatListener = function removeLogcatListener(listener) {
|
|
663
|
-
if (_lodash.default.isEmpty(this.logcat)) {
|
|
664
|
-
throw new Error("Logcat process hasn't been started");
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
this.logcat.removeListener('output', listener);
|
|
668
|
-
};
|
|
669
|
-
|
|
670
|
-
methods.listProcessStatus = async function listProcessStatus() {
|
|
671
|
-
if (!_lodash.default.isBoolean(this._doesPsSupportAOption)) {
|
|
672
|
-
try {
|
|
673
|
-
this._doesPsSupportAOption = /^-A\b/m.test(await this.shell(['ps', '--help']));
|
|
674
|
-
} catch (e) {
|
|
675
|
-
_logger.default.debug(e.stack);
|
|
676
|
-
|
|
677
|
-
this._doesPsSupportAOption = false;
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
return await this.shell(this._doesPsSupportAOption ? ['ps', '-A'] : ['ps']);
|
|
682
|
-
};
|
|
683
|
-
|
|
684
|
-
methods.getNameByPid = async function getNameByPid(pid) {
|
|
685
|
-
if (isNaN(pid)) {
|
|
686
|
-
throw new Error(`The PID value must be a valid number. '${pid}' is given instead`);
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
pid = parseInt(pid, 10);
|
|
690
|
-
const stdout = await this.listProcessStatus();
|
|
691
|
-
const titleMatch = PS_TITLE_PATTERN.exec(stdout);
|
|
692
|
-
|
|
693
|
-
if (!titleMatch) {
|
|
694
|
-
_logger.default.debug(stdout);
|
|
695
|
-
|
|
696
|
-
throw new Error(`Could not get the process name for PID '${pid}'`);
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
const allTitles = titleMatch[1].trim().split(/\s+/);
|
|
700
|
-
const pidIndex = allTitles.indexOf(PID_COLUMN_TITLE);
|
|
701
|
-
const nameOffset = allTitles.indexOf(PROCESS_NAME_COLUMN_TITLE) - allTitles.length;
|
|
702
|
-
const pidRegex = new RegExp(`^(.*\\b${pid}\\b.*)$`, 'gm');
|
|
703
|
-
let matchedLine;
|
|
704
|
-
|
|
705
|
-
while (matchedLine = pidRegex.exec(stdout)) {
|
|
706
|
-
const items = matchedLine[1].trim().split(/\s+/);
|
|
707
|
-
|
|
708
|
-
if (parseInt(items[pidIndex], 10) === pid && items[items.length + nameOffset]) {
|
|
709
|
-
return items[items.length + nameOffset];
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
_logger.default.debug(stdout);
|
|
714
|
-
|
|
715
|
-
throw new Error(`Could not get the process name for PID '${pid}'`);
|
|
716
|
-
};
|
|
717
|
-
|
|
718
|
-
methods.getPIDsByName = async function getPIDsByName(name) {
|
|
719
|
-
_logger.default.debug(`Getting IDs of all '${name}' processes`);
|
|
720
|
-
|
|
721
|
-
if (!this.isValidClass(name)) {
|
|
722
|
-
throw new Error(`Invalid process name: '${name}'`);
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
if ((await this.getApiLevel()) >= 23) {
|
|
726
|
-
if (!_lodash.default.isBoolean(this._isPgrepAvailable)) {
|
|
727
|
-
const pgrepOutput = _lodash.default.trim(await this.shell(['pgrep --help; echo $?']));
|
|
728
|
-
|
|
729
|
-
this._isPgrepAvailable = parseInt(_lodash.default.last(pgrepOutput.split(/\s+/)), 10) === 0;
|
|
730
|
-
|
|
731
|
-
if (this._isPgrepAvailable) {
|
|
732
|
-
this._canPgrepUseFullCmdLineSearch = /^-f\b/m.test(pgrepOutput);
|
|
733
|
-
} else {
|
|
734
|
-
this._isPidofAvailable = parseInt(await this.shell(['pidof --help > /dev/null; echo $?']), 10) === 0;
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
if (this._isPgrepAvailable || this._isPidofAvailable) {
|
|
739
|
-
const shellCommand = this._isPgrepAvailable ? this._canPgrepUseFullCmdLineSearch ? ['pgrep', '-f', _lodash.default.escapeRegExp(`([[:blank:]]|^)${name}([[:blank:]]|$)`)] : [`pgrep ^${_lodash.default.escapeRegExp(name.slice(-MAX_PGREP_PATTERN_LEN))}$ ` + `|| pgrep ^${_lodash.default.escapeRegExp(name.slice(0, MAX_PGREP_PATTERN_LEN))}$`] : ['pidof', name];
|
|
740
|
-
|
|
741
|
-
try {
|
|
742
|
-
return (await this.shell(shellCommand)).split(/\s+/).map(x => parseInt(x, 10)).filter(x => _lodash.default.isInteger(x));
|
|
743
|
-
} catch (e) {
|
|
744
|
-
if (e.code !== 1) {
|
|
745
|
-
throw new Error(`Could not extract process ID of '${name}': ${e.message}`);
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
if (_lodash.default.includes(e.stderr || e.stdout, 'syntax error')) {
|
|
749
|
-
_logger.default.warn(`Got an unexpected response from the shell interpreter: ${e.stderr || e.stdout}`);
|
|
750
|
-
} else {
|
|
751
|
-
return [];
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
_logger.default.debug('Using ps-based PID detection');
|
|
758
|
-
|
|
759
|
-
const stdout = await this.listProcessStatus();
|
|
760
|
-
const titleMatch = PS_TITLE_PATTERN.exec(stdout);
|
|
761
|
-
|
|
762
|
-
if (!titleMatch) {
|
|
763
|
-
_logger.default.debug(stdout);
|
|
764
|
-
|
|
765
|
-
throw new Error(`Could not extract PID of '${name}' from ps output`);
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
const allTitles = titleMatch[1].trim().split(/\s+/);
|
|
769
|
-
const pidIndex = allTitles.indexOf(PID_COLUMN_TITLE);
|
|
770
|
-
const pids = [];
|
|
771
|
-
const processNameRegex = new RegExp(`^(.*\\b\\d+\\b.*\\b${_lodash.default.escapeRegExp(name)}\\b.*)$`, 'gm');
|
|
772
|
-
let matchedLine;
|
|
773
|
-
|
|
774
|
-
while (matchedLine = processNameRegex.exec(stdout)) {
|
|
775
|
-
const items = matchedLine[1].trim().split(/\s+/);
|
|
776
|
-
|
|
777
|
-
if (pidIndex >= allTitles.length || isNaN(items[pidIndex])) {
|
|
778
|
-
_logger.default.debug(stdout);
|
|
779
|
-
|
|
780
|
-
throw new Error(`Could not extract PID of '${name}' from '${matchedLine[1].trim()}'`);
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
pids.push(parseInt(items[pidIndex], 10));
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
return pids;
|
|
787
|
-
};
|
|
788
|
-
|
|
789
|
-
methods.killProcessesByName = async function killProcessesByName(name) {
|
|
790
|
-
try {
|
|
791
|
-
_logger.default.debug(`Attempting to kill all ${name} processes`);
|
|
792
|
-
|
|
793
|
-
const pids = await this.getPIDsByName(name);
|
|
794
|
-
|
|
795
|
-
if (_lodash.default.isEmpty(pids)) {
|
|
796
|
-
_logger.default.info(`No '${name}' process has been found`);
|
|
797
|
-
} else {
|
|
798
|
-
await _bluebird.default.all(pids.map(p => this.killProcessByPID(p)));
|
|
799
|
-
}
|
|
800
|
-
} catch (e) {
|
|
801
|
-
throw new Error(`Unable to kill ${name} processes. Original error: ${e.message}`);
|
|
802
|
-
}
|
|
803
|
-
};
|
|
804
|
-
|
|
805
|
-
methods.killProcessByPID = async function killProcessByPID(pid) {
|
|
806
|
-
_logger.default.debug(`Attempting to kill process ${pid}`);
|
|
807
|
-
|
|
808
|
-
const noProcessFlag = 'No such process';
|
|
809
|
-
|
|
810
|
-
try {
|
|
811
|
-
await this.shell(['kill', pid]);
|
|
812
|
-
} catch (e) {
|
|
813
|
-
if (_lodash.default.includes(e.stderr, noProcessFlag)) {
|
|
814
|
-
return;
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
if (!_lodash.default.includes(e.stderr, 'Operation not permitted')) {
|
|
818
|
-
throw e;
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
_logger.default.info(`Cannot kill PID ${pid} due to insufficient permissions. Retrying as root`);
|
|
822
|
-
|
|
823
|
-
try {
|
|
824
|
-
await this.shell(['kill', pid], {
|
|
825
|
-
privileged: true
|
|
826
|
-
});
|
|
827
|
-
} catch (e1) {
|
|
828
|
-
if (_lodash.default.includes(e1.stderr, noProcessFlag)) {
|
|
829
|
-
return;
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
throw e1;
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
};
|
|
836
|
-
|
|
837
|
-
methods.broadcastProcessEnd = async function broadcastProcessEnd(intent, processName) {
|
|
838
|
-
this.broadcast(intent);
|
|
839
|
-
let start = Date.now();
|
|
840
|
-
let timeoutMs = 40000;
|
|
841
|
-
|
|
842
|
-
try {
|
|
843
|
-
while (Date.now() - start < timeoutMs) {
|
|
844
|
-
if (await this.processExists(processName)) {
|
|
845
|
-
await (0, _asyncbox.sleep)(400);
|
|
846
|
-
continue;
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
return;
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
throw new Error(`Process never died within ${timeoutMs} ms`);
|
|
853
|
-
} catch (e) {
|
|
854
|
-
throw new Error(`Unable to broadcast process end. Original error: ${e.message}`);
|
|
855
|
-
}
|
|
856
|
-
};
|
|
857
|
-
|
|
858
|
-
methods.broadcast = async function broadcast(intent) {
|
|
859
|
-
if (!this.isValidClass(intent)) {
|
|
860
|
-
throw new Error(`Invalid intent ${intent}`);
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
_logger.default.debug(`Broadcasting: ${intent}`);
|
|
864
|
-
|
|
865
|
-
await this.shell(['am', 'broadcast', '-a', intent]);
|
|
866
|
-
};
|
|
867
|
-
|
|
868
|
-
methods.endAndroidCoverage = async function endAndroidCoverage() {
|
|
869
|
-
if (this.instrumentProc && this.instrumentProc.isRunning) {
|
|
870
|
-
await this.instrumentProc.stop();
|
|
871
|
-
}
|
|
872
|
-
};
|
|
873
|
-
|
|
874
|
-
methods.instrument = async function instrument(pkg, activity, instrumentWith) {
|
|
875
|
-
if (activity[0] !== '.') {
|
|
876
|
-
pkg = '';
|
|
877
|
-
}
|
|
878
|
-
|
|
879
|
-
let pkgActivity = (pkg + activity).replace(/\.+/g, '.');
|
|
880
|
-
let stdout = await this.shell(['am', 'instrument', '-e', 'main_activity', pkgActivity, instrumentWith]);
|
|
881
|
-
|
|
882
|
-
if (stdout.indexOf('Exception') !== -1) {
|
|
883
|
-
throw new Error(`Unknown exception during instrumentation. Original error ${stdout.split('\n')[0]}`);
|
|
884
|
-
}
|
|
885
|
-
};
|
|
886
|
-
|
|
887
|
-
methods.androidCoverage = async function androidCoverage(instrumentClass, waitPkg, waitActivity) {
|
|
888
|
-
if (!this.isValidClass(instrumentClass)) {
|
|
889
|
-
throw new Error(`Invalid class ${instrumentClass}`);
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
return await new _bluebird.default(async (resolve, reject) => {
|
|
893
|
-
let args = this.executable.defaultArgs.concat(['shell', 'am', 'instrument', '-e', 'coverage', 'true', '-w']).concat([instrumentClass]);
|
|
894
|
-
|
|
895
|
-
_logger.default.debug(`Collecting coverage data with: ${[this.executable.path].concat(args).join(' ')}`);
|
|
896
|
-
|
|
897
|
-
try {
|
|
898
|
-
this.instrumentProc = new _teen_process.SubProcess(this.executable.path, args);
|
|
899
|
-
await this.instrumentProc.start(0);
|
|
900
|
-
this.instrumentProc.on('output', (stdout, stderr) => {
|
|
901
|
-
if (stderr) {
|
|
902
|
-
reject(new Error(`Failed to run instrumentation. Original error: ${stderr}`));
|
|
903
|
-
}
|
|
904
|
-
});
|
|
905
|
-
await this.waitForActivity(waitPkg, waitActivity);
|
|
906
|
-
resolve();
|
|
907
|
-
} catch (e) {
|
|
908
|
-
reject(new Error(`Android coverage failed. Original error: ${e.message}`));
|
|
909
|
-
}
|
|
910
|
-
});
|
|
911
|
-
};
|
|
912
|
-
|
|
913
|
-
methods.getDeviceProperty = async function getDeviceProperty(property) {
|
|
914
|
-
let stdout = await this.shell(['getprop', property]);
|
|
915
|
-
let val = stdout.trim();
|
|
916
|
-
|
|
917
|
-
_logger.default.debug(`Current device property '${property}': ${val}`);
|
|
918
|
-
|
|
919
|
-
return val;
|
|
920
|
-
};
|
|
921
|
-
|
|
922
|
-
methods.setDeviceProperty = async function setDeviceProperty(prop, val, opts = {}) {
|
|
923
|
-
const {
|
|
924
|
-
privileged = true
|
|
925
|
-
} = opts;
|
|
926
|
-
|
|
927
|
-
_logger.default.debug(`Setting device property '${prop}' to '${val}'`);
|
|
928
|
-
|
|
929
|
-
await this.shell(['setprop', prop, val], {
|
|
930
|
-
privileged
|
|
931
|
-
});
|
|
932
|
-
};
|
|
933
|
-
|
|
934
|
-
methods.getDeviceSysLanguage = async function getDeviceSysLanguage() {
|
|
935
|
-
return await this.getDeviceProperty('persist.sys.language');
|
|
936
|
-
};
|
|
937
|
-
|
|
938
|
-
methods.getDeviceSysCountry = async function getDeviceSysCountry() {
|
|
939
|
-
return await this.getDeviceProperty('persist.sys.country');
|
|
940
|
-
};
|
|
941
|
-
|
|
942
|
-
methods.getDeviceSysLocale = async function getDeviceSysLocale() {
|
|
943
|
-
return await this.getDeviceProperty('persist.sys.locale');
|
|
944
|
-
};
|
|
945
|
-
|
|
946
|
-
methods.getDeviceProductLanguage = async function getDeviceProductLanguage() {
|
|
947
|
-
return await this.getDeviceProperty('ro.product.locale.language');
|
|
948
|
-
};
|
|
949
|
-
|
|
950
|
-
methods.getDeviceProductCountry = async function getDeviceProductCountry() {
|
|
951
|
-
return await this.getDeviceProperty('ro.product.locale.region');
|
|
952
|
-
};
|
|
953
|
-
|
|
954
|
-
methods.getDeviceProductLocale = async function getDeviceProductLocale() {
|
|
955
|
-
return await this.getDeviceProperty('ro.product.locale');
|
|
956
|
-
};
|
|
957
|
-
|
|
958
|
-
methods.getModel = async function getModel() {
|
|
959
|
-
return await this.getDeviceProperty('ro.product.model');
|
|
960
|
-
};
|
|
961
|
-
|
|
962
|
-
methods.getManufacturer = async function getManufacturer() {
|
|
963
|
-
return await this.getDeviceProperty('ro.product.manufacturer');
|
|
964
|
-
};
|
|
965
|
-
|
|
966
|
-
methods.getScreenSize = async function getScreenSize() {
|
|
967
|
-
let stdout = await this.shell(['wm', 'size']);
|
|
968
|
-
let size = new RegExp(/Physical size: ([^\r?\n]+)*/g).exec(stdout);
|
|
969
|
-
|
|
970
|
-
if (size && size.length >= 2) {
|
|
971
|
-
return size[1].trim();
|
|
972
|
-
}
|
|
973
|
-
|
|
974
|
-
return null;
|
|
975
|
-
};
|
|
976
|
-
|
|
977
|
-
methods.getScreenDensity = async function getScreenDensity() {
|
|
978
|
-
let stdout = await this.shell(['wm', 'density']);
|
|
979
|
-
let density = new RegExp(/Physical density: ([^\r?\n]+)*/g).exec(stdout);
|
|
980
|
-
|
|
981
|
-
if (density && density.length >= 2) {
|
|
982
|
-
let densityNumber = parseInt(density[1].trim(), 10);
|
|
983
|
-
return isNaN(densityNumber) ? null : densityNumber;
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
return null;
|
|
987
|
-
};
|
|
988
|
-
|
|
989
|
-
methods.setHttpProxy = async function setHttpProxy(proxyHost, proxyPort) {
|
|
990
|
-
let proxy = `${proxyHost}:${proxyPort}`;
|
|
991
|
-
|
|
992
|
-
if (_lodash.default.isUndefined(proxyHost)) {
|
|
993
|
-
throw new Error(`Call to setHttpProxy method with undefined proxy_host: ${proxy}`);
|
|
994
|
-
}
|
|
995
|
-
|
|
996
|
-
if (_lodash.default.isUndefined(proxyPort)) {
|
|
997
|
-
throw new Error(`Call to setHttpProxy method with undefined proxy_port ${proxy}`);
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
const httpProxySettins = [['http_proxy', proxy], ['global_http_proxy_host', proxyHost], ['global_http_proxy_port', proxyPort]];
|
|
1001
|
-
|
|
1002
|
-
for (const [settingKey, settingValue] of httpProxySettins) {
|
|
1003
|
-
await this.setSetting('global', settingKey, settingValue);
|
|
1004
|
-
}
|
|
1005
|
-
};
|
|
1006
|
-
|
|
1007
|
-
methods.deleteHttpProxy = async function deleteHttpProxy() {
|
|
1008
|
-
const httpProxySettins = ['http_proxy', 'global_http_proxy_host', 'global_http_proxy_port', 'global_http_proxy_exclusion_list'];
|
|
1009
|
-
|
|
1010
|
-
for (const setting of httpProxySettins) {
|
|
1011
|
-
await this.shell(['settings', 'delete', 'global', setting]);
|
|
1012
|
-
}
|
|
1013
|
-
};
|
|
1014
|
-
|
|
1015
|
-
methods.setSetting = async function setSetting(namespace, setting, value) {
|
|
1016
|
-
return await this.shell(['settings', 'put', namespace, setting, value]);
|
|
1017
|
-
};
|
|
1018
|
-
|
|
1019
|
-
methods.getSetting = async function getSetting(namespace, setting) {
|
|
1020
|
-
return await this.shell(['settings', 'get', namespace, setting]);
|
|
1021
|
-
};
|
|
1022
|
-
|
|
1023
|
-
methods.bugreport = async function bugreport(timeout = 120000) {
|
|
1024
|
-
return await this.adbExec(['bugreport'], {
|
|
1025
|
-
timeout
|
|
1026
|
-
});
|
|
1027
|
-
};
|
|
1028
|
-
|
|
1029
|
-
methods.screenrecord = function screenrecord(destination, options = {}) {
|
|
1030
|
-
const cmd = ['screenrecord'];
|
|
1031
|
-
const {
|
|
1032
|
-
videoSize,
|
|
1033
|
-
bitRate,
|
|
1034
|
-
timeLimit,
|
|
1035
|
-
bugReport
|
|
1036
|
-
} = options;
|
|
1037
|
-
|
|
1038
|
-
if (_support.util.hasValue(videoSize)) {
|
|
1039
|
-
cmd.push('--size', videoSize);
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
|
-
if (_support.util.hasValue(timeLimit)) {
|
|
1043
|
-
cmd.push('--time-limit', timeLimit);
|
|
1044
|
-
}
|
|
1045
|
-
|
|
1046
|
-
if (_support.util.hasValue(bitRate)) {
|
|
1047
|
-
cmd.push('--bit-rate', bitRate);
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
if (bugReport) {
|
|
1051
|
-
cmd.push('--bugreport');
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
|
-
cmd.push(destination);
|
|
1055
|
-
const fullCmd = [...this.executable.defaultArgs, 'shell', ...cmd];
|
|
1056
|
-
|
|
1057
|
-
_logger.default.debug(`Building screenrecord process with the command line: adb ${_support.util.quote(fullCmd)}`);
|
|
1058
|
-
|
|
1059
|
-
return new _teen_process.SubProcess(this.executable.path, fullCmd);
|
|
1060
|
-
};
|
|
1061
|
-
|
|
1062
|
-
methods.runInImeContext = async function runInImeContext(ime, fn) {
|
|
1063
|
-
const originalIme = await this.defaultIME();
|
|
1064
|
-
|
|
1065
|
-
if (originalIme === ime) {
|
|
1066
|
-
_logger.default.debug(`The original IME is the same as '${ime}'. There is no need to reset it`);
|
|
1067
|
-
} else {
|
|
1068
|
-
await this.enableIME(ime);
|
|
1069
|
-
await this.setIME(ime);
|
|
1070
|
-
await _bluebird.default.delay(500);
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
|
-
try {
|
|
1074
|
-
return await fn();
|
|
1075
|
-
} finally {
|
|
1076
|
-
if (originalIme !== ime) {
|
|
1077
|
-
await this.setIME(originalIme);
|
|
1078
|
-
}
|
|
1079
|
-
}
|
|
1080
|
-
};
|
|
1081
|
-
|
|
1082
|
-
methods.getTimeZone = async function getTimeZone() {
|
|
1083
|
-
_logger.default.debug('Getting current timezone');
|
|
1084
|
-
|
|
1085
|
-
try {
|
|
1086
|
-
return await this.getDeviceProperty('persist.sys.timezone');
|
|
1087
|
-
} catch (e) {
|
|
1088
|
-
throw new Error(`Error getting timezone. Original error: ${e.message}`);
|
|
1089
|
-
}
|
|
1090
|
-
};
|
|
1091
|
-
|
|
1092
|
-
methods.listFeatures = async function listFeatures() {
|
|
1093
|
-
this._memoizedFeatures = this._memoizedFeatures || _lodash.default.memoize(async () => await this.adbExec(['features']), () => this.curDeviceId);
|
|
1094
|
-
|
|
1095
|
-
try {
|
|
1096
|
-
return (await this._memoizedFeatures()).split(/\s+/).map(x => x.trim()).filter(Boolean);
|
|
1097
|
-
} catch (e) {
|
|
1098
|
-
if (_lodash.default.includes(e.stderr, 'unknown command')) {
|
|
1099
|
-
return [];
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
throw e;
|
|
1103
|
-
}
|
|
1104
|
-
};
|
|
1105
|
-
|
|
1106
|
-
methods.isStreamedInstallSupported = async function isStreamedInstallSupported() {
|
|
1107
|
-
const proto = Object.getPrototypeOf(this);
|
|
1108
|
-
proto._helpOutput = proto._helpOutput || (await this.adbExec(['help']));
|
|
1109
|
-
return proto._helpOutput.includes('--streaming') && (await this.listFeatures()).includes('cmd');
|
|
1110
|
-
};
|
|
1111
|
-
|
|
1112
|
-
methods.isIncrementalInstallSupported = async function isIncrementalInstallSupported() {
|
|
1113
|
-
const {
|
|
1114
|
-
binary
|
|
1115
|
-
} = await this.getVersion();
|
|
1116
|
-
|
|
1117
|
-
if (!binary) {
|
|
1118
|
-
return false;
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
return _support.util.compareVersions(binary.version, '>=', '30.0.1') && (await this.listFeatures()).includes('abb_exec');
|
|
1122
|
-
};
|
|
1123
|
-
|
|
1124
|
-
methods.getDeviceIdleWhitelist = async function getDeviceIdleWhitelist() {
|
|
1125
|
-
if ((await this.getApiLevel()) < 23) {
|
|
1126
|
-
return [];
|
|
1127
|
-
}
|
|
1128
|
-
|
|
1129
|
-
_logger.default.info('Listing packages in Doze whitelist');
|
|
1130
|
-
|
|
1131
|
-
const output = await this.shell(['dumpsys', 'deviceidle', 'whitelist']);
|
|
1132
|
-
return _lodash.default.trim(output).split(/\n/).map(line => _lodash.default.trim(line)).filter(Boolean);
|
|
1133
|
-
};
|
|
1134
|
-
|
|
1135
|
-
methods.addToDeviceIdleWhitelist = async function addToDeviceIdleWhitelist(...packages) {
|
|
1136
|
-
if (_lodash.default.isEmpty(packages) || (await this.getApiLevel()) < 23) {
|
|
1137
|
-
return false;
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1140
|
-
_logger.default.info(`Adding ${_support.util.pluralize('package', packages.length)} ${JSON.stringify(packages)} to Doze whitelist`);
|
|
1141
|
-
|
|
1142
|
-
await this.shellChunks(pkg => ['dumpsys', 'deviceidle', 'whitelist', `+${pkg}`], packages);
|
|
1143
|
-
return true;
|
|
1144
|
-
};
|
|
1145
|
-
|
|
1146
|
-
var _default = methods;
|
|
1147
|
-
exports.default = _default;require('source-map-support').install();
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGliL3Rvb2xzL2FkYi1jb21tYW5kcy5qcyIsIm5hbWVzIjpbIk1BWF9TSEVMTF9CVUZGRVJfTEVOR1RIIiwiTk9UX0NIQU5HRUFCTEVfUEVSTV9FUlJPUiIsIklHTk9SRURfUEVSTV9FUlJPUlMiLCJNQVhfUEdSRVBfUEFUVEVSTl9MRU4iLCJISURERU5fQVBJX1BPTElDWV9LRVlTIiwiUElEX0NPTFVNTl9USVRMRSIsIlBST0NFU1NfTkFNRV9DT0xVTU5fVElUTEUiLCJQU19USVRMRV9QQVRURVJOIiwiUmVnRXhwIiwiQURCX0lOUFVUX0VTQ0FQRV9QQVRURVJOIiwibWV0aG9kcyIsInNoZWxsQ2h1bmtzIiwiYXJnVHJhbnNmb3JtZXIiLCJhcmdzIiwiY29tbWFuZHMiLCJjbWRDaHVuayIsImFyZyIsIm5leHRDbWQiLCJfIiwiaXNBcnJheSIsIkVycm9yIiwibGFzdCIsInB1c2giLCJqb2luIiwibGVuZ3RoIiwiaXNFbXB0eSIsImxvZyIsImRlYnVnIiwiSlNPTiIsInN0cmluZ2lmeSIsImxhc3RFcnJvciIsImNtZCIsInNoZWxsIiwiZSIsImdldEFkYldpdGhDb3JyZWN0QWRiUGF0aCIsImV4ZWN1dGFibGUiLCJwYXRoIiwiZ2V0U2RrQmluYXJ5UGF0aCIsImFkYiIsImluaXRBYXB0IiwiaW5pdEFhcHQyIiwiaW5pdFppcEFsaWduIiwiaW5pdEJ1bmRsZXRvb2wiLCJiaW5hcmllcyIsImJ1bmRsZXRvb2wiLCJmcyIsIndoaWNoIiwiZXJyIiwiZ2V0QXBpTGV2ZWwiLCJpc0ludGVnZXIiLCJfYXBpTGV2ZWwiLCJzdHJPdXRwdXQiLCJnZXREZXZpY2VQcm9wZXJ0eSIsImFwaUxldmVsIiwicGFyc2VJbnQiLCJ0cmltIiwiY2hhckNvZGVRIiwiY2hhckNvZGVBdCIsImFwaUxldmVsRGlmZiIsImNvZGVuYW1lIiwiU3RyaW5nIiwiZnJvbUNoYXJDb2RlIiwiZ2V0UGxhdGZvcm1WZXJzaW9uIiwidG9Mb3dlckNhc2UiLCJ0b1VwcGVyQ2FzZSIsImlzTmFOIiwibWVzc2FnZSIsImluZm8iLCJpc0RldmljZUNvbm5lY3RlZCIsImRldmljZXMiLCJnZXRDb25uZWN0ZWREZXZpY2VzIiwibWtkaXIiLCJyZW1vdGVQYXRoIiwiaXNWYWxpZENsYXNzIiwiY2xhc3NTdHJpbmciLCJtYXRjaENvbXBvbmVudE5hbWUiLCJyZXNvbHZlTGF1bmNoYWJsZUFjdGl2aXR5IiwicGtnIiwib3B0cyIsInByZWZlckNtZCIsInN0ZG91dCIsIm5hbWVzIiwicGFyc2VMYXVuY2hhYmxlQWN0aXZpdHlOYW1lcyIsInRtcFJvb3QiLCJ0ZW1wRGlyIiwib3BlbkRpciIsInRtcEFwcCIsInB1bGxBcGsiLCJhcGtBY3Rpdml0eSIsInBhY2thZ2VBbmRMYXVuY2hBY3Rpdml0eUZyb21NYW5pZmVzdCIsInN0YWNrIiwid2FybiIsInJpbXJhZiIsInN0ZGVyciIsIm91dHB1dEZvcm1hdCIsIkVYRUNfT1VUUFVUX0ZPUk1BVCIsIkZVTEwiLCJsaW5lIiwic3BsaXQiLCJtYXAiLCJmb3JjZVN0b3AiLCJraWxsUGFja2FnZSIsImNsZWFyIiwiZ3JhbnRBbGxQZXJtaXNzaW9ucyIsImFwayIsInRhcmdldFNkayIsImR1bXBzeXNPdXRwdXQiLCJ0YXJnZXRTZGtWZXJzaW9uVXNpbmdQS0ciLCJ0YXJnZXRTZGtWZXJzaW9uRnJvbU1hbmlmZXN0IiwicmVxdWVzdGVkUGVybWlzc2lvbnMiLCJnZXRSZXFQZXJtaXNzaW9ucyIsImdyYW50ZWRQZXJtaXNzaW9ucyIsImdldEdyYW50ZWRQZXJtaXNzaW9ucyIsInBlcm1pc3Npb25zVG9HcmFudCIsImRpZmZlcmVuY2UiLCJncmFudFBlcm1pc3Npb25zIiwicGVybWlzc2lvbnMiLCJwZXJtIiwic29tZSIsInBhdHRlcm4iLCJ0ZXN0IiwiZ3JhbnRQZXJtaXNzaW9uIiwicGVybWlzc2lvbiIsInJldm9rZVBlcm1pc3Npb24iLCJjbWRPdXRwdXQiLCJleHRyYWN0TWF0Y2hpbmdQZXJtaXNzaW9ucyIsImdldERlbmllZFBlcm1pc3Npb25zIiwiZ2V0TG9jYXRpb25Qcm92aWRlcnMiLCJnZXRTZXR0aW5nIiwicCIsImZpbHRlciIsIkJvb2xlYW4iLCJ0b2dnbGVHUFNMb2NhdGlvblByb3ZpZGVyIiwiZW5hYmxlZCIsInNldFNldHRpbmciLCJzZXRIaWRkZW5BcGlQb2xpY3kiLCJ2YWx1ZSIsImlnbm9yZUVycm9yIiwiayIsInNldERlZmF1bHRIaWRkZW5BcGlQb2xpY3kiLCJzdG9wQW5kQ2xlYXIiLCJhdmFpbGFibGVJTUVzIiwiZ2V0SU1FTGlzdEZyb21PdXRwdXQiLCJlbmFibGVkSU1FcyIsImVuYWJsZUlNRSIsImltZUlkIiwiZGlzYWJsZUlNRSIsInNldElNRSIsImRlZmF1bHRJTUUiLCJlbmdpbmUiLCJrZXlldmVudCIsImtleWNvZGUiLCJjb2RlIiwiaW5wdXRUZXh0IiwidGV4dCIsIm9yaWdpbmFsU3RyIiwiZXNjYXBlZFRleHQiLCJyZXBsYWNlIiwiZXZlcnkiLCJjIiwiaW5jbHVkZXMiLCJxIiwiY2xlYXJUZXh0RmllbGQiLCJpIiwibG9jayIsImlzU2NyZWVuTG9ja2VkIiwidGltZW91dE1zIiwid2FpdEZvckNvbmRpdGlvbiIsIndhaXRNcyIsImludGVydmFsTXMiLCJiYWNrIiwiZ29Ub0hvbWUiLCJnZXRBZGJQYXRoIiwiZ2V0U2NyZWVuT3JpZW50YXRpb24iLCJnZXRTdXJmYWNlT3JpZW50YXRpb24iLCJzZW5kVGVsbmV0Q29tbWFuZCIsImNvbW1hbmQiLCJleGVjRW11Q29uc29sZUNvbW1hbmQiLCJwb3J0IiwiZ2V0RW11bGF0b3JQb3J0IiwiaXNBaXJwbGFuZU1vZGVPbiIsInNldEFpcnBsYW5lTW9kZSIsIm9uIiwiYnJvYWRjYXN0QWlycGxhbmVNb2RlIiwiaXNXaWZpT24iLCJpc0RhdGFPbiIsInNldFdpZmlBbmREYXRhIiwid2lmaSIsImRhdGEiLCJpc0VtdWxhdG9yIiwidXRpbCIsImhhc1ZhbHVlIiwic2V0V2lmaVN0YXRlIiwic2V0RGF0YVN0YXRlIiwiaXNBbmltYXRpb25PbiIsImFuaW1hdG9yX2R1cmF0aW9uX3NjYWxlIiwidHJhbnNpdGlvbl9hbmltYXRpb25fc2NhbGUiLCJ3aW5kb3dfYW5pbWF0aW9uX3NjYWxlIiwic2V0dGluZyIsImxvY2FsUGF0aCIsInBvc2l4IiwiZGlybmFtZSIsImFkYkV4ZWMiLCJwdWxsIiwidGltZW91dCIsInByb2Nlc3NFeGlzdHMiLCJwcm9jZXNzTmFtZSIsImdldFBJRHNCeU5hbWUiLCJnZXRGb3J3YXJkTGlzdCIsImNvbm5lY3Rpb25zIiwiRU9MIiwiZm9yd2FyZFBvcnQiLCJzeXN0ZW1Qb3J0IiwiZGV2aWNlUG9ydCIsInJlbW92ZVBvcnRGb3J3YXJkIiwiZ2V0UmV2ZXJzZUxpc3QiLCJyZXZlcnNlUG9ydCIsInJlbW92ZVBvcnRSZXZlcnNlIiwiZm9yd2FyZEFic3RyYWN0UG9ydCIsInBpbmciLCJpbmRleE9mIiwicmVzdGFydCIsInN0b3BMb2djYXQiLCJyZXN0YXJ0QWRiIiwid2FpdEZvckRldmljZSIsInN0YXJ0TG9nY2F0IiwiX2xvZ2NhdFN0YXJ0dXBQYXJhbXMiLCJsb2djYXQiLCJMb2djYXQiLCJkZWJ1Z1RyYWNlIiwiY2xlYXJEZXZpY2VMb2dzT25TdGFydCIsInN0YXJ0Q2FwdHVyZSIsInN0b3BDYXB0dXJlIiwiZ2V0TG9nY2F0TG9ncyIsImdldExvZ3MiLCJzZXRMb2djYXRMaXN0ZW5lciIsImxpc3RlbmVyIiwicmVtb3ZlTG9nY2F0TGlzdGVuZXIiLCJyZW1vdmVMaXN0ZW5lciIsImxpc3RQcm9jZXNzU3RhdHVzIiwiaXNCb29sZWFuIiwiX2RvZXNQc1N1cHBvcnRBT3B0aW9uIiwiZ2V0TmFtZUJ5UGlkIiwicGlkIiwidGl0bGVNYXRjaCIsImV4ZWMiLCJhbGxUaXRsZXMiLCJwaWRJbmRleCIsIm5hbWVPZmZzZXQiLCJwaWRSZWdleCIsIm1hdGNoZWRMaW5lIiwiaXRlbXMiLCJuYW1lIiwiX2lzUGdyZXBBdmFpbGFibGUiLCJwZ3JlcE91dHB1dCIsIl9jYW5QZ3JlcFVzZUZ1bGxDbWRMaW5lU2VhcmNoIiwiX2lzUGlkb2ZBdmFpbGFibGUiLCJzaGVsbENvbW1hbmQiLCJlc2NhcGVSZWdFeHAiLCJzbGljZSIsIngiLCJwaWRzIiwicHJvY2Vzc05hbWVSZWdleCIsImtpbGxQcm9jZXNzZXNCeU5hbWUiLCJCIiwiYWxsIiwia2lsbFByb2Nlc3NCeVBJRCIsIm5vUHJvY2Vzc0ZsYWciLCJwcml2aWxlZ2VkIiwiZTEiLCJicm9hZGNhc3RQcm9jZXNzRW5kIiwiaW50ZW50IiwiYnJvYWRjYXN0Iiwic3RhcnQiLCJEYXRlIiwibm93Iiwic2xlZXAiLCJlbmRBbmRyb2lkQ292ZXJhZ2UiLCJpbnN0cnVtZW50UHJvYyIsImlzUnVubmluZyIsInN0b3AiLCJpbnN0cnVtZW50IiwiYWN0aXZpdHkiLCJpbnN0cnVtZW50V2l0aCIsInBrZ0FjdGl2aXR5IiwiYW5kcm9pZENvdmVyYWdlIiwiaW5zdHJ1bWVudENsYXNzIiwid2FpdFBrZyIsIndhaXRBY3Rpdml0eSIsInJlc29sdmUiLCJyZWplY3QiLCJkZWZhdWx0QXJncyIsImNvbmNhdCIsIlN1YlByb2Nlc3MiLCJ3YWl0Rm9yQWN0aXZpdHkiLCJwcm9wZXJ0eSIsInZhbCIsInNldERldmljZVByb3BlcnR5IiwicHJvcCIsImdldERldmljZVN5c0xhbmd1YWdlIiwiZ2V0RGV2aWNlU3lzQ291bnRyeSIsImdldERldmljZVN5c0xvY2FsZSIsImdldERldmljZVByb2R1Y3RMYW5ndWFnZSIsImdldERldmljZVByb2R1Y3RDb3VudHJ5IiwiZ2V0RGV2aWNlUHJvZHVjdExvY2FsZSIsImdldE1vZGVsIiwiZ2V0TWFudWZhY3R1cmVyIiwiZ2V0U2NyZWVuU2l6ZSIsInNpemUiLCJnZXRTY3JlZW5EZW5zaXR5IiwiZGVuc2l0eSIsImRlbnNpdHlOdW1iZXIiLCJzZXRIdHRwUHJveHkiLCJwcm94eUhvc3QiLCJwcm94eVBvcnQiLCJwcm94eSIsImlzVW5kZWZpbmVkIiwiaHR0cFByb3h5U2V0dGlucyIsInNldHRpbmdLZXkiLCJzZXR0aW5nVmFsdWUiLCJkZWxldGVIdHRwUHJveHkiLCJuYW1lc3BhY2UiLCJidWdyZXBvcnQiLCJzY3JlZW5yZWNvcmQiLCJkZXN0aW5hdGlvbiIsIm9wdGlvbnMiLCJ2aWRlb1NpemUiLCJiaXRSYXRlIiwidGltZUxpbWl0IiwiYnVnUmVwb3J0IiwiZnVsbENtZCIsInF1b3RlIiwicnVuSW5JbWVDb250ZXh0IiwiaW1lIiwiZm4iLCJvcmlnaW5hbEltZSIsImRlbGF5IiwiZ2V0VGltZVpvbmUiLCJsaXN0RmVhdHVyZXMiLCJfbWVtb2l6ZWRGZWF0dXJlcyIsIm1lbW9pemUiLCJjdXJEZXZpY2VJZCIsImlzU3RyZWFtZWRJbnN0YWxsU3VwcG9ydGVkIiwicHJvdG8iLCJPYmplY3QiLCJnZXRQcm90b3R5cGVPZiIsIl9oZWxwT3V0cHV0IiwiaXNJbmNyZW1lbnRhbEluc3RhbGxTdXBwb3J0ZWQiLCJiaW5hcnkiLCJnZXRWZXJzaW9uIiwiY29tcGFyZVZlcnNpb25zIiwidmVyc2lvbiIsImdldERldmljZUlkbGVXaGl0ZWxpc3QiLCJvdXRwdXQiLCJhZGRUb0RldmljZUlkbGVXaGl0ZWxpc3QiLCJwYWNrYWdlcyIsInBsdXJhbGl6ZSJdLCJzb3VyY2VSb290IjoiLi4vLi4vLi4iLCJzb3VyY2VzIjpbImxpYi90b29scy9hZGItY29tbWFuZHMuanMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGxvZyBmcm9tICcuLi9sb2dnZXIuanMnO1xuaW1wb3J0IHtcbiAgZ2V0SU1FTGlzdEZyb21PdXRwdXQsIGdldFN1cmZhY2VPcmllbnRhdGlvbiwgZXh0cmFjdE1hdGNoaW5nUGVybWlzc2lvbnMsXG4gIHBhcnNlTGF1bmNoYWJsZUFjdGl2aXR5TmFtZXMsIG1hdGNoQ29tcG9uZW50TmFtZSxcbn0gZnJvbSAnLi4vaGVscGVycy5qcyc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgeyBmcywgdXRpbCwgdGVtcERpciB9IGZyb20gJ0BhcHBpdW0vc3VwcG9ydCc7XG5pbXBvcnQgeyBFT0wgfSBmcm9tICdvcyc7XG5pbXBvcnQgTG9nY2F0IGZyb20gJy4uL2xvZ2NhdCc7XG5pbXBvcnQgeyBzbGVlcCwgd2FpdEZvckNvbmRpdGlvbiB9IGZyb20gJ2FzeW5jYm94JztcbmltcG9ydCB7IFN1YlByb2Nlc3MgfSBmcm9tICd0ZWVuX3Byb2Nlc3MnO1xuaW1wb3J0IEIgZnJvbSAnYmx1ZWJpcmQnO1xuXG5jb25zdCBNQVhfU0hFTExfQlVGRkVSX0xFTkdUSCA9IDEwMDA7XG5jb25zdCBOT1RfQ0hBTkdFQUJMRV9QRVJNX0VSUk9SID0gL25vdCBhIGNoYW5nZWFibGUgcGVybWlzc2lvbiB0eXBlL2k7XG5jb25zdCBJR05PUkVEX1BFUk1fRVJST1JTID0gW1xuICBOT1RfQ0hBTkdFQUJMRV9QRVJNX0VSUk9SLFxuICAvVW5rbm93biBwZXJtaXNzaW9uL2ksXG5dO1xuY29uc3QgTUFYX1BHUkVQX1BBVFRFUk5fTEVOID0gMTU7XG5jb25zdCBISURERU5fQVBJX1BPTElDWV9LRVlTID0gW1xuICAnaGlkZGVuX2FwaV9wb2xpY3lfcHJlX3BfYXBwcycsXG4gICdoaWRkZW5fYXBpX3BvbGljeV9wX2FwcHMnLFxuICAnaGlkZGVuX2FwaV9wb2xpY3knXG5dO1xuY29uc3QgUElEX0NPTFVNTl9USVRMRSA9ICdQSUQnO1xuY29uc3QgUFJPQ0VTU19OQU1FX0NPTFVNTl9USVRMRSA9ICdOQU1FJztcbmNvbnN0IFBTX1RJVExFX1BBVFRFUk4gPSBuZXcgUmVnRXhwKGBeKC4qXFxcXGIke1BJRF9DT0xVTU5fVElUTEV9XFxcXGIuKlxcXFxiJHtQUk9DRVNTX05BTUVfQ09MVU1OX1RJVExFfVxcXFxiLiopJGAsICdtJyk7XG4vLyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yNTc5MTQyMy9hZGItc2hlbGwtaW5wdXQtdGV4dC1kb2VzLW5vdC10YWtlLWFtcGVyc2FuZC1jaGFyYWN0ZXIvMjU3OTE0OThcbmNvbnN0IEFEQl9JTlBVVF9FU0NBUEVfUEFUVEVSTiA9IC9bKCk8Pnw7JipcXFxcfl5cIiddL2c7XG5cbmNvbnN0IG1ldGhvZHMgPSB7fTtcblxuLyoqXG4gKiBDcmVhdGVzIGNodW5rcyBmb3IgdGhlIGdpdmVuIGFyZ3VtZW50cyBhbmQgZXhlY3V0ZXMgdGhlbSBpbiBgYWRiIHNoZWxsYC5cbiAqIFRoaXMgaXMgZmFzdGVyIHRoYW4gY2FsbGluZyBgYWRiIHNoZWxsYCBzZXBhcmF0ZWx5IGZvciBlYWNoIGFyZywgaG93ZXZlclxuICogdGhlcmUgaXMgYSBsaW1pdCBmb3IgYSBtYXhpbXVtIGxlbmd0aCBvZiBhIHNpbmdsZSBhZGIgY29tbWFuZC4gdGhhdCBpcyB3aHlcbiAqIHdlIG5lZWQgYWxsIHRoaXMgY29tcGxpY2F0ZWQgbG9naWMuXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gYXJnVHJhbnNmb3JtZXIgQSBmdW5jdGlvbiwgdGhhdCByZWNlaXZlcyBzaW5nbGUgYXJndW1lbnRcbiAqIGZyb20gdGhlIGBhcmdzYCBhcnJheSBhbmQgdHJhbnNmb3JtcyBpdCBpbnRvIGEgc2hlbGwgY29tbWFuZC4gVGhlIHJlc3VsdFxuICogb2YgdGhlIGZ1bmN0aW9uIG11c3QgYmUgYW4gYXJyYXksIHdoZXJlIGVhY2ggaXRlbSBpcyBhIHBhcnQgb2YgYSBzaW5nbGUgY29tbWFuZC5cbiAqIFRoZSBsYXN0IGl0ZW0gb2YgdGhlIGFycmF5IGNvdWxkIGJlICc7Jy4gSWYgdGhpcyBpcyBub3QgYSBzZW1pY29sb24gdGhlbiBpdCBpcyBnb2luZyB0b1xuICogYmUgYWRkZWQgYXV0b21hdGljYWxseS5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyfHN0cmluZz59IGFyZ3MgQXJyYXkgb2YgYXJndW1lbnQgdmFsdWVzIHRvIGNyZWF0ZSBjaHVua3MgZm9yXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgYW55IG9mIHRoZSBjaHVua3MgcmV0dXJucyBub24temVybyBleGl0IGNvZGUgYWZ0ZXIgYmVpbmcgZXhlY3V0ZWRcbiAqL1xubWV0aG9kcy5zaGVsbENodW5rcyA9IGFzeW5jIGZ1bmN0aW9uIHNoZWxsQ2h1bmtzIChhcmdUcmFuc2Zvcm1lciwgYXJncykge1xuICBjb25zdCBjb21tYW5kcyA9IFtdO1xuICBsZXQgY21kQ2h1bmsgPSBbXTtcbiAgZm9yIChjb25zdCBhcmcgb2YgYXJncykge1xuICAgIGNvbnN0IG5leHRDbWQgPSBhcmdUcmFuc2Zvcm1lcihhcmcpO1xuICAgIGlmICghXy5pc0FycmF5KG5leHRDbWQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FyZ3VtZW50IHRyYW5zZm9ybWVyIG11c3QgcmVzdWx0IGluIGFuIGFycmF5Jyk7XG4gICAgfVxuICAgIGlmIChfLmxhc3QobmV4dENtZCkgIT09ICc7Jykge1xuICAgICAgbmV4dENtZC5wdXNoKCc7Jyk7XG4gICAgfVxuICAgIGlmIChuZXh0Q21kLmpvaW4oJyAnKS5sZW5ndGggKyBjbWRDaHVuay5qb2luKCcgJykubGVuZ3RoID49IE1BWF9TSEVMTF9CVUZGRVJfTEVOR1RIKSB7XG4gICAgICBjb21tYW5kcy5wdXNoKGNtZENodW5rKTtcbiAgICAgIGNtZENodW5rID0gW107XG4gICAgfVxuICAgIGNtZENodW5rID0gWy4uLmNtZENodW5rLCAuLi5uZXh0Q21kXTtcbiAgfVxuICBpZiAoIV8uaXNFbXB0eShjbWRDaHVuaykpIHtcbiAgICBjb21tYW5kcy5wdXNoKGNtZENodW5rKTtcbiAgfVxuICBsb2cuZGVidWcoYEdvdCB0aGUgZm9sbG93aW5nIGNvbW1hbmQgY2h1bmtzIHRvIGV4ZWN1dGU6ICR7SlNPTi5zdHJpbmdpZnkoY29tbWFuZHMpfWApO1xuICBsZXQgbGFzdEVycm9yID0gbnVsbDtcbiAgZm9yIChjb25zdCBjbWQgb2YgY29tbWFuZHMpIHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5zaGVsbChjbWQpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxhc3RFcnJvciA9IGU7XG4gICAgfVxuICB9XG4gIGlmIChsYXN0RXJyb3IpIHtcbiAgICB0aHJvdyBsYXN0RXJyb3I7XG4gIH1cbn07XG5cbi8qKlxuICogR2V0IHRoZSBwYXRoIHRvIGFkYiBleGVjdXRhYmxlIGFtZCBhc3NpZ24gaXRcbiAqIHRvIHRoaXMuZXhlY3V0YWJsZS5wYXRoIGFuZCB0aGlzLmJpbmFyaWVzLmFkYiBwcm9wZXJ0aWVzLlxuICpcbiAqIEByZXR1cm4ge0FEQn0gQURCIGluc3RhbmNlLlxuICovXG5tZXRob2RzLmdldEFkYldpdGhDb3JyZWN0QWRiUGF0aCA9IGFzeW5jIGZ1bmN0aW9uIGdldEFkYldpdGhDb3JyZWN0QWRiUGF0aCAoKSB7XG4gIHRoaXMuZXhlY3V0YWJsZS5wYXRoID0gYXdhaXQgdGhpcy5nZXRTZGtCaW5hcnlQYXRoKCdhZGInKTtcbiAgcmV0dXJuIHRoaXMuYWRiO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIGZ1bGwgcGF0aCB0byBhYXB0IHRvb2wgYW5kIGFzc2lnbiBpdCB0b1xuICogdGhpcy5iaW5hcmllcy5hYXB0IHByb3BlcnR5XG4gKi9cbm1ldGhvZHMuaW5pdEFhcHQgPSBhc3luYyBmdW5jdGlvbiBpbml0QWFwdCAoKSB7XG4gIGF3YWl0IHRoaXMuZ2V0U2RrQmluYXJ5UGF0aCgnYWFwdCcpO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIGZ1bGwgcGF0aCB0byBhYXB0MiB0b29sIGFuZCBhc3NpZ24gaXQgdG9cbiAqIHRoaXMuYmluYXJpZXMuYWFwdDIgcHJvcGVydHlcbiAqL1xubWV0aG9kcy5pbml0QWFwdDIgPSBhc3luYyBmdW5jdGlvbiBpbml0QWFwdDIgKCkge1xuICBhd2FpdCB0aGlzLmdldFNka0JpbmFyeVBhdGgoJ2FhcHQyJyk7XG59O1xuXG4vKipcbiAqIEdldCB0aGUgZnVsbCBwYXRoIHRvIHppcGFsaWduIHRvb2wgYW5kIGFzc2lnbiBpdCB0b1xuICogdGhpcy5iaW5hcmllcy56aXBhbGlnbiBwcm9wZXJ0eVxuICovXG5tZXRob2RzLmluaXRaaXBBbGlnbiA9IGFzeW5jIGZ1bmN0aW9uIGluaXRaaXBBbGlnbiAoKSB7XG4gIGF3YWl0IHRoaXMuZ2V0U2RrQmluYXJ5UGF0aCgnemlwYWxpZ24nKTtcbn07XG5cbi8qKlxuICogR2V0IHRoZSBmdWxsIHBhdGggdG8gYnVuZGxldG9vbCBiaW5hcnkgYW5kIGFzc2lnbiBpdCB0b1xuICogdGhpcy5iaW5hcmllcy5idW5kbGV0b29sIHByb3BlcnR5XG4gKi9cbm1ldGhvZHMuaW5pdEJ1bmRsZXRvb2wgPSBhc3luYyBmdW5jdGlvbiBpbml0QnVuZGxldG9vbCAoKSB7XG4gIHRyeSB7XG4gICAgdGhpcy5iaW5hcmllcy5idW5kbGV0b29sID0gYXdhaXQgZnMud2hpY2goJ2J1bmRsZXRvb2wuamFyJyk7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIHRocm93IG5ldyBFcnJvcignYnVuZGxldG9vbC5qYXIgYmluYXJ5IGlzIGV4cGVjdGVkIHRvIGJlIHByZXNlbnQgaW4gUEFUSC4gJyArXG4gICAgICAnVmlzaXQgaHR0cHM6Ly9naXRodWIuY29tL2dvb2dsZS9idW5kbGV0b29sIGZvciBtb3JlIGRldGFpbHMuJyk7XG4gIH1cbn07XG5cbi8qKlxuICogUmV0cmlldmUgdGhlIEFQSSBsZXZlbCBvZiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHJldHVybiB7bnVtYmVyfSBUaGUgQVBJIGxldmVsIGFzIGludGVnZXIgbnVtYmVyLCBmb3IgZXhhbXBsZSAyMSBmb3JcbiAqICAgICAgICAgICAgICAgICAgQW5kcm9pZCBMb2xsaXBvcC4gVGhlIHJlc3VsdCBvZiB0aGlzIG1ldGhvZCBpcyBjYWNoZWQsIHNvIGFsbCB0aGUgZnVydGhlclxuICogY2FsbHMgcmV0dXJuIHRoZSBzYW1lIHZhbHVlIGFzIHRoZSBmaXJzdCBvbmUuXG4gKi9cbm1ldGhvZHMuZ2V0QXBpTGV2ZWwgPSBhc3luYyBmdW5jdGlvbiBnZXRBcGlMZXZlbCAoKSB7XG4gIGlmICghXy5pc0ludGVnZXIodGhpcy5fYXBpTGV2ZWwpKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHN0ck91dHB1dCA9IGF3YWl0IHRoaXMuZ2V0RGV2aWNlUHJvcGVydHkoJ3JvLmJ1aWxkLnZlcnNpb24uc2RrJyk7XG4gICAgICBsZXQgYXBpTGV2ZWwgPSBwYXJzZUludChzdHJPdXRwdXQudHJpbSgpLCAxMCk7XG5cbiAgICAgIC8vIFdvcmthcm91bmQgZm9yIHByZXZpZXcvYmV0YSBwbGF0Zm9ybSBBUEkgbGV2ZWxcbiAgICAgIGNvbnN0IGNoYXJDb2RlUSA9ICdxJy5jaGFyQ29kZUF0KDApO1xuICAgICAgLy8gMjggaXMgdGhlIGZpcnN0IEFQSSBMZXZlbCwgd2hlcmUgQW5kcm9pZCBTREsgc3RhcnRlZCByZXR1cm5pbmcgbGV0dGVycyBpbiByZXNwb25zZSB0byBnZXRQbGF0Zm9ybVZlcnNpb25cbiAgICAgIGNvbnN0IGFwaUxldmVsRGlmZiA9IGFwaUxldmVsIC0gMjg7XG4gICAgICBjb25zdCBjb2RlbmFtZSA9IFN0cmluZy5mcm9tQ2hhckNvZGUoY2hhckNvZGVRICsgYXBpTGV2ZWxEaWZmKTtcbiAgICAgIGlmIChhcGlMZXZlbERpZmYgPj0gMCAmJiAoYXdhaXQgdGhpcy5nZXRQbGF0Zm9ybVZlcnNpb24oKSkudG9Mb3dlckNhc2UoKSA9PT0gY29kZW5hbWUpIHtcbiAgICAgICAgbG9nLmRlYnVnKGBSZWxlYXNlIHZlcnNpb24gaXMgJHtjb2RlbmFtZS50b1VwcGVyQ2FzZSgpfSBidXQgZm91bmQgQVBJIExldmVsICR7YXBpTGV2ZWx9LiBTZXR0aW5nIEFQSSBMZXZlbCB0byAke2FwaUxldmVsICsgMX1gKTtcbiAgICAgICAgYXBpTGV2ZWwrKztcbiAgICAgIH1cblxuICAgICAgdGhpcy5fYXBpTGV2ZWwgPSBhcGlMZXZlbDtcbiAgICAgIGxvZy5kZWJ1ZyhgRGV2aWNlIEFQSSBsZXZlbDogJHt0aGlzLl9hcGlMZXZlbH1gKTtcbiAgICAgIGlmIChpc05hTih0aGlzLl9hcGlMZXZlbCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGUgYWN0dWFsIG91dHB1dCAnJHtzdHJPdXRwdXR9JyBjYW5ub3QgYmUgY29udmVydGVkIHRvIGFuIGludGVnZXJgKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIGdldHRpbmcgZGV2aWNlIEFQSSBsZXZlbC4gT3JpZ2luYWwgZXJyb3I6ICR7ZS5tZXNzYWdlfWApO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdGhpcy5fYXBpTGV2ZWw7XG59O1xuXG4vKipcbiAqIFJldHJpZXZlIHRoZSBwbGF0Zm9ybSB2ZXJzaW9uIG9mIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBwbGF0Zm9ybSB2ZXJzaW9uIGFzIGEgc3RyaW5nLCBmb3IgZXhhbXBsZSAnNS4wJyBmb3JcbiAqIEFuZHJvaWQgTG9sbGlwb3AuXG4gKi9cbm1ldGhvZHMuZ2V0UGxhdGZvcm1WZXJzaW9uID0gYXN5bmMgZnVuY3Rpb24gZ2V0UGxhdGZvcm1WZXJzaW9uICgpIHtcbiAgbG9nLmluZm8oJ0dldHRpbmcgZGV2aWNlIHBsYXRmb3JtIHZlcnNpb24nKTtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5nZXREZXZpY2VQcm9wZXJ0eSgncm8uYnVpbGQudmVyc2lvbi5yZWxlYXNlJyk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIGdldHRpbmcgZGV2aWNlIHBsYXRmb3JtIHZlcnNpb24uIE9yaWdpbmFsIGVycm9yOiAke2UubWVzc2FnZX1gKTtcbiAgfVxufTtcblxuLyoqXG4gKiBWZXJpZnkgd2hldGhlciBhIGRldmljZSBpcyBjb25uZWN0ZWQuXG4gKlxuICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiBhdCBsZWFzdCBvbmUgZGV2aWNlIGlzIHZpc2libGUgdG8gYWRiLlxuICovXG5tZXRob2RzLmlzRGV2aWNlQ29ubmVjdGVkID0gYXN5bmMgZnVuY3Rpb24gaXNEZXZpY2VDb25uZWN0ZWQgKCkge1xuICBsZXQgZGV2aWNlcyA9IGF3YWl0IHRoaXMuZ2V0Q29ubmVjdGVkRGV2aWNlcygpO1xuICByZXR1cm4gZGV2aWNlcy5sZW5ndGggPiAwO1xufTtcblxuLyoqXG4gKiBSZWN1cnNpdmVseSBjcmVhdGUgYSBuZXcgZm9sZGVyIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcmVtb3RlUGF0aCAtIFRoZSBuZXcgcGF0aCB0byBiZSBjcmVhdGVkLlxuICogQHJldHVybiB7c3RyaW5nfSBta2RpciBjb21tYW5kIG91dHB1dC5cbiAqL1xubWV0aG9kcy5ta2RpciA9IGFzeW5jIGZ1bmN0aW9uIG1rZGlyIChyZW1vdGVQYXRoKSB7XG4gIHJldHVybiBhd2FpdCB0aGlzLnNoZWxsKFsnbWtkaXInLCAnLXAnLCByZW1vdGVQYXRoXSk7XG59O1xuXG4vKipcbiAqIFZlcmlmeSB3aGV0aGVyIHRoZSBnaXZlbiBhcmd1bWVudCBpcyBhXG4gKiB2YWxpZCBjbGFzcyBuYW1lLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc1N0cmluZyAtIFRoZSBhY3R1YWwgY2xhc3MgbmFtZSB0byBiZSB2ZXJpZmllZC5cbiAqIEByZXR1cm4gez9BcnJheS48TWF0Y2g+fSBUaGUgcmVzdWx0IG9mIFJlZ2V4cC5leGVjIG9wZXJhdGlvblxuICogICAgICAgICAgICAgICAgICAgICAgICAgIG9yIF9udWxsXyBpZiBubyBtYXRjaGVzIGFyZSBmb3VuZC5cbiAqL1xubWV0aG9kcy5pc1ZhbGlkQ2xhc3MgPSBmdW5jdGlvbiBpc1ZhbGlkQ2xhc3MgKGNsYXNzU3RyaW5nKSB7XG4gIC8vIHNvbWUucGFja2FnZS9zb21lLnBhY2thZ2UuQWN0aXZpdHlcbiAgcmV0dXJuIG1hdGNoQ29tcG9uZW50TmFtZShjbGFzc1N0cmluZyk7XG59O1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFJlc29sdmVBY3Rpdml0eU9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbj99IHByZWZlckNtZCBbdHJ1ZV0gV2hldGhlciB0byBwcmVmZXIgYGNtZGAgdG9vbCB1c2FnZSBmb3JcbiAqIGxhdW5jaGFibGUgYWN0aXZpdHkgbmFtZSBkZXRlY3Rpb24uIEl0IG1pZ2h0IGJlIHVzZWZ1bCB0byBkaXNhYmxlIGl0IGlmXG4gKiBgY21kIHBhY2thZ2UgcmVzb2x2ZS1hY3Rpdml0eWAgcmV0dXJucyAnYW5kcm9pZC9jb20uYW5kcm9pZC5pbnRlcm5hbC5hcHAuUmVzb2x2ZXJBY3Rpdml0eScsXG4gKiB3aGljaCBtZWFucyB0aGUgYXBwIGhhcyBubyBkZWZhdWx0IGhhbmRsZXIgc2V0IGluIHN5c3RlbSBzZXR0aW5ncy5cbiAqIFNlZSBodHRwczovL2dpdGh1Yi5jb20vYXBwaXVtL2FwcGl1bS9pc3N1ZXMvMTcxMjggZm9yIG1vcmUgZGV0YWlscy5cbiAqIFRoaXMgb3B0aW9uIGhhcyBubyBlZmZlY3QgaWYgdGhlIHRhcmdldCBBbmRyb2lkIHZlcnNpb24gaXMgYmVsb3cgMjQgYXMgdGhlcmVcbiAqIHRoZSBjb3JyZXNwb25kaW5nIGBjbWRgIHN1YmNvbW1hbmQgaXMgbm90IGltcGxlbWVudGVkIGFuZCBkdW1wc3lzIHVzYWdlIGlzIHRoZSBvbmx5XG4gKiBwb3NzaWJsZSB3YXkgdG8gZGV0ZWN0IHRoZSBsYXVuY2hhYmxlIGFjdGl2aXR5IG5hbWUuXG4gKi9cblxuLyoqXG4gKiBGZXRjaGVzIHRoZSBmdWxseSBxdWFsaWZpZWQgbmFtZSBvZiB0aGUgbGF1bmNoYWJsZSBhY3Rpdml0eSBmb3IgdGhlXG4gKiBnaXZlbiBwYWNrYWdlLiBJdCBpcyBleHBlY3RlZCB0aGUgcGFja2FnZSBpcyBhbHJlYWR5IGluc3RhbGxlZCBvblxuICogdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwa2cgLSBUaGUgdGFyZ2V0IHBhY2thZ2UgaWRlbnRpZmllclxuICogQHBhcmFtIHtSZXNvbHZlQWN0aXZpdHlPcHRpb25zP30gb3B0c1xuICogQHJldHVybiB7c3RyaW5nfSBGdWxseSBxdWFsaWZpZWQgbmFtZSBvZiB0aGUgbGF1bmNoYWJsZSBhY3Rpdml0eVxuICogQHRocm93cyB7RXJyb3J9IElmIHRoZXJlIHdhcyBhbiBlcnJvciB3aGlsZSByZXNvbHZpbmcgdGhlIGFjdGl2aXR5IG5hbWVcbiAqL1xubWV0aG9kcy5yZXNvbHZlTGF1bmNoYWJsZUFjdGl2aXR5ID0gYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZUxhdW5jaGFibGVBY3Rpdml0eSAocGtnLCBvcHRzID0ge30pIHtcbiAgY29uc3QgeyBwcmVmZXJDbWQgPSB0cnVlIH0gPSBvcHRzO1xuICBpZiAoIXByZWZlckNtZCB8fCBhd2FpdCB0aGlzLmdldEFwaUxldmVsKCkgPCAyNCkge1xuICAgIGNvbnN0IHN0ZG91dCA9IGF3YWl0IHRoaXMuc2hlbGwoWydkdW1wc3lzJywgJ3BhY2thZ2UnLCBwa2ddKTtcbiAgICBjb25zdCBuYW1lcyA9IHBhcnNlTGF1bmNoYWJsZUFjdGl2aXR5TmFtZXMoc3Rkb3V0KTtcbiAgICBpZiAoXy5pc0VtcHR5KG5hbWVzKSkge1xuICAgICAgbG9nLmRlYnVnKHN0ZG91dCk7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byByZXNvbHZlIHRoZSBsYXVuY2hhYmxlIGFjdGl2aXR5IG9mICcke3BrZ30nLiBJcyBpdCBpbnN0YWxsZWQgb24gdGhlIGRldmljZT9gKTtcbiAgICB9XG4gICAgaWYgKG5hbWVzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgcmV0dXJuIG5hbWVzWzBdO1xuICAgIH1cblxuICAgIGNvbnN0IHRtcFJvb3QgPSBhd2FpdCB0ZW1wRGlyLm9wZW5EaXIoKTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgdG1wQXBwID0gYXdhaXQgdGhpcy5wdWxsQXBrKHBrZywgdG1wUm9vdCk7XG4gICAgICBjb25zdCB7YXBrQWN0aXZpdHl9ID0gYXdhaXQgdGhpcy5wYWNrYWdlQW5kTGF1bmNoQWN0aXZpdHlGcm9tTWFuaWZlc3QodG1wQXBwKTtcbiAgICAgIHJldHVybiBhcGtBY3Rpdml0eTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBsb2cuZGVidWcoZS5zdGFjayk7XG4gICAgICBsb2cud2FybihgVW5hYmxlIHRvIHJlc29sdmUgdGhlIGxhdW5jaGFibGUgYWN0aXZpdHkgb2YgJyR7cGtnfScuIGAgK1xuICAgICAgICBgVGhlIHZlcnkgZmlyc3QgbWF0Y2ggb2YgdGhlIGR1bXBzeXMgb3V0cHV0IGlzIGdvaW5nIHRvIGJlIHVzZWQuIGAgK1xuICAgICAgICBgT3JpZ2luYWwgZXJyb3I6ICR7ZS5tZXNzYWdlfWApO1xuICAgICAgcmV0dXJuIG5hbWVzWzBdO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCBmcy5yaW1yYWYodG1wUm9vdCk7XG4gICAgfVxuICB9XG4gIGNvbnN0IHtzdGRvdXQsIHN0ZGVycn0gPSBhd2FpdCB0aGlzLnNoZWxsKFsnY21kJywgJ3BhY2thZ2UnLCAncmVzb2x2ZS1hY3Rpdml0eScsICctLWJyaWVmJywgcGtnXSwge1xuICAgIG91dHB1dEZvcm1hdDogdGhpcy5FWEVDX09VVFBVVF9GT1JNQVQuRlVMTFxuICB9KTtcbiAgZm9yIChjb25zdCBsaW5lIG9mIChzdGRvdXQgfHwgJycpLnNwbGl0KCdcXG4nKS5tYXAoXy50cmltKSkge1xuICAgIGlmICh0aGlzLmlzVmFsaWRDbGFzcyhsaW5lKSkge1xuICAgICAgcmV0dXJuIGxpbmU7XG4gICAgfVxuICB9XG4gIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIHJlc29sdmUgdGhlIGxhdW5jaGFibGUgYWN0aXZpdHkgb2YgJyR7cGtnfScuIE9yaWdpbmFsIGVycm9yOiAke3N0ZGVyciB8fCBzdGRvdXR9YCk7XG59O1xuXG4vKipcbiAqIEZvcmNlIGFwcGxpY2F0aW9uIHRvIHN0b3Agb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwa2cgLSBUaGUgcGFja2FnZSBuYW1lIHRvIGJlIHN0b3BwZWQuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBvdXRwdXQgb2YgdGhlIGNvcnJlc3BvbmRpbmcgYWRiIGNvbW1hbmQuXG4gKi9cbm1ldGhvZHMuZm9yY2VTdG9wID0gYXN5bmMgZnVuY3Rpb24gZm9yY2VTdG9wIChwa2cpIHtcbiAgcmV0dXJuIGF3YWl0IHRoaXMuc2hlbGwoWydhbScsICdmb3JjZS1zdG9wJywgcGtnXSk7XG59O1xuXG4vKlxuICogS2lsbCBhcHBsaWNhdGlvblxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwa2cgLSBUaGUgcGFja2FnZSBuYW1lIHRvIGJlIHN0b3BwZWQuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBvdXRwdXQgb2YgdGhlIGNvcnJlc3BvbmRpbmcgYWRiIGNvbW1hbmQuXG4gKi9cbm1ldGhvZHMua2lsbFBhY2thZ2UgPSBhc3luYyBmdW5jdGlvbiBraWxsUGFja2FnZSAocGtnKSB7XG4gIHJldHVybiBhd2FpdCB0aGlzLnNoZWxsKFsnYW0nLCAna2lsbCcsIHBrZ10pO1xufTtcblxuLyoqXG4gKiBDbGVhciB0aGUgdXNlciBkYXRhIG9mIHRoZSBwYXJ0aWN1bGFyIGFwcGxpY2F0aW9uIG9uIHRoZSBkZXZpY2VcbiAqIHVuZGVyIHRlc3QuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHBrZyAtIFRoZSBwYWNrYWdlIG5hbWUgdG8gYmUgY2xlYXJlZC5cbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIG91dHB1dCBvZiB0aGUgY29ycmVzcG9uZGluZyBhZGIgY29tbWFuZC5cbiAqL1xubWV0aG9kcy5jbGVhciA9IGFzeW5jIGZ1bmN0aW9uIGNsZWFyIChwa2cpIHtcbiAgcmV0dXJuIGF3YWl0IHRoaXMuc2hlbGwoWydwbScsICdjbGVhcicsIHBrZ10pO1xufTtcblxuLyoqXG4gKiBHcmFudCBhbGwgcGVybWlzc2lvbnMgcmVxdWVzdGVkIGJ5IHRoZSBwYXJ0aWN1bGFyIHBhY2thZ2UuXG4gKiBUaGlzIG1ldGhvZCBpcyBvbmx5IHVzZWZ1bCBvbiBBbmRyb2lkIDYuMCsgYW5kIGZvciBhcHBsaWNhdGlvbnNcbiAqIHRoYXQgc3VwcG9ydCBjb21wb25lbnRzLWJhc2VkIHBlcm1pc3Npb25zIHNldHRpbmcuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHBrZyAtIFRoZSBwYWNrYWdlIG5hbWUgdG8gYmUgcHJvY2Vzc2VkLlxuICogQHBhcmFtIHtzdHJpbmd9IGFwayAtIFRoZSBwYXRoIHRvIHRoZSBhY3R1YWwgYXBrIGZpbGUuXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlcmUgd2FzIGFuIGVycm9yIHdoaWxlIGdyYW50aW5nIHBlcm1pc3Npb25zXG4gKi9cbm1ldGhvZHMuZ3JhbnRBbGxQZXJtaXNzaW9ucyA9IGFzeW5jIGZ1bmN0aW9uIGdyYW50QWxsUGVybWlzc2lvbnMgKHBrZywgYXBrKSB7XG4gIGNvbnN0IGFwaUxldmVsID0gYXdhaXQgdGhpcy5nZXRBcGlMZXZlbCgpO1xuICBsZXQgdGFyZ2V0U2RrID0gMDtcbiAgbGV0IGR1bXBzeXNPdXRwdXQgPSBudWxsO1xuICB0cnkge1xuICAgIGlmICghYXBrKSB7XG4gICAgICAvKipcbiAgICAgICAqIElmIGFwayBub3QgcHJvdmlkZWQsIGNvbnNpZGVyaW5nIGFwayBhbHJlYWR5IGluc3RhbGxlZCBvbiB0aGUgZGV2aWNlXG4gICAgICAgKiBhbmQgZmV0Y2hpbmcgdGFyZ2V0U2RrIHVzaW5nIHBhY2thZ2UgbmFtZS5cbiAgICAgICAqL1xuICAgICAgZHVtcHN5c091dHB1dCA9IGF3YWl0IHRoaXMuc2hlbGwoWydkdW1wc3lzJywgJ3BhY2thZ2UnLCBwa2ddKTtcbiAgICAgIHRhcmdldFNkayA9IGF3YWl0IHRoaXMudGFyZ2V0U2RrVmVyc2lvblVzaW5nUEtHKHBrZywgZHVtcHN5c091dHB1dCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRhcmdldFNkayA9IGF3YWl0IHRoaXMudGFyZ2V0U2RrVmVyc2lvbkZyb21NYW5pZmVzdChhcGspO1xuICAgIH1cbiAgfSBjYXRjaCAoZSkge1xuICAgIC8vYXZvaWRpbmcgbG9nZ2luZyBlcnJvciBzdGFjaywgYXMgY2FsbGluZyBsaWJyYXJ5IGZ1bmN0aW9uIHdvdWxkIGhhdmUgbG9nZ2VkXG4gICAgbG9nLndhcm4oYFJhbiBpbnRvIHByb2JsZW0gZ2V0dGluZyB0YXJnZXQgU0RLIHZlcnNpb247IGlnbm9yaW5nLi4uYCk7XG4gIH1cbiAgaWYgKGFwaUxldmVsID49IDIzICYmIHRhcmdldFNkayA+PSAyMykge1xuICAgIC8qKlxuICAgICAqIElmIHRoZSBkZXZpY2UgaXMgcnVubmluZyBBbmRyb2lkIDYuMChBUEkgMjMpIG9yIGhpZ2hlciwgYW5kIHlvdXIgYXBwJ3MgdGFyZ2V0IFNESyBpcyAyMyBvciBoaWdoZXI6XG4gICAgICogVGhlIGFwcCBoYXMgdG8gbGlzdCB0aGUgcGVybWlzc2lvbnMgaW4gdGhlIG1hbmlmZXN0LlxuICAgICAqIHJlZmVyOiBodHRwczovL2RldmVsb3Blci5hbmRyb2lkLmNvbS90cmFpbmluZy9wZXJtaXNzaW9ucy9yZXF1ZXN0aW5nLmh0bWxcbiAgICAgKi9cbiAgICBkdW1wc3lzT3V0cHV0ID0gZHVtcHN5c091dHB1dCB8fCBhd2FpdCB0aGlzLnNoZWxsKFsnZHVtcHN5cycsICdwYWNrYWdlJywgcGtnXSk7XG4gICAgY29uc3QgcmVxdWVzdGVkUGVybWlzc2lvbnMgPSBhd2FpdCB0aGlzLmdldFJlcVBlcm1pc3Npb25zKHBrZywgZHVtcHN5c091dHB1dCk7XG4gICAgY29uc3QgZ3JhbnRlZFBlcm1pc3Npb25zID0gYXdhaXQgdGhpcy5nZXRHcmFudGVkUGVybWlzc2lvbnMocGtnLCBkdW1wc3lzT3V0cHV0KTtcbiAgICBjb25zdCBwZXJtaXNzaW9uc1RvR3JhbnQgPSBfLmRpZmZlcmVuY2UocmVxdWVzdGVkUGVybWlzc2lvbnMsIGdyYW50ZWRQZXJtaXNzaW9ucyk7XG4gICAgaWYgKF8uaXNFbXB0eShwZXJtaXNzaW9uc1RvR3JhbnQpKSB7XG4gICAgICBsb2cuaW5mbyhgJHtwa2d9IGNvbnRhaW5zIG5vIHBlcm1pc3Npb25zIGF2YWlsYWJsZSBmb3IgZ3JhbnRpbmdgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXdhaXQgdGhpcy5ncmFudFBlcm1pc3Npb25zKHBrZywgcGVybWlzc2lvbnNUb0dyYW50KTtcbiAgICB9XG4gIH1cbn07XG5cbi8qKlxuICogR3JhbnQgbXVsdGlwbGUgcGVybWlzc2lvbnMgZm9yIHRoZSBwYXJ0aWN1bGFyIHBhY2thZ2UuXG4gKiBUaGlzIGNhbGwgaXMgbW9yZSBwZXJmb3JtYW50IHRoYW4gYGdyYW50UGVybWlzc2lvbmAgb25lLCBzaW5jZSBpdCBjb21iaW5lc1xuICogbXVsdGlwbGUgYGFkYiBzaGVsbGAgY2FsbHMgaW50byBhIHNpbmdsZSBjb21tYW5kLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwa2cgLSBUaGUgcGFja2FnZSBuYW1lIHRvIGJlIHByb2Nlc3NlZC5cbiAqIEBwYXJhbSB7QXJyYXk8c3RyaW5nPn0gcGVybWlzc2lvbnMgLSBUaGUgbGlzdCBvZiBwZXJtaXNzaW9ucyB0byBiZSBncmFudGVkLlxuICogQHRocm93cyB7RXJyb3J9IElmIHRoZXJlIHdhcyBhbiBlcnJvciB3aGlsZSBjaGFuZ2luZyBwZXJtaXNzaW9ucy5cbiAqL1xubWV0aG9kcy5ncmFudFBlcm1pc3Npb25zID0gYXN5bmMgZnVuY3Rpb24gZ3JhbnRQZXJtaXNzaW9ucyAocGtnLCBwZXJtaXNzaW9ucykge1xuICAvLyBBcyBpdCBjb25zdW1lcyBtb3JlIHRpbWUgZm9yIGdyYW50aW5nIGVhY2ggcGVybWlzc2lvbixcbiAgLy8gdHJ5aW5nIHRvIGdyYW50IGFsbCBwZXJtaXNzaW9uIGJ5IGZvcm1pbmcgZXF1aXZhbGVudCBjb21tYW5kLlxuICAvLyBBbHNvLCBpdCBpcyBuZWNlc3NhcnkgdG8gc3BsaXQgbG9uZyBjb21tYW5kcyBpbnRvIGNodW5rcywgc2luY2UgdGhlIG1heGltdW0gbGVuZ3RoIG9mXG4gIC8vIGFkYiBzaGVsbCBidWZmZXIgaXMgbGltaXRlZFxuICBsb2cuZGVidWcoYEdyYW50aW5nIHBlcm1pc3Npb25zICR7SlNPTi5zdHJpbmdpZnkocGVybWlzc2lvbnMpfSB0byAnJHtwa2d9J2ApO1xuICB0cnkge1xuICAgIGF3YWl0IHRoaXMuc2hlbGxDaHVua3MoKHBlcm0pID0+IFsncG0nLCAnZ3JhbnQnLCBwa2csIHBlcm1dLCBwZXJtaXNzaW9ucyk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoIUlHTk9SRURfUEVSTV9FUlJPUlMuc29tZSgocGF0dGVybikgPT4gcGF0dGVybi50ZXN0KGUuc3RkZXJyIHx8IGUubWVzc2FnZSkpKSB7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBHcmFudCBzaW5nbGUgcGVybWlzc2lvbiBmb3IgdGhlIHBhcnRpY3VsYXIgcGFja2FnZS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcGtnIC0gVGhlIHBhY2thZ2UgbmFtZSB0byBiZSBwcm9jZXNzZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gcGVybWlzc2lvbiAtIFRoZSBmdWxsIG5hbWUgb2YgdGhlIHBlcm1pc3Npb24gdG8gYmUgZ3JhbnRlZC5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGVyZSB3YXMgYW4gZXJyb3Igd2hpbGUgY2hhbmdpbmcgcGVybWlzc2lvbnMuXG4gKi9cbm1ldGhvZHMuZ3JhbnRQZXJtaXNzaW9uID0gYXN5bmMgZnVuY3Rpb24gZ3JhbnRQZXJtaXNzaW9uIChwa2csIHBlcm1pc3Npb24pIHtcbiAgdHJ5IHtcbiAgICBhd2FpdCB0aGlzLnNoZWxsKFsncG0nLCAnZ3JhbnQnLCBwa2csIHBlcm1pc3Npb25dKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmICghTk9UX0NIQU5HRUFCTEVfUEVSTV9FUlJPUi50ZXN0KGUuc3RkZXJyIHx8IGUubWVzc2FnZSkpIHtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIFJldm9rZSBzaW5nbGUgcGVybWlzc2lvbiBmcm9tIHRoZSBwYXJ0aWN1bGFyIHBhY2thZ2UuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHBrZyAtIFRoZSBwYWNrYWdlIG5hbWUgdG8gYmUgcHJvY2Vzc2VkLlxuICogQHBhcmFtIHtzdHJpbmd9IHBlcm1pc3Npb24gLSBUaGUgZnVsbCBuYW1lIG9mIHRoZSBwZXJtaXNzaW9uIHRvIGJlIHJldm9rZWQuXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlcmUgd2FzIGFuIGVycm9yIHdoaWxlIGNoYW5naW5nIHBlcm1pc3Npb25zLlxuICovXG5tZXRob2RzLnJldm9rZVBlcm1pc3Npb24gPSBhc3luYyBmdW5jdGlvbiByZXZva2VQZXJtaXNzaW9uIChwa2csIHBlcm1pc3Npb24pIHtcbiAgdHJ5IHtcbiAgICBhd2FpdCB0aGlzLnNoZWxsKFsncG0nLCAncmV2b2tlJywgcGtnLCBwZXJtaXNzaW9uXSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoIU5PVF9DSEFOR0VBQkxFX1BFUk1fRVJST1IudGVzdChlLnN0ZGVyciB8fCBlLm1lc3NhZ2UpKSB7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBSZXRyaWV2ZSB0aGUgbGlzdCBvZiBncmFudGVkIHBlcm1pc3Npb25zIGZvciB0aGUgcGFydGljdWxhciBwYWNrYWdlLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwa2cgLSBUaGUgcGFja2FnZSBuYW1lIHRvIGJlIHByb2Nlc3NlZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjbWRPdXRwdXQgW251bGxdIC0gT3B0aW9uYWwgcGFyYW1ldGVyIGNvbnRhaW5pbmcgY29tbWFuZCBvdXRwdXQgb2ZcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX2R1bXBzeXMgcGFja2FnZV8gY29tbWFuZC4gSXQgbWF5IHNwZWVkIHVwIHRoZSBtZXRob2QgZXhlY3V0aW9uLlxuICogQHJldHVybiB7QXJyYXk8U3RyaW5nPn0gVGhlIGxpc3Qgb2YgZ3JhbnRlZCBwZXJtaXNzaW9ucyBvciBhbiBlbXB0eSBsaXN0LlxuICogQHRocm93cyB7RXJyb3J9IElmIHRoZXJlIHdhcyBhbiBlcnJvciB3aGlsZSBjaGFuZ2luZyBwZXJtaXNzaW9ucy5cbiAqL1xubWV0aG9kcy5nZXRHcmFudGVkUGVybWlzc2lvbnMgPSBhc3luYyBmdW5jdGlvbiBnZXRHcmFudGVkUGVybWlzc2lvbnMgKHBrZywgY21kT3V0cHV0ID0gbnVsbCkge1xuICBsb2cuZGVidWcoJ1JldHJpZXZpbmcgZ3JhbnRlZCBwZXJtaXNzaW9ucycpO1xuICBjb25zdCBzdGRvdXQgPSBjbWRPdXRwdXQgfHwgYXdhaXQgdGhpcy5zaGVsbChbJ2R1bXBzeXMnLCAncGFja2FnZScsIHBrZ10pO1xuICByZXR1cm4gZXh0cmFjdE1hdGNoaW5nUGVybWlzc2lvbnMoc3Rkb3V0LCBbJ2luc3RhbGwnLCAncnVudGltZSddLCB0cnVlKTtcbn07XG5cbi8qKlxuICogUmV0cmlldmUgdGhlIGxpc3Qgb2YgZGVuaWVkIHBlcm1pc3Npb25zIGZvciB0aGUgcGFydGljdWxhciBwYWNrYWdlLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwa2cgLSBUaGUgcGFja2FnZSBuYW1lIHRvIGJlIHByb2Nlc3NlZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjbWRPdXRwdXQgW251bGxdIC0gT3B0aW9uYWwgcGFyYW1ldGVyIGNvbnRhaW5pbmcgY29tbWFuZCBvdXRwdXQgb2ZcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX2R1bXBzeXMgcGFja2FnZV8gY29tbWFuZC4gSXQgbWF5IHNwZWVkIHVwIHRoZSBtZXRob2QgZXhlY3V0aW9uLlxuICogQHJldHVybiB7QXJyYXk8U3RyaW5nPn0gVGhlIGxpc3Qgb2YgZGVuaWVkIHBlcm1pc3Npb25zIG9yIGFuIGVtcHR5IGxpc3QuXG4gKi9cbm1ldGhvZHMuZ2V0RGVuaWVkUGVybWlzc2lvbnMgPSBhc3luYyBmdW5jdGlvbiBnZXREZW5pZWRQZXJtaXNzaW9ucyAocGtnLCBjbWRPdXRwdXQgPSBudWxsKSB7XG4gIGxvZy5kZWJ1ZygnUmV0cmlldmluZyBkZW5pZWQgcGVybWlzc2lvbnMnKTtcbiAgY29uc3Qgc3Rkb3V0ID0gY21kT3V0cHV0IHx8IGF3YWl0IHRoaXMuc2hlbGwoWydkdW1wc3lzJywgJ3BhY2thZ2UnLCBwa2ddKTtcbiAgcmV0dXJuIGV4dHJhY3RNYXRjaGluZ1Blcm1pc3Npb25zKHN0ZG91dCwgWydpbnN0YWxsJywgJ3J1bnRpbWUnXSwgZmFsc2UpO1xufTtcblxuLyoqXG4gKiBSZXRyaWV2ZSB0aGUgbGlzdCBvZiByZXF1ZXN0ZWQgcGVybWlzc2lvbnMgZm9yIHRoZSBwYXJ0aWN1bGFyIHBhY2thZ2UuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHBrZyAtIFRoZSBwYWNrYWdlIG5hbWUgdG8gYmUgcHJvY2Vzc2VkLlxuICogQHBhcmFtIHtzdHJpbmd9IGNtZE91dHB1dCBbbnVsbF0gLSBPcHRpb25hbCBwYXJhbWV0ZXIgY29udGFpbmluZyBjb21tYW5kIG91dHB1dCBvZlxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfZHVtcHN5cyBwYWNrYWdlXyBjb21tYW5kLiBJdCBtYXkgc3BlZWQgdXAgdGhlIG1ldGhvZCBleGVjdXRpb24uXG4gKiBAcmV0dXJuIHtBcnJheTxTdHJpbmc+fSBUaGUgbGlzdCBvZiByZXF1ZXN0ZWQgcGVybWlzc2lvbnMgb3IgYW4gZW1wdHkgbGlzdC5cbiAqL1xubWV0aG9kcy5nZXRSZXFQZXJtaXNzaW9ucyA9IGFzeW5jIGZ1bmN0aW9uIGdldFJlcVBlcm1pc3Npb25zIChwa2csIGNtZE91dHB1dCA9IG51bGwpIHtcbiAgbG9nLmRlYnVnKCdSZXRyaWV2aW5nIHJlcXVlc3RlZCBwZXJtaXNzaW9ucycpO1xuICBjb25zdCBzdGRvdXQgPSBjbWRPdXRwdXQgfHwgYXdhaXQgdGhpcy5zaGVsbChbJ2R1bXBzeXMnLCAncGFja2FnZScsIHBrZ10pO1xuICByZXR1cm4gZXh0cmFjdE1hdGNoaW5nUGVybWlzc2lvbnMoc3Rkb3V0LCBbJ3JlcXVlc3RlZCddKTtcbn07XG5cbi8qKlxuICogUmV0cmlldmUgdGhlIGxpc3Qgb2YgbG9jYXRpb24gcHJvdmlkZXJzIGZvciB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHJldHVybiB7QXJyYXkuPFN0cmluZz59IFRoZSBsaXN0IG9mIGF2YWlsYWJsZSBsb2NhdGlvbiBwcm92aWRlcnMgb3IgYW4gZW1wdHkgbGlzdC5cbiAqL1xubWV0aG9kcy5nZXRMb2NhdGlvblByb3ZpZGVycyA9IGFzeW5jIGZ1bmN0aW9uIGdldExvY2F0aW9uUHJvdmlkZXJzICgpIHtcbiAgbGV0IHN0ZG91dCA9IGF3YWl0IHRoaXMuZ2V0U2V0dGluZygnc2VjdXJlJywgJ2xvY2F0aW9uX3Byb3ZpZGVyc19hbGxvd2VkJyk7XG4gIHJldHVybiBzdGRvdXQudHJpbSgpLnNwbGl0KCcsJylcbiAgICAubWFwKChwKSA9PiBwLnRyaW0oKSlcbiAgICAuZmlsdGVyKEJvb2xlYW4pO1xufTtcblxuLyoqXG4gKiBUb2dnbGUgdGhlIHN0YXRlIG9mIEdQUyBsb2NhdGlvbiBwcm92aWRlci5cbiAqXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGVuYWJsZWQgLSBXaGV0aGVyIHRvIGVuYWJsZSAodHJ1ZSkgb3IgZGlzYWJsZSAoZmFsc2UpIHRoZSBHUFMgcHJvdmlkZXIuXG4gKi9cbm1ldGhvZHMudG9nZ2xlR1BTTG9jYXRpb25Qcm92aWRlciA9IGFzeW5jIGZ1bmN0aW9uIHRvZ2dsZUdQU0xvY2F0aW9uUHJvdmlkZXIgKGVuYWJsZWQpIHtcbiAgYXdhaXQgdGhpcy5zZXRTZXR0aW5nKCdzZWN1cmUnLCAnbG9jYXRpb25fcHJvdmlkZXJzX2FsbG93ZWQnLCBgJHtlbmFibGVkID8gJysnIDogJy0nfWdwc2ApO1xufTtcblxuLyoqXG4gKiBTZXQgaGlkZGVuIGFwaSBwb2xpY3kgdG8gbWFuYWdlIGFjY2VzcyB0byBub24tU0RLIEFQSXMuXG4gKiBodHRwczovL2RldmVsb3Blci5hbmRyb2lkLmNvbS9wcmV2aWV3L3Jlc3RyaWN0aW9ucy1ub24tc2RrLWludGVyZmFjZXNcbiAqXG4gKiBAcGFyYW0ge251bWJlcnxzdHJpbmd9IHZhbHVlIC0gVGhlIEFQSSBlbmZvcmNlbWVudCBwb2xpY3kuXG4gKiAgICAgRm9yIEFuZHJvaWQgUFxuICogICAgIDA6IERpc2FibGUgbm9uLVNESyBBUEkgdXNhZ2UgZGV0ZWN0aW9uLiBUaGlzIHdpbGwgYWxzbyBkaXNhYmxlIGxvZ2dpbmcsIGFuZCBhbHNvIGJyZWFrIHRoZSBzdHJpY3QgbW9kZSBBUEksXG4gKiAgICAgICAgZGV0ZWN0Tm9uU2RrQXBpVXNhZ2UoKS4gTm90IHJlY29tbWVuZGVkLlxuICogICAgIDE6IFwiSnVzdCB3YXJuXCIgLSBwZXJtaXQgYWNjZXNzIHRvIGFsbCBub24tU0RLIEFQSXMsIGJ1dCBrZWVwIHdhcm5pbmdzIGluIHRoZSBsb2cuXG4gKiAgICAgICAgVGhlIHN0cmljdCBtb2RlIEFQSSB3aWxsIGtlZXAgd29ya2luZy5cbiAqICAgICAyOiBEaXNhbGxvdyB1c2FnZSBvZiBkYXJrIGdyZXkgYW5kIGJsYWNrIGxpc3RlZCBBUElzLlxuICogICAgIDM6IERpc2FsbG93IHVzYWdlIG9mIGJsYWNrbGlzdGVkIEFQSXMsIGJ1dCBhbGxvdyB1c2FnZSBvZiBkYXJrIGdyZXkgbGlzdGVkIEFQSXMuXG4gKlxuICogICAgIEZvciBBbmRyb2lkIFFcbiAqICAgICBodHRwczovL2RldmVsb3Blci5hbmRyb2lkLmNvbS9wcmV2aWV3L25vbi1zZGstcSNlbmFibGUtbm9uLXNkay1hY2Nlc3NcbiAqICAgICAwOiBEaXNhYmxlIGFsbCBkZXRlY3Rpb24gb2Ygbm9uLVNESyBpbnRlcmZhY2VzLiBVc2luZyB0aGlzIHNldHRpbmcgZGlzYWJsZXMgYWxsIGxvZyBtZXNzYWdlcyBmb3Igbm9uLVNESyBpbnRlcmZhY2UgdXNhZ2VcbiAqICAgICAgICBhbmQgcHJldmVudHMgeW91IGZyb20gdGVzdGluZyB5b3VyIGFwcCB1c2luZyB0aGUgU3RyaWN0TW9kZSBBUEkuIFRoaXMgc2V0dGluZyBpcyBub3QgcmVjb21tZW5kZWQuXG4gKiAgICAgMTogRW5hYmxlIGFjY2VzcyB0byBhbGwgbm9uLVNESyBpbnRlcmZhY2VzLCBidXQgcHJpbnQgbG9nIG1lc3NhZ2VzIHdpdGggd2FybmluZ3MgZm9yIGFueSBub24tU0RLIGludGVyZmFjZSB1c2FnZS5cbiAqICAgICAgICBVc2luZyB0aGlzIHNldHRpbmcgYWxzbyBhbGxvd3MgeW91IHRvIHRlc3QgeW91ciBhcHAgdXNpbmcgdGhlIFN0cmljdE1vZGUgQVBJLlxuICogICAgIDI6IERpc2FsbG93IHVzYWdlIG9mIG5vbi1TREsgaW50ZXJmYWNlcyB0aGF0IGJlbG9uZyB0byBlaXRoZXIgdGhlIGJsYWNrIGxpc3RcbiAqICAgICAgICBvciB0byBhIHJlc3RyaWN0ZWQgZ3JleWxpc3QgZm9yIHlvdXIgdGFyZ2V0IEFQSSBsZXZlbC5cbiAqXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGlnbm9yZUVycm9yIFtmYWxzZV0gV2hldGhlciB0byBpZ25vcmUgYW4gZXhjZXB0aW9uIGluICdhZGIgc2hlbGwgc2V0dGluZ3MgcHV0IGdsb2JhbCcgY29tbWFuZFxuICogQHRocm93cyB7ZXJyb3J9IElmIHRoZXJlIHdhcyBhbiBlcnJvciBhbmQgaWdub3JlRXJyb3Igd2FzIHRydWUgd2hpbGUgZXhlY3V0aW5nICdhZGIgc2hlbGwgc2V0dGluZ3MgcHV0IGdsb2JhbCdcbiAqICAgICAgICAgICAgICAgICBjb21tYW5kIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqL1xubWV0aG9kcy5zZXRIaWRkZW5BcGlQb2xpY3kgPSBhc3luYyBmdW5jdGlvbiBzZXRIaWRkZW5BcGlQb2xpY3kgKHZhbHVlLCBpZ25vcmVFcnJvciA9IGZhbHNlKSB7XG4gIHRyeSB7XG4gICAgYXdhaXQgdGhpcy5zaGVsbChISURERU5fQVBJX1BPTElDWV9LRVlTLm1hcCgoaykgPT4gYHNldHRpbmdzIHB1dCBnbG9iYWwgJHtrfSAke3ZhbHVlfWApLmpvaW4oJzsnKSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoIWlnbm9yZUVycm9yKSB7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgICBsb2cuaW5mbyhgRmFpbGVkIHRvIHNldCBzZXR0aW5nIGtleXMgJyR7SElEREVOX0FQSV9QT0xJQ1lfS0VZU30nIHRvICcke3ZhbHVlfScuIE9yaWdpbmFsIGVycm9yOiAke2UubWVzc2FnZX1gKTtcbiAgfVxufTtcblxuLyoqXG4gKiBSZXNldCBhY2Nlc3MgdG8gbm9uLVNESyBBUElzIHRvIGl0cyBkZWZhdWx0IHNldHRpbmcuXG4gKiBodHRwczovL2RldmVsb3Blci5hbmRyb2lkLmNvbS9wcmV2aWV3L3Jlc3RyaWN0aW9ucy1ub24tc2RrLWludGVyZmFjZXNcbiAqXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGlnbm9yZUVycm9yIFtmYWxzZV0gV2hldGhlciB0byBpZ25vcmUgYW4gZXhjZXB0aW9uIGluICdhZGIgc2hlbGwgc2V0dGluZ3MgZGVsZXRlIGdsb2JhbCcgY29tbWFuZFxuICogQHRocm93cyB7ZXJyb3J9IElmIHRoZXJlIHdhcyBhbiBlcnJvciBhbmQgaWdub3JlRXJyb3Igd2FzIHRydWUgd2hpbGUgZXhlY3V0aW5nICdhZGIgc2hlbGwgc2V0dGluZ3MgZGVsZXRlIGdsb2JhbCdcbiAqICAgICAgICAgICAgICAgICBjb21tYW5kIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqL1xubWV0aG9kcy5zZXREZWZhdWx0SGlkZGVuQXBpUG9saWN5ID0gYXN5bmMgZnVuY3Rpb24gc2V0RGVmYXVsdEhpZGRlbkFwaVBvbGljeSAoaWdub3JlRXJyb3IgPSBmYWxzZSkge1xuICB0cnkge1xuICAgIGF3YWl0IHRoaXMuc2hlbGwoSElEREVOX0FQSV9QT0xJQ1lfS0VZUy5tYXAoKGspID0+IGBzZXR0aW5ncyBkZWxldGUgZ2xvYmFsICR7a31gKS5qb2luKCc7JykpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKCFpZ25vcmVFcnJvcikge1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gICAgbG9nLmluZm8oYEZhaWxlZCB0byBkZWxldGUga2V5cyAnJHtISURERU5fQVBJX1BPTElDWV9LRVlTfScuIE9yaWdpbmFsIGVycm9yOiAke2UubWVzc2FnZX1gKTtcbiAgfVxufTtcblxuLyoqXG4gKiBTdG9wIHRoZSBwYXJ0aWN1bGFyIHBhY2thZ2UgaWYgaXQgaXMgcnVubmluZyBhbmQgY2xlYXJzIGl0cyBhcHBsaWNhdGlvbiBkYXRhLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwa2cgLSBUaGUgcGFja2FnZSBuYW1lIHRvIGJlIHByb2Nlc3NlZC5cbiAqL1xubWV0aG9kcy5zdG9wQW5kQ2xlYXIgPSBhc3luYyBmdW5jdGlvbiBzdG9wQW5kQ2xlYXIgKHBrZykge1xuICB0cnkge1xuICAgIGF3YWl0IHRoaXMuZm9yY2VTdG9wKHBrZyk7XG4gICAgYXdhaXQgdGhpcy5jbGVhcihwa2cpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3Qgc3RvcCBhbmQgY2xlYXIgJHtwa2d9LiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gIH1cbn07XG5cbi8qKlxuICogUmV0cmlldmUgdGhlIGxpc3Qgb2YgYXZhaWxhYmxlIGlucHV0IG1ldGhvZHMgKElNRXMpIGZvciB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHJldHVybiB7QXJyYXkuPFN0cmluZz59IFRoZSBsaXN0IG9mIElNRSBuYW1lcyBvciBhbiBlbXB0eSBsaXN0LlxuICovXG5tZXRob2RzLmF2YWlsYWJsZUlNRXMgPSBhc3luYyBmdW5jdGlvbiBhdmFpbGFibGVJTUVzICgpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gZ2V0SU1FTGlzdEZyb21PdXRwdXQoYXdhaXQgdGhpcy5zaGVsbChbJ2ltZScsICdsaXN0JywgJy1hJ10pKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgZ2V0dGluZyBhdmFpbGFibGUgSU1FJ3MuIE9yaWdpbmFsIGVycm9yOiAke2UubWVzc2FnZX1gKTtcbiAgfVxufTtcblxuLyoqXG4gKiBSZXRyaWV2ZSB0aGUgbGlzdCBvZiBlbmFibGVkIGlucHV0IG1ldGhvZHMgKElNRXMpIGZvciB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHJldHVybiB7QXJyYXkuPFN0cmluZz59IFRoZSBsaXN0IG9mIGVuYWJsZWQgSU1FIG5hbWVzIG9yIGFuIGVtcHR5IGxpc3QuXG4gKi9cbm1ldGhvZHMuZW5hYmxlZElNRXMgPSBhc3luYyBmdW5jdGlvbiBlbmFibGVkSU1FcyAoKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGdldElNRUxpc3RGcm9tT3V0cHV0KGF3YWl0IHRoaXMuc2hlbGwoWydpbWUnLCAnbGlzdCddKSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIGdldHRpbmcgZW5hYmxlZCBJTUUncy4gT3JpZ2luYWwgZXJyb3I6ICR7ZS5tZXNzYWdlfWApO1xuICB9XG59O1xuXG4vKipcbiAqIEVuYWJsZSB0aGUgcGFydGljdWxhciBpbnB1dCBtZXRob2Qgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBpbWVJZCAtIE9uZSBvZiBleGlzdGluZyBJTUUgaWRzLlxuICovXG5tZXRob2RzLmVuYWJsZUlNRSA9IGFzeW5jIGZ1bmN0aW9uIGVuYWJsZUlNRSAoaW1lSWQpIHtcbiAgYXdhaXQgdGhpcy5zaGVsbChbJ2ltZScsICdlbmFibGUnLCBpbWVJZF0pO1xufTtcblxuLyoqXG4gKiBEaXNhYmxlIHRoZSBwYXJ0aWN1bGFyIGlucHV0IG1ldGhvZCBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGltZUlkIC0gT25lIG9mIGV4aXN0aW5nIElNRSBpZHMuXG4gKi9cbm1ldGhvZHMuZGlzYWJsZUlNRSA9IGFzeW5jIGZ1bmN0aW9uIGRpc2FibGVJTUUgKGltZUlkKSB7XG4gIGF3YWl0IHRoaXMuc2hlbGwoWydpbWUnLCAnZGlzYWJsZScsIGltZUlkXSk7XG59O1xuXG4vKipcbiAqIFNldCB0aGUgcGFydGljdWxhciBpbnB1dCBtZXRob2Qgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBpbWVJZCAtIE9uZSBvZiBleGlzdGluZyBJTUUgaWRzLlxuICovXG5tZXRob2RzLnNldElNRSA9IGFzeW5jIGZ1bmN0aW9uIHNldElNRSAoaW1lSWQpIHtcbiAgYXdhaXQgdGhpcy5zaGVsbChbJ2ltZScsICdzZXQnLCBpbWVJZF0pO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIGRlZmF1bHQgaW5wdXQgbWV0aG9kIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqXG4gKiBAcmV0dXJuIHs/c3RyaW5nfSBUaGUgbmFtZSBvZiB0aGUgZGVmYXVsdCBpbnB1dCBtZXRob2RcbiAqL1xubWV0aG9kcy5kZWZhdWx0SU1FID0gYXN5bmMgZnVuY3Rpb24gZGVmYXVsdElNRSAoKSB7XG4gIHRyeSB7XG4gICAgbGV0IGVuZ2luZSA9IGF3YWl0IHRoaXMuZ2V0U2V0dGluZygnc2VjdXJlJywgJ2RlZmF1bHRfaW5wdXRfbWV0aG9kJyk7XG4gICAgaWYgKGVuZ2luZSA9PT0gJ251bGwnKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIGVuZ2luZS50cmltKCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIGdldHRpbmcgZGVmYXVsdCBJTUUuIE9yaWdpbmFsIGVycm9yOiAke2UubWVzc2FnZX1gKTtcbiAgfVxufTtcblxuLyoqXG4gKiBTZW5kIHRoZSBwYXJ0aWN1bGFyIGtleWNvZGUgdG8gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0ga2V5Y29kZSAtIFRoZSBhY3R1YWwga2V5IGNvZGUgdG8gYmUgc2VudC5cbiAqL1xubWV0aG9kcy5rZXlldmVudCA9IGFzeW5jIGZ1bmN0aW9uIGtleWV2ZW50IChrZXljb2RlKSB7XG4gIC8vIGtleWNvZGUgbXVzdCBiZSBhbiBpbnQuXG4gIGxldCBjb2RlID0gcGFyc2VJbnQoa2V5Y29kZSwgMTApO1xuICBhd2FpdCB0aGlzLnNoZWxsKFsnaW5wdXQnLCAna2V5ZXZlbnQnLCBjb2RlXSk7XG59O1xuXG4vKipcbiAqIFNlbmQgdGhlIHBhcnRpY3VsYXIgdGV4dCBvciBhIG51bWJlciB0byB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKiBUaGUgdGV4dCBnZXRzIHByb3Blcmx5IGVzY2FwZWQgYmVmb3JlIGJlaW5nIHBhc3NlZCB0byBBREIuXG4gKiBOb29wIGlmIHRoZSB0ZXh0IGlzIGVtcHR5LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gdGV4dCAtIFRoZSBhY3R1YWwgdGV4dCB0byBiZSBzZW50LlxuICogQHRocm93cyB7RXJyb3J9IElmIGl0IGlzIGltcG9zc2libGUgdG8gZXNjYXBlIHRoZSBnaXZlbiBzdHJpbmdcbiAqL1xubWV0aG9kcy5pbnB1dFRleHQgPSBhc3luYyBmdW5jdGlvbiBpbnB1dFRleHQgKHRleHQpIHtcbiAgaWYgKHRleHQgPT09ICcnKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3Qgb3JpZ2luYWxTdHIgPSBgJHt0ZXh0fWA7XG4gIGNvbnN0IGVzY2FwZWRUZXh0ID0gb3JpZ2luYWxTdHIucmVwbGFjZSgvXFwkL2csICdcXFxcJCcpLnJlcGxhY2UoLyAvZywgJyVzJyk7XG4gIGxldCBhcmdzID0gWydpbnB1dCcsICd0ZXh0Jywgb3JpZ2luYWxTdHJdO1xuICBpZiAoZXNjYXBlZFRleHQgIT09IG9yaWdpbmFsU3RyIHx8IEFEQl9JTlBVVF9FU0NBUEVfUEFUVEVSTi50ZXN0KG9yaWdpbmFsU3RyKSkge1xuICAgIGlmIChfLmV2ZXJ5KFsnXCInLCBgJ2BdLCAoYykgPT4gb3JpZ2luYWxTdHIuaW5jbHVkZXMoYykpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBEaWQgbm90IGtub3cgaG93IHRvIGVzY2FwZSBhIHN0cmluZyB0aGF0IGNvbnRhaW5zIGJvdGggdHlwZXMgb2YgcXVvdGVzIChcIiBhbmQgJylgXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCBxID0gb3JpZ2luYWxTdHIuaW5jbHVkZXMoJ1wiJykgPyBgJ2AgOiAnXCInO1xuICAgIGFyZ3MgPSBbYGlucHV0IHRleHQgJHtxfSR7ZXNjYXBlZFRleHR9JHtxfWBdO1xuICB9XG4gIGF3YWl0IHRoaXMuc2hlbGwoYXJncyk7XG59O1xuXG4vKipcbiAqIENsZWFyIHRoZSBhY3RpdmUgdGV4dCBmaWVsZCBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QgYnkgc2VuZGluZ1xuICogc3BlY2lhbCBrZXlldmVudHMgdG8gaXQuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IGxlbmd0aCBbMTAwXSAtIFRoZSBtYXhpbXVtIGxlbmd0aCBvZiB0aGUgdGV4dCBpbiB0aGUgZmllbGQgdG8gYmUgY2xlYXJlZC5cbiAqL1xubWV0aG9kcy5jbGVhclRleHRGaWVsZCA9IGFzeW5jIGZ1bmN0aW9uIGNsZWFyVGV4dEZpZWxkIChsZW5ndGggPSAxMDApIHtcbiAgLy8gYXNzdW1lcyB0aGF0IHRoZSBFZGl0VGV4dCBmaWVsZCBhbHJlYWR5IGhhcyBmb2N1c1xuICBsb2cuZGVidWcoYENsZWFyaW5nIHVwIHRvICR7bGVuZ3RofSBjaGFyYWN0ZXJzYCk7XG4gIGlmIChsZW5ndGggPT09IDApIHtcbiAgICByZXR1cm47XG4gIH1cbiAgbGV0IGFyZ3MgPSBbJ2lucHV0JywgJ2tleWV2ZW50J107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAvLyB3ZSBjYW5ub3Qga25vdyB3aGVyZSB0aGUgY3Vyc29yIGlzIGluIHRoZSB0ZXh0IGZpZWxkLCBzbyBkZWxldGUgYm90aCBiZWZvcmVcbiAgICAvLyBhbmQgYWZ0ZXIgc28gdGhhdCB3ZSBnZXQgcmlkIG9mIGV2ZXJ5dGhpbmdcbiAgICAvLyBodHRwczovL2RldmVsb3Blci5hbmRyb2lkLmNvbS9yZWZlcmVuY2UvYW5kcm9pZC92aWV3L0tleUV2ZW50Lmh0bWwjS0VZQ09ERV9ERUxcbiAgICAvLyBodHRwczovL2RldmVsb3Blci5hbmRyb2lkLmNvbS9yZWZlcmVuY2UvYW5kcm9pZC92aWV3L0tleUV2ZW50Lmh0bWwjS0VZQ09ERV9GT1JXQVJEX0RFTFxuICAgIGFyZ3MucHVzaCgnNjcnLCAnMTEyJyk7XG4gIH1cbiAgYXdhaXQgdGhpcy5zaGVsbChhcmdzKTtcbn07XG5cbi8qKlxuICogU2VuZCB0aGUgc3BlY2lhbCBrZXljb2RlIHRvIHRoZSBkZXZpY2UgdW5kZXIgdGVzdCBpbiBvcmRlciB0byBsb2NrIGl0LlxuICovXG5tZXRob2RzLmxvY2sgPSBhc3luYyBmdW5jdGlvbiBsb2NrICgpIHtcbiAgaWYgKGF3YWl0IHRoaXMuaXNTY3JlZW5Mb2NrZWQoKSkge1xuICAgIGxvZy5kZWJ1ZygnU2NyZWVuIGlzIGFscmVhZHkgbG9ja2VkLiBEb2luZyBub3RoaW5nLicpO1xuICAgIHJldHVybjtcbiAgfVxuICBsb2cuZGVidWcoJ1ByZXNzaW5nIHRoZSBLRVlDT0RFX1BPV0VSIGJ1dHRvbiB0byBsb2NrIHNjcmVlbicpO1xuICBhd2FpdCB0aGlzLmtleWV2ZW50KDI2KTtcblxuICBjb25zdCB0aW1lb3V0TXMgPSA1MDAwO1xuICB0cnkge1xuICAgIGF3YWl0IHdhaXRGb3JDb25kaXRpb24oYXN5bmMgKCkgPT4gYXdhaXQgdGhpcy5pc1NjcmVlbkxvY2tlZCgpLCB7XG4gICAgICB3YWl0TXM6IHRpbWVvdXRNcyxcbiAgICAgIGludGVydmFsTXM6IDUwMCxcbiAgICB9KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVGhlIGRldmljZSBzY3JlZW4gaXMgc3RpbGwgbG9ja2VkIGFmdGVyICR7dGltZW91dE1zfW1zIHRpbWVvdXRgKTtcbiAgfVxufTtcblxuLyoqXG4gKiBTZW5kIHRoZSBzcGVjaWFsIGtleWNvZGUgdG8gdGhlIGRldmljZSB1bmRlciB0ZXN0IGluIG9yZGVyIHRvIGVtdWxhdGVcbiAqIEJhY2sgYnV0dG9uIHRhcC5cbiAqL1xubWV0aG9kcy5iYWNrID0gYXN5bmMgZnVuY3Rpb24gYmFjayAoKSB7XG4gIGxvZy5kZWJ1ZygnUHJlc3NpbmcgdGhlIEJBQ0sgYnV0dG9uJyk7XG4gIGF3YWl0IHRoaXMua2V5ZXZlbnQoNCk7XG59O1xuXG4vKipcbiAqIFNlbmQgdGhlIHNwZWNpYWwga2V5Y29kZSB0byB0aGUgZGV2aWNlIHVuZGVyIHRlc3QgaW4gb3JkZXIgdG8gZW11bGF0ZVxuICogSG9tZSBidXR0b24gdGFwLlxuICovXG5tZXRob2RzLmdvVG9Ib21lID0gYXN5bmMgZnVuY3Rpb24gZ29Ub0hvbWUgKCkge1xuICBsb2cuZGVidWcoJ1ByZXNzaW5nIHRoZSBIT01FIGJ1dHRvbicpO1xuICBhd2FpdCB0aGlzLmtleWV2ZW50KDMpO1xufTtcblxuLyoqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IHRoZSBhY3R1YWwgcGF0aCB0byBhZGIgZXhlY3V0YWJsZS5cbiAqL1xubWV0aG9kcy5nZXRBZGJQYXRoID0gZnVuY3Rpb24gZ2V0QWRiUGF0aCAoKSB7XG4gIHJldHVybiB0aGlzLmV4ZWN1dGFibGUucGF0aDtcbn07XG5cbi8qKlxuICogUmV0cmlldmUgY3VycmVudCBzY3JlZW4gb3JpZW50YXRpb24gb2YgdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEByZXR1cm4ge251bWJlcn0gVGhlIGN1cnJlbnQgb3JpZW50YXRpb24gZW5jb2RlZCBhcyBhbiBpbnRlZ2VyIG51bWJlci5cbiAqL1xubWV0aG9kcy5nZXRTY3JlZW5PcmllbnRhdGlvbiA9IGFzeW5jIGZ1bmN0aW9uIGdldFNjcmVlbk9yaWVudGF0aW9uICgpIHtcbiAgbGV0IHN0ZG91dCA9IGF3YWl0IHRoaXMuc2hlbGwoWydkdW1wc3lzJywgJ2lucHV0J10pO1xuICByZXR1cm4gZ2V0U3VyZmFjZU9yaWVudGF0aW9uKHN0ZG91dCk7XG59O1xuXG4vKipcbiAqIFNlbmQgYW4gYXJiaXRyYXJ5IFRlbG5ldCBjb21tYW5kIHRvIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gY29tbWFuZCAtIFRoZSBjb21tYW5kIHRvIGJlIHNlbnQuXG4gKlxuICogQHJldHVybiB7c3RyaW5nfSBUaGUgYWN0dWFsIG91dHB1dCBvZiB0aGUgZ2l2ZW4gY29tbWFuZC5cbiAqL1xubWV0aG9kcy5zZW5kVGVsbmV0Q29tbWFuZCA9IGFzeW5jIGZ1bmN0aW9uIHNlbmRUZWxuZXRDb21tYW5kIChjb21tYW5kKSB7XG4gIHJldHVybiBhd2FpdCB0aGlzLmV4ZWNFbXVDb25zb2xlQ29tbWFuZChjb21tYW5kLCB7cG9ydDogYXdhaXQgdGhpcy5nZXRFbXVsYXRvclBvcnQoKX0pO1xufTtcblxuLyoqXG4gKiBDaGVjayB0aGUgc3RhdGUgb2YgQWlycGxhbmUgbW9kZSBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiBBaXJwbGFuZSBtb2RlIGlzIGVuYWJsZWQuXG4gKi9cbm1ldGhvZHMuaXNBaXJwbGFuZU1vZGVPbiA9IGFzeW5jIGZ1bmN0aW9uIGlzQWlycGxhbmVNb2RlT24gKCkge1xuICBsZXQgc3Rkb3V0ID0gYXdhaXQgdGhpcy5nZXRTZXR0aW5nKCdnbG9iYWwnLCAnYWlycGxhbmVfbW9kZV9vbicpO1xuICByZXR1cm4gcGFyc2VJbnQoc3Rkb3V0LCAxMCkgIT09IDA7XG59O1xuXG4vKipcbiAqIENoYW5nZSB0aGUgc3RhdGUgb2YgQWlycGxhbmUgbW9kZSBpbiBTZXR0aW5ncyBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHBhcmFtIHtib29sZWFufSBvbiAtIFRydWUgdG8gZW5hYmxlIHRoZSBBaXJwbGFuZSBtb2RlIGluIFNldHRpbmdzIGFuZCBmYWxzZSB0byBkaXNhYmxlIGl0LlxuICovXG5tZXRob2RzLnNldEFpcnBsYW5lTW9kZSA9IGFzeW5jIGZ1bmN0aW9uIHNldEFpcnBsYW5lTW9kZSAob24pIHtcbiAgYXdhaXQgdGhpcy5zZXRTZXR0aW5nKCdnbG9iYWwnLCAnYWlycGxhbmVfbW9kZV9vbicsIG9uID8gMSA6IDApO1xufTtcblxuLyoqXG4gKiBCcm9hZGNhc3QgdGhlIHN0YXRlIG9mIEFpcnBsYW5lIG1vZGUgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICogVGhpcyBtZXRob2Qgc2hvdWxkIGJlIGNhbGxlZCBhZnRlciB7QGxpbmsgI3NldEFpcnBsYW5lTW9kZX0sIG90aGVyd2lzZVxuICogdGhlIG1vZGUgY2hhbmdlIGlzIG5vdCBnb2luZyB0byBiZSBhcHBsaWVkIGZvciB0aGUgZGV2aWNlLlxuICpcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gb24gLSBUcnVlIHRvIGJyb2FkY2FzdCBlbmFibGUgYW5kIGZhbHNlIHRvIGJyb2FkY2FzdCBkaXNhYmxlLlxuICovXG5tZXRob2RzLmJyb2FkY2FzdEFpcnBsYW5lTW9kZSA9IGFzeW5jIGZ1bmN0aW9uIGJyb2FkY2FzdEFpcnBsYW5lTW9kZSAob24pIHtcbiAgYXdhaXQgdGhpcy5zaGVsbChbXG4gICAgJ2FtJywgJ2Jyb2FkY2FzdCcsXG4gICAgJy1hJywgJ2FuZHJvaWQuaW50ZW50LmFjdGlvbi5BSVJQTEFORV9NT0RFJyxcbiAgICAnLS1leicsICdzdGF0ZScsIG9uID8gJ3RydWUnIDogJ2ZhbHNlJ1xuICBdKTtcbn07XG5cbi8qKlxuICogQ2hlY2sgdGhlIHN0YXRlIG9mIFdpRmkgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgV2lGaSBpcyBlbmFibGVkLlxuICovXG5tZXRob2RzLmlzV2lmaU9uID0gYXN5bmMgZnVuY3Rpb24gaXNXaWZpT24gKCkge1xuICBsZXQgc3Rkb3V0ID0gYXdhaXQgdGhpcy5nZXRTZXR0aW5nKCdnbG9iYWwnLCAnd2lmaV9vbicpO1xuICByZXR1cm4gKHBhcnNlSW50KHN0ZG91dCwgMTApICE9PSAwKTtcbn07XG5cbi8qKlxuICogQ2hlY2sgdGhlIHN0YXRlIG9mIERhdGEgdHJhbnNmZXIgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgRGF0YSB0cmFuc2ZlciBpcyBlbmFibGVkLlxuICovXG5tZXRob2RzLmlzRGF0YU9uID0gYXN5bmMgZnVuY3Rpb24gaXNEYXRhT24gKCkge1xuICBsZXQgc3Rkb3V0ID0gYXdhaXQgdGhpcy5nZXRTZXR0aW5nKCdnbG9iYWwnLCAnbW9iaWxlX2RhdGEnKTtcbiAgcmV0dXJuIChwYXJzZUludChzdGRvdXQsIDEwKSAhPT0gMCk7XG59O1xuXG4vKipcbiAqIENoYW5nZSB0aGUgc3RhdGUgb2YgV2lGaSBhbmQvb3IgRGF0YSB0cmFuc2ZlciBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHBhcmFtIHtib29sZWFufSB3aWZpIC0gVHJ1ZSB0byBlbmFibGUgYW5kIGZhbHNlIHRvIGRpc2FibGUgV2lGaS5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gZGF0YSAtIFRydWUgdG8gZW5hYmxlIGFuZCBmYWxzZSB0byBkaXNhYmxlIERhdGEgdHJhbnNmZXIuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGlzRW11bGF0b3IgW2ZhbHNlXSAtIFNldCBpdCB0byB0cnVlIGlmIHRoZSBkZXZpY2UgdW5kZXIgdGVzdFxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpcyBhbiBlbXVsYXRvciByYXRoZXIgdGhhbiBhIHJlYWwgZGV2aWNlLlxuICovXG5tZXRob2RzLnNldFdpZmlBbmREYXRhID0gYXN5bmMgZnVuY3Rpb24gc2V0V2lmaUFuZERhdGEgKHt3aWZpLCBkYXRhfSwgaXNFbXVsYXRvciA9IGZhbHNlKSB7XG4gIGlmICh1dGlsLmhhc1ZhbHVlKHdpZmkpKSB7XG4gICAgYXdhaXQgdGhpcy5zZXRXaWZpU3RhdGUod2lmaSwgaXNFbXVsYXRvcik7XG4gIH1cbiAgaWYgKHV0aWwuaGFzVmFsdWUoZGF0YSkpIHtcbiAgICBhd2FpdCB0aGlzLnNldERhdGFTdGF0ZShkYXRhLCBpc0VtdWxhdG9yKTtcbiAgfVxufTtcblxuLyoqXG4gKiBDaGVjayB0aGUgc3RhdGUgb2YgYW5pbWF0aW9uIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIGF0IGxlYXN0IG9uZSBvZiBhbmltYXRpb24gc2NhbGUgc2V0dGluZ3NcbiAqICAgICAgICAgICAgICAgICAgIGlzIG5vdCBlcXVhbCB0byAnMC4wJy5cbiAqL1xubWV0aG9kcy5pc0FuaW1hdGlvbk9uID0gYXN5bmMgZnVuY3Rpb24gaXNBbmltYXRpb25PbiAoKSB7XG4gIGxldCBhbmltYXRvcl9kdXJhdGlvbl9zY2FsZSA9IGF3YWl0IHRoaXMuZ2V0U2V0dGluZygnZ2xvYmFsJywgJ2FuaW1hdG9yX2R1cmF0aW9uX3NjYWxlJyk7XG4gIGxldCB0cmFuc2l0aW9uX2FuaW1hdGlvbl9zY2FsZSA9IGF3YWl0IHRoaXMuZ2V0U2V0dGluZygnZ2xvYmFsJywgJ3RyYW5zaXRpb25fYW5pbWF0aW9uX3NjYWxlJyk7XG4gIGxldCB3aW5kb3dfYW5pbWF0aW9uX3NjYWxlID0gYXdhaXQgdGhpcy5nZXRTZXR0aW5nKCdnbG9iYWwnLCAnd2luZG93X2FuaW1hdGlvbl9zY2FsZScpO1xuICByZXR1cm4gXy5zb21lKFthbmltYXRvcl9kdXJhdGlvbl9zY2FsZSwgdHJhbnNpdGlvbl9hbmltYXRpb25fc2NhbGUsIHdpbmRvd19hbmltYXRpb25fc2NhbGVdLFxuICAgICAgICAgICAgICAgIChzZXR0aW5nKSA9PiBzZXR0aW5nICE9PSAnMC4wJyk7XG59O1xuXG4vKipcbiAqIEZvcmNlZnVsbHkgcmVjdXJzaXZlbHkgcmVtb3ZlIGEgcGF0aCBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKiBCZSBjYXJlZnVsIHdoaWxlIGNhbGxpbmcgdGhpcyBtZXRob2QuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHBhdGggLSBUaGUgcGF0aCB0byBiZSByZW1vdmVkIHJlY3Vyc2l2ZWx5LlxuICovXG5tZXRob2RzLnJpbXJhZiA9IGFzeW5jIGZ1bmN0aW9uIHJpbXJhZiAocGF0aCkge1xuICBhd2FpdCB0aGlzLnNoZWxsKFsncm0nLCAnLXJmJywgcGF0aF0pO1xufTtcblxuLyoqXG4gKiBTZW5kIGEgZmlsZSB0byB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGxvY2FsUGF0aCAtIFRoZSBwYXRoIHRvIHRoZSBmaWxlIG9uIHRoZSBsb2NhbCBmaWxlIHN5c3RlbS5cbiAqIEBwYXJhbSB7c3RyaW5nfSByZW1vdGVQYXRoIC0gVGhlIGRlc3RpbmF0aW9uIHBhdGggb24gdGhlIHJlbW90ZSBkZXZpY2UuXG4gKiBAcGFyYW0ge29iamVjdH0gb3B0cyAtIEFkZGl0aW9uYWwgb3B0aW9ucyBtYXBwaW5nLiBTZWVcbiAqICAgICAgICAgICAgICAgICAgICAgICAgaHR0cHM6Ly9naXRodWIuY29tL2FwcGl1bS9ub2RlLXRlZW5fcHJvY2VzcyxcbiAqICAgICAgICAgICAgICAgICAgICAgICAgX2V4ZWNfIG1ldGhvZCBvcHRpb25zLCBmb3IgbW9yZSBpbmZvcm1hdGlvbiBhYm91dCBhdmFpbGFibGVcbiAqICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5cbiAqL1xubWV0aG9kcy5wdXNoID0gYXN5bmMgZnVuY3Rpb24gcHVzaCAobG9jYWxQYXRoLCByZW1vdGVQYXRoLCBvcHRzKSB7XG4gIGF3YWl0IHRoaXMubWtkaXIocGF0aC5wb3NpeC5kaXJuYW1lKHJlbW90ZVBhdGgpKTtcbiAgYXdhaXQgdGhpcy5hZGJFeGVjKFsncHVzaCcsIGxvY2FsUGF0aCwgcmVtb3RlUGF0aF0sIG9wdHMpO1xufTtcblxuLyoqXG4gKiBSZWNlaXZlIGEgZmlsZSBmcm9tIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcmVtb3RlUGF0aCAtIFRoZSBzb3VyY2UgcGF0aCBvbiB0aGUgcmVtb3RlIGRldmljZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBsb2NhbFBhdGggLSBUaGUgZGVzdGluYXRpb24gcGF0aCB0byB0aGUgZmlsZSBvbiB0aGUgbG9jYWwgZmlsZSBzeXN0ZW0uXG4gKiBAcGFyYW0ge29iamVjdH0gb3B0cyAtIEFkZGl0aW9uYWwgb3B0aW9ucyBtYXBwaW5nLiBTZWVcbiAqICAgICAgICAgICAgICAgICAgICAgICAgaHR0cHM6Ly9naXRodWIuY29tL2FwcGl1bS9ub2RlLXRlZW5fcHJvY2VzcyxcbiAqICAgICAgICAgICAgICAgICAgICAgICAgX2V4ZWNfIG1ldGhvZCBvcHRpb25zLCBmb3IgbW9yZSBpbmZvcm1hdGlvbiBhYm91dCBhdmFpbGFibGVcbiAqICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5cbiAqL1xubWV0aG9kcy5wdWxsID0gYXN5bmMgZnVuY3Rpb24gcHVsbCAocmVtb3RlUGF0aCwgbG9jYWxQYXRoLCBvcHRzID0ge30pIHtcbiAgLy8gcHVsbCBmb2xkZXIgY2FuIHRha2UgbW9yZSB0aW1lLCBpbmNyZWFzaW5nIHRpbWUgb3V0IHRvIDYwIHNlY3NcbiAgYXdhaXQgdGhpcy5hZGJFeGVjKFsncHVsbCcsIHJlbW90ZVBhdGgsIGxvY2FsUGF0aF0sIHsuLi5vcHRzLCB0aW1lb3V0OiBvcHRzLnRpbWVvdXQgPz8gNjAwMDB9KTtcbn07XG5cbi8qKlxuICogQ2hlY2sgd2hldGhlciB0aGUgcHJvY2VzcyB3aXRoIHRoZSBwYXJ0aWN1bGFyIG5hbWUgaXMgcnVubmluZyBvbiB0aGUgZGV2aWNlXG4gKiB1bmRlciB0ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9jZXNzTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9jZXNzIHRvIGJlIGNoZWNrZWQuXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIHRoZSBnaXZlbiBwcm9jZXNzIGlzIHJ1bm5pbmcuXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIGdpdmVuIHByb2Nlc3MgbmFtZSBpcyBub3QgYSB2YWxpZCBjbGFzcyBuYW1lLlxuICovXG5tZXRob2RzLnByb2Nlc3NFeGlzdHMgPSBhc3luYyBmdW5jdGlvbiBwcm9jZXNzRXhpc3RzIChwcm9jZXNzTmFtZSkge1xuICByZXR1cm4gIV8uaXNFbXB0eShhd2FpdCB0aGlzLmdldFBJRHNCeU5hbWUocHJvY2Vzc05hbWUpKTtcbn07XG5cbi8qKlxuICogR2V0IFRDUCBwb3J0IGZvcndhcmRpbmcgd2l0aCBhZGIgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICogQHJldHVybiB7QXJyYXkuPFN0cmluZz59IFRoZSBvdXRwdXQgb2YgdGhlIGNvcnJlc3BvbmRpbmcgYWRiIGNvbW1hbmQuIEFuIGFycmF5IGNvbnRhaW5zIGVhY2ggZm9yd2FyZGluZyBsaW5lIG9mIG91dHB1dFxuICovXG5tZXRob2RzLmdldEZvcndhcmRMaXN0ID0gYXN5bmMgZnVuY3Rpb24gZ2V0Rm9yd2FyZExpc3QgKCkge1xuICBsb2cuZGVidWcoYExpc3QgZm9yd2FyZGluZyBwb3J0c2ApO1xuICBjb25zdCBjb25uZWN0aW9ucyA9IGF3YWl0IHRoaXMuYWRiRXhlYyhbJ2ZvcndhcmQnLCAnLS1saXN0J10pO1xuICByZXR1cm4gY29ubmVjdGlvbnMuc3BsaXQoRU9MKS5maWx0ZXIoKGxpbmUpID0+IEJvb2xlYW4obGluZS50cmltKCkpKTtcbn07XG5cbi8qKlxuICogU2V0dXAgVENQIHBvcnQgZm9yd2FyZGluZyB3aXRoIGFkYiBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBzeXN0ZW1Qb3J0IC0gVGhlIG51bWJlciBvZiB0aGUgbG9jYWwgc3lzdGVtIHBvcnQuXG4gKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGRldmljZVBvcnQgLSBUaGUgbnVtYmVyIG9mIHRoZSByZW1vdGUgZGV2aWNlIHBvcnQuXG4gKi9cbm1ldGhvZHMuZm9yd2FyZFBvcnQgPSBhc3luYyBmdW5jdGlvbiBmb3J3YXJkUG9ydCAoc3lzdGVtUG9ydCwgZGV2aWNlUG9ydCkge1xuICBsb2cuZGVidWcoYEZvcndhcmRpbmcgc3lzdGVtOiAke3N5c3RlbVBvcnR9IHRvIGRldmljZTogJHtkZXZpY2VQb3J0fWApO1xuICBhd2FpdCB0aGlzLmFkYkV4ZWMoWydmb3J3YXJkJywgYHRjcDoke3N5c3RlbVBvcnR9YCwgYHRjcDoke2RldmljZVBvcnR9YF0pO1xufTtcblxuLyoqXG4gKiBSZW1vdmUgVENQIHBvcnQgZm9yd2FyZGluZyB3aXRoIGFkYiBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuIFRoZSBmb3J3YXJkaW5nXG4gKiBmb3IgdGhlIGdpdmVuIHBvcnQgc2hvdWxkIGJlIHNldHVwIHdpdGgge0BsaW5rICNmb3J3YXJkUG9ydH0gZmlyc3QuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBzeXN0ZW1Qb3J0IC0gVGhlIG51bWJlciBvZiB0aGUgbG9jYWwgc3lzdGVtIHBvcnRcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvIHJlbW92ZSBmb3J3YXJkaW5nIG9uLlxuICovXG5tZXRob2RzLnJlbW92ZVBvcnRGb3J3YXJkID0gYXN5bmMgZnVuY3Rpb24gcmVtb3ZlUG9ydEZvcndhcmQgKHN5c3RlbVBvcnQpIHtcbiAgbG9nLmRlYnVnKGBSZW1vdmluZyBmb3J3YXJkZWQgcG9ydCBzb2NrZXQgY29ubmVjdGlvbjogJHtzeXN0ZW1Qb3J0fSBgKTtcbiAgYXdhaXQgdGhpcy5hZGJFeGVjKFsnZm9yd2FyZCcsIGAtLXJlbW92ZWAsIGB0Y3A6JHtzeXN0ZW1Qb3J0fWBdKTtcbn07XG5cbi8qKlxuICogR2V0IFRDUCBwb3J0IGZvcndhcmRpbmcgd2l0aCBhZGIgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICogQHJldHVybiB7QXJyYXkuPFN0cmluZz59IFRoZSBvdXRwdXQgb2YgdGhlIGNvcnJlc3BvbmRpbmcgYWRiIGNvbW1hbmQuIEFuIGFycmF5IGNvbnRhaW5zIGVhY2ggZm9yd2FyZGluZyBsaW5lIG9mIG91dHB1dFxuICovXG5tZXRob2RzLmdldFJldmVyc2VMaXN0ID0gYXN5bmMgZnVuY3Rpb24gZ2V0UmV2ZXJzZUxpc3QgKCkge1xuICBsb2cuZGVidWcoYExpc3QgcmV2ZXJzZSBmb3J3YXJkaW5nIHBvcnRzYCk7XG4gIGNvbnN0IGNvbm5lY3Rpb25zID0gYXdhaXQgdGhpcy5hZGJFeGVjKFsncmV2ZXJzZScsICctLWxpc3QnXSk7XG4gIHJldHVybiBjb25uZWN0aW9ucy5zcGxpdChFT0wpLmZpbHRlcigobGluZSkgPT4gQm9vbGVhbihsaW5lLnRyaW0oKSkpO1xufTtcblxuLyoqXG4gKiBTZXR1cCBUQ1AgcG9ydCBmb3J3YXJkaW5nIHdpdGggYWRiIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqIE9ubHkgYXZhaWxhYmxlIGZvciBBUEkgMjErLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gZGV2aWNlUG9ydCAtIFRoZSBudW1iZXIgb2YgdGhlIHJlbW90ZSBkZXZpY2UgcG9ydC5cbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gc3lzdGVtUG9ydCAtIFRoZSBudW1iZXIgb2YgdGhlIGxvY2FsIHN5c3RlbSBwb3J0LlxuICovXG5tZXRob2RzLnJldmVyc2VQb3J0ID0gYXN5bmMgZnVuY3Rpb24gcmV2ZXJzZVBvcnQgKGRldmljZVBvcnQsIHN5c3RlbVBvcnQpIHtcbiAgbG9nLmRlYnVnKGBGb3J3YXJkaW5nIGRldmljZTogJHtkZXZpY2VQb3J0fSB0byBzeXN0ZW06ICR7c3lzdGVtUG9ydH1gKTtcbiAgYXdhaXQgdGhpcy5hZGJFeGVjKFsncmV2ZXJzZScsIGB0Y3A6JHtkZXZpY2VQb3J0fWAsIGB0Y3A6JHtzeXN0ZW1Qb3J0fWBdKTtcbn07XG5cbi8qKlxuICogUmVtb3ZlIFRDUCBwb3J0IGZvcndhcmRpbmcgd2l0aCBhZGIgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LiBUaGUgZm9yd2FyZGluZ1xuICogZm9yIHRoZSBnaXZlbiBwb3J0IHNob3VsZCBiZSBzZXR1cCB3aXRoIHtAbGluayAjZm9yd2FyZFBvcnR9IGZpcnN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gZGV2aWNlUG9ydCAtIFRoZSBudW1iZXIgb2YgdGhlIHJlbW90ZSBkZXZpY2UgcG9ydFxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG8gcmVtb3ZlIGZvcndhcmRpbmcgb24uXG4gKi9cbm1ldGhvZHMucmVtb3ZlUG9ydFJldmVyc2UgPSBhc3luYyBmdW5jdGlvbiByZW1vdmVQb3J0UmV2ZXJzZSAoZGV2aWNlUG9ydCkge1xuICBsb2cuZGVidWcoYFJlbW92aW5nIHJldmVyc2UgZm9yd2FyZGVkIHBvcnQgc29ja2V0IGNvbm5lY3Rpb246ICR7ZGV2aWNlUG9ydH0gYCk7XG4gIGF3YWl0IHRoaXMuYWRiRXhlYyhbJ3JldmVyc2UnLCBgLS1yZW1vdmVgLCBgdGNwOiR7ZGV2aWNlUG9ydH1gXSk7XG59O1xuXG4vKipcbiAqIFNldHVwIFRDUCBwb3J0IGZvcndhcmRpbmcgd2l0aCBhZGIgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LiBUaGUgZGlmZmVyZW5jZVxuICogYmV0d2VlbiB7QGxpbmsgI2ZvcndhcmRQb3J0fSBpcyB0aGF0IHRoaXMgbWV0aG9kIGRvZXMgc2V0dXAgZm9yIGFuIGFic3RyYWN0XG4gKiBsb2NhbCBwb3J0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gc3lzdGVtUG9ydCAtIFRoZSBudW1iZXIgb2YgdGhlIGxvY2FsIHN5c3RlbSBwb3J0LlxuICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBkZXZpY2VQb3J0IC0gVGhlIG51bWJlciBvZiB0aGUgcmVtb3RlIGRldmljZSBwb3J0LlxuICovXG5tZXRob2RzLmZvcndhcmRBYnN0cmFjdFBvcnQgPSBhc3luYyBmdW5jdGlvbiBmb3J3YXJkQWJzdHJhY3RQb3J0IChzeXN0ZW1Qb3J0LCBkZXZpY2VQb3J0KSB7XG4gIGxvZy5kZWJ1ZyhgRm9yd2FyZGluZyBzeXN0ZW06ICR7c3lzdGVtUG9ydH0gdG8gYWJzdHJhY3QgZGV2aWNlOiAke2RldmljZVBvcnR9YCk7XG4gIGF3YWl0IHRoaXMuYWRiRXhlYyhbJ2ZvcndhcmQnLCBgdGNwOiR7c3lzdGVtUG9ydH1gLCBgbG9jYWxhYnN0cmFjdDoke2RldmljZVBvcnR9YF0pO1xufTtcblxuLyoqXG4gKiBFeGVjdXRlIHBpbmcgc2hlbGwgY29tbWFuZCBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgY29tbWFuZCBvdXRwdXQgY29udGFpbnMgJ3BpbmcnIHN1YnN0cmluZy5cbiAqIEB0aHJvd3Mge2Vycm9yfSBJZiB0aGVyZSB3YXMgYW4gZXJyb3Igd2hpbGUgZXhlY3V0aW5nICdwaW5nJyBjb21tYW5kIG9uIHRoZVxuICogICAgICAgICAgICAgICAgIGRldmljZSB1bmRlciB0ZXN0LlxuICovXG5tZXRob2RzLnBpbmcgPSBhc3luYyBmdW5jdGlvbiBwaW5nICgpIHtcbiAgbGV0IHN0ZG91dCA9IGF3YWl0IHRoaXMuc2hlbGwoWydlY2hvJywgJ3BpbmcnXSk7XG4gIGlmIChzdGRvdXQuaW5kZXhPZigncGluZycpID09PSAwKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgdGhyb3cgbmV3IEVycm9yKGBBREIgcGluZyBmYWlsZWQsIHJldHVybmVkICR7c3Rkb3V0fWApO1xufTtcblxuLyoqXG4gKiBSZXN0YXJ0IHRoZSBkZXZpY2UgdW5kZXIgdGVzdCB1c2luZyBhZGIgY29tbWFuZHMuXG4gKlxuICogQHRocm93cyB7ZXJyb3J9IElmIHN0YXJ0IGZhaWxzLlxuICovXG5tZXRob2RzLnJlc3RhcnQgPSBhc3luYyBmdW5jdGlvbiByZXN0YXJ0ICgpIHtcbiAgdHJ5IHtcbiAgICBhd2FpdCB0aGlzLnN0b3BMb2djYXQoKTtcbiAgICBhd2FpdCB0aGlzLnJlc3RhcnRBZGIoKTtcbiAgICBhd2FpdCB0aGlzLndhaXRGb3JEZXZpY2UoNjApO1xuICAgIGF3YWl0IHRoaXMuc3RhcnRMb2djYXQodGhpcy5fbG9nY2F0U3RhcnR1cFBhcmFtcyk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFJlc3RhcnQgZmFpbGVkLiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gIH1cbn07XG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gTG9nY2F0T3B0c1xuICogQHByb3BlcnR5IHtzdHJpbmd9IGZvcm1hdCBUaGUgbG9nIHByaW50IGZvcm1hdCwgd2hlcmUgPGZvcm1hdD4gaXMgb25lIG9mOlxuICogICBicmllZiBwcm9jZXNzIHRhZyB0aHJlYWQgcmF3IHRpbWUgdGhyZWFkdGltZSBsb25nXG4gKiBgdGhyZWFkdGltZWAgaXMgdGhlIGRlZmF1bHQgdmFsdWUuXG4gKiBAcHJvcGVydHkge0FycmF5PHN0cmluZz59IGZpbHRlclNwZWNzIFNlcmllcyBvZiA8dGFnPls6cHJpb3JpdHldXG4gKiB3aGVyZSA8dGFnPiBpcyBhIGxvZyBjb21wb25lbnQgdGFnIChvciAqIGZvciBhbGwpIGFuZCBwcmlvcml0eSBpczpcbiAqICBWICAgIFZlcmJvc2VcbiAqICBEICAgIERlYnVnXG4gKiAgSSAgICBJbmZvXG4gKiAgVyAgICBXYXJuXG4gKiAgRSAgICBFcnJvclxuICogIEYgICAgRmF0YWxcbiAqICBTICAgIFNpbGVudCAoc3VwcmVzcyBhbGwgb3V0cHV0KVxuICpcbiAqICcqJyBtZWFucyAnKjpkJyBhbmQgPHRhZz4gYnkgaXRzZWxmIG1lYW5zIDx0YWc+OnZcbiAqXG4gKiBJZiBub3Qgc3BlY2lmaWVkIG9uIHRoZSBjb21tYW5kbGluZSwgZmlsdGVyc3BlYyBpcyBzZXQgZnJvbSBBTkRST0lEX0xPR19UQUdTLlxuICogSWYgbm8gZmlsdGVyc3BlYyBpcyBmb3VuZCwgZmlsdGVyIGRlZmF1bHRzIHRvICcqOkknXG4gKi9cblxuLyoqXG4gKiBTdGFydCB0aGUgbG9nY2F0IHByb2Nlc3MgdG8gZ2F0aGVyIGxvZ3MuXG4gKlxuICogQHBhcmFtIHs/TG9nY2F0T3B0c30gb3B0c1xuICogQHRocm93cyB7RXJyb3J9IElmIHJlc3RhcnQgZmFpbHMuXG4gKi9cbm1ldGhvZHMuc3RhcnRMb2djYXQgPSBhc3luYyBmdW5jdGlvbiBzdGFydExvZ2NhdCAob3B0cyA9IHt9KSB7XG4gIGlmICghXy5pc0VtcHR5KHRoaXMubG9nY2F0KSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIlRyeWluZyB0byBzdGFydCBsb2djYXQgY2FwdHVyZSBidXQgaXQncyBhbHJlYWR5IHN0YXJ0ZWQhXCIpO1xuICB9XG5cbiAgdGhpcy5sb2djYXQgPSBuZXcgTG9nY2F0KHtcbiAgICBhZGI6IHRoaXMuZXhlY3V0YWJsZSxcbiAgICBkZWJ1ZzogZmFsc2UsXG4gICAgZGVidWdUcmFjZTogZmFsc2UsXG4gICAgY2xlYXJEZXZpY2VMb2dzT25TdGFydDogISF0aGlzLmNsZWFyRGV2aWNlTG9nc09uU3RhcnQsXG4gIH0pO1xuICBhd2FpdCB0aGlzLmxvZ2NhdC5zdGFydENhcHR1cmUob3B0cyk7XG4gIHRoaXMuX2xvZ2NhdFN0YXJ0dXBQYXJhbXMgPSBvcHRzO1xufTtcblxuLyoqXG4gKiBTdG9wIHRoZSBhY3RpdmUgbG9nY2F0IHByb2Nlc3Mgd2hpY2ggZ2F0aGVycyBsb2dzLlxuICogVGhlIGNhbGwgd2lsbCBiZSBpZ25vcmVkIGlmIG5vIGxvZ2NhdCBwcm9jZXNzIGlzIHJ1bm5pbmcuXG4gKi9cbm1ldGhvZHMuc3RvcExvZ2NhdCA9IGFzeW5jIGZ1bmN0aW9uIHN0b3BMb2djYXQgKCkge1xuICBpZiAoXy5pc0VtcHR5KHRoaXMubG9nY2F0KSkge1xuICAgIHJldHVybjtcbiAgfVxuICB0cnkge1xuICAgIGF3YWl0IHRoaXMubG9nY2F0LnN0b3BDYXB0dXJlKCk7XG4gIH0gZmluYWxseSB7XG4gICAgdGhpcy5sb2djYXQgPSBudWxsO1xuICB9XG59O1xuXG4vKipcbiAqIFJldHJpZXZlIHRoZSBvdXRwdXQgZnJvbSB0aGUgY3VycmVudGx5IHJ1bm5pbmcgbG9nY2F0IHByb2Nlc3MuXG4gKiBUaGUgbG9nY2F0IHByb2Nlc3Mgc2hvdWxkIGJlIGV4ZWN1dGVkIGJ5IHsybGluayAjc3RhcnRMb2djYXR9IG1ldGhvZC5cbiAqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBjb2xsZWN0ZWQgbG9nY2F0IG91dHB1dC5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiBsb2djYXQgcHJvY2VzcyBpcyBub3QgcnVubmluZy5cbiAqL1xubWV0aG9kcy5nZXRMb2djYXRMb2dzID0gZnVuY3Rpb24gZ2V0TG9nY2F0TG9ncyAoKSB7XG4gIGlmIChfLmlzRW1wdHkodGhpcy5sb2djYXQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuJ3QgZ2V0IGxvZ2NhdCBsb2dzIHNpbmNlIGxvZ2NhdCBoYXNuJ3Qgc3RhcnRlZFwiKTtcbiAgfVxuICByZXR1cm4gdGhpcy5sb2djYXQuZ2V0TG9ncygpO1xufTtcblxuLyoqXG4gKiBTZXQgdGhlIGNhbGxiYWNrIGZvciB0aGUgbG9nY2F0IG91dHB1dCBldmVudC5cbiAqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciAtIFRoZSBsaXN0ZW5lciBmdW5jdGlvbiwgd2hpY2ggYWNjZXB0cyBvbmUgYXJndW1lbnQuIFRoZSBhcmd1bWVudCBpc1xuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhIGxvZyByZWNvcmQgb2JqZWN0IHdpdGggYHRpbWVzdGFtcGAsIGBsZXZlbGAgYW5kIGBtZXNzYWdlYCBwcm9wZXJ0aWVzLlxuICogQHRocm93cyB7RXJyb3J9IElmIGxvZ2NhdCBwcm9jZXNzIGlzIG5vdCBydW5uaW5nLlxuICovXG5tZXRob2RzLnNldExvZ2NhdExpc3RlbmVyID0gZnVuY3Rpb24gc2V0TG9nY2F0TGlzdGVuZXIgKGxpc3RlbmVyKSB7XG4gIGlmIChfLmlzRW1wdHkodGhpcy5sb2djYXQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiTG9nY2F0IHByb2Nlc3MgaGFzbid0IGJlZW4gc3RhcnRlZFwiKTtcbiAgfVxuICB0aGlzLmxvZ2NhdC5vbignb3V0cHV0JywgbGlzdGVuZXIpO1xufTtcblxuLyoqXG4gKiBSZW1vdmVzIHRoZSBwcmV2aW91c2x5IHNldCBjYWxsYmFjayBmb3IgdGhlIGxvZ2NhdCBvdXRwdXQgZXZlbnQuXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgLSBUaGUgbGlzdGVuZXIgZnVuY3Rpb24sIHdoaWNoIGhhcyBiZWVuIHByZXZpb3VzbHlcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzc2VkIHRvIGBzZXRMb2djYXRMaXN0ZW5lcmBcbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiBsb2djYXQgcHJvY2VzcyBpcyBub3QgcnVubmluZy5cbiAqL1xubWV0aG9kcy5yZW1vdmVMb2djYXRMaXN0ZW5lciA9IGZ1bmN0aW9uIHJlbW92ZUxvZ2NhdExpc3RlbmVyIChsaXN0ZW5lcikge1xuICBpZiAoXy5pc0VtcHR5KHRoaXMubG9nY2F0KSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkxvZ2NhdCBwcm9jZXNzIGhhc24ndCBiZWVuIHN0YXJ0ZWRcIik7XG4gIH1cbiAgdGhpcy5sb2djYXQucmVtb3ZlTGlzdGVuZXIoJ291dHB1dCcsIGxpc3RlbmVyKTtcbn07XG5cbi8qKlxuICogQXQgc29tZSBwb2ludCBvZiB0aW1lIEdvb2dsZSBoYXMgY2hhbmdlZCB0aGUgZGVmYXVsdCBgcHNgIGJlaGF2aW91ciwgc28gaXQgb25seVxuICogbGlzdHMgcHJvY2Vzc2VzIHRoYXQgYmVsb25nIHRvIHRoZSBjdXJyZW50IHNoZWxsIHVzZXIgcmF0aGVyIHRvIGFsbFxuICogdXNlcnMuIEl0IGlzIG5lY2Vzc2FyeSB0byBleGVjdXRlIHBzIHdpdGggLUEgY29tbWFuZCBsaW5lIGFyZ3VtZW50XG4gKiB0byBtaW1pYyB0aGUgcHJldmlvdXMgYmVoYXZpb3VyLlxuICpcbiAqIEByZXR1cm5zIHtzdHJpbmd9IHRoZSBvdXRwdXQgb2YgYHBzYCBjb21tYW5kIHdoZXJlIGFsbCBwcm9jZXNzZXMgYXJlIGluY2x1ZGVkXG4gKi9cbm1ldGhvZHMubGlzdFByb2Nlc3NTdGF0dXMgPSBhc3luYyBmdW5jdGlvbiBsaXN0UHJvY2Vzc1N0YXR1cyAoKSB7XG4gIGlmICghXy5pc0Jvb2xlYW4odGhpcy5fZG9lc1BzU3VwcG9ydEFPcHRpb24pKSB7XG4gICAgdHJ5IHtcbiAgICAgIHRoaXMuX2RvZXNQc1N1cHBvcnRBT3B0aW9uID0gL14tQVxcYi9tLnRlc3QoYXdhaXQgdGhpcy5zaGVsbChbJ3BzJywgJy0taGVscCddKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgbG9nLmRlYnVnKGUuc3RhY2spO1xuICAgICAgdGhpcy5fZG9lc1BzU3VwcG9ydEFPcHRpb24gPSBmYWxzZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGF3YWl0IHRoaXMuc2hlbGwodGhpcy5fZG9lc1BzU3VwcG9ydEFPcHRpb24gPyBbJ3BzJywgJy1BJ10gOiBbJ3BzJ10pO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIHByb2Nlc3MgbmFtZSBmb3IgdGhlIGdpdmVuIHByb2Nlc3MgaWRlbnRpZmllclxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gcGlkIC0gVGhlIHZhbGlkIHByb2Nlc3MgaWRlbnRpZmllclxuICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBnaXZlbiBQSUQgaXMgZWl0aGVyIGludmFsaWQgb3IgaXMgbm90IHByZXNlbnRcbiAqIGluIHRoZSBhY3RpdmUgcHJvY2Vzc2VzIGxpc3RcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBwcm9jZXNzIG5hbWVcbiAqL1xubWV0aG9kcy5nZXROYW1lQnlQaWQgPSBhc3luYyBmdW5jdGlvbiBnZXROYW1lQnlQaWQgKHBpZCkge1xuICBpZiAoaXNOYU4ocGlkKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVGhlIFBJRCB2YWx1ZSBtdXN0IGJlIGEgdmFsaWQgbnVtYmVyLiAnJHtwaWR9JyBpcyBnaXZlbiBpbnN0ZWFkYCk7XG4gIH1cbiAgcGlkID0gcGFyc2VJbnQocGlkLCAxMCk7XG5cbiAgY29uc3Qgc3Rkb3V0ID0gYXdhaXQgdGhpcy5saXN0UHJvY2Vzc1N0YXR1cygpO1xuICBjb25zdCB0aXRsZU1hdGNoID0gUFNfVElUTEVfUEFUVEVSTi5leGVjKHN0ZG91dCk7XG4gIGlmICghdGl0bGVNYXRjaCkge1xuICAgIGxvZy5kZWJ1ZyhzdGRvdXQpO1xuICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IGdldCB0aGUgcHJvY2VzcyBuYW1lIGZvciBQSUQgJyR7cGlkfSdgKTtcbiAgfVxuICBjb25zdCBhbGxUaXRsZXMgPSB0aXRsZU1hdGNoWzFdLnRyaW0oKS5zcGxpdCgvXFxzKy8pO1xuICBjb25zdCBwaWRJbmRleCA9IGFsbFRpdGxlcy5pbmRleE9mKFBJRF9DT0xVTU5fVElUTEUpO1xuICAvLyBpdCBtaWdodCBub3QgYmUgc3RhYmxlIHRvIHRha2UgTkFNRSBieSBpbmRleCwgYmVjYXVzZSBkZXBlbmRpbmcgb24gdGhlXG4gIC8vIGFjdHVhbCBTREsgdGhlIHBzIG91dHB1dCBtaWdodCBub3QgY29udGFpbiBhbiBhYmJyZXZpYXRpb24gZm9yIHRoZSBTIGZsYWc6XG4gIC8vIFVTRVIgICAgIFBJRCAgIFBQSUQgIFZTSVpFICBSU1MgICAgIFdDSEFOICAgIFBDICAgICAgICBOQU1FXG4gIC8vIFVTRVIgICAgIFBJRCAgIFBQSUQgIFZTSVpFICBSU1MgICAgIFdDSEFOICAgIFBDICAgUyAgICBOQU1FXG4gIGNvbnN0IG5hbWVPZmZzZXQgPSBhbGxUaXRsZXMuaW5kZXhPZihQUk9DRVNTX05BTUVfQ09MVU1OX1RJVExFKSAtIGFsbFRpdGxlcy5sZW5ndGg7XG4gIGNvbnN0IHBpZFJlZ2V4ID0gbmV3IFJlZ0V4cChgXiguKlxcXFxiJHtwaWR9XFxcXGIuKikkYCwgJ2dtJyk7XG4gIGxldCBtYXRjaGVkTGluZTtcbiAgd2hpbGUgKChtYXRjaGVkTGluZSA9IHBpZFJlZ2V4LmV4ZWMoc3Rkb3V0KSkpIHtcbiAgICBjb25zdCBpdGVtcyA9IG1hdGNoZWRMaW5lWzFdLnRyaW0oKS5zcGxpdCgvXFxzKy8pO1xuICAgIGlmIChwYXJzZUludChpdGVtc1twaWRJbmRleF0sIDEwKSA9PT0gcGlkICYmIGl0ZW1zW2l0ZW1zLmxlbmd0aCArIG5hbWVPZmZzZXRdKSB7XG4gICAgICByZXR1cm4gaXRlbXNbaXRlbXMubGVuZ3RoICsgbmFtZU9mZnNldF07XG4gICAgfVxuICB9XG4gIGxvZy5kZWJ1ZyhzdGRvdXQpO1xuICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBnZXQgdGhlIHByb2Nlc3MgbmFtZSBmb3IgUElEICcke3BpZH0nYCk7XG59O1xuXG4vKipcbiAqIEdldCB0aGUgbGlzdCBvZiBwcm9jZXNzIGlkcyBmb3IgdGhlIHBhcnRpY3VsYXIgcHJvY2VzcyBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBUaGUgcGFydCBvZiBwcm9jZXNzIG5hbWUuXG4gKiBAcmV0dXJuIHtBcnJheS48bnVtYmVyPn0gVGhlIGxpc3Qgb2YgbWF0Y2hlZCBwcm9jZXNzIElEcyBvciBhbiBlbXB0eSBsaXN0LlxuICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXNzZWQgcHJvY2VzcyBuYW1lIGlzIG5vdCBhIHZhbGlkIG9uZVxuICovXG5tZXRob2RzLmdldFBJRHNCeU5hbWUgPSBhc3luYyBmdW5jdGlvbiBnZXRQSURzQnlOYW1lIChuYW1lKSB7XG4gIGxvZy5kZWJ1ZyhgR2V0dGluZyBJRHMgb2YgYWxsICcke25hbWV9JyBwcm9jZXNzZXNgKTtcbiAgaWYgKCF0aGlzLmlzVmFsaWRDbGFzcyhuYW1lKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBwcm9jZXNzIG5hbWU6ICcke25hbWV9J2ApO1xuICB9XG4gIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9hcHBpdW0vYXBwaXVtL2lzc3Vlcy8xMzU2N1xuICBpZiAoYXdhaXQgdGhpcy5nZXRBcGlMZXZlbCgpID49IDIzKSB7XG4gICAgaWYgKCFfLmlzQm9vbGVhbih0aGlzLl9pc1BncmVwQXZhaWxhYmxlKSkge1xuICAgICAgLy8gcGdyZXAgaXMgaW4gcHJpb3JpdHksIHNpbmNlIHBpZG9mIGhhcyBiZWVuIHJlcG9ydGVkIG9mIGhhdmluZyBidWdzIG9uIHNvbWUgcGxhdGZvcm1zXG4gICAgICBjb25zdCBwZ3JlcE91dHB1dCA9IF8udHJpbShhd2FpdCB0aGlzLnNoZWxsKFsncGdyZXAgLS1oZWxwOyBlY2hvICQ/J10pKTtcbiAgICAgIHRoaXMuX2lzUGdyZXBBdmFpbGFibGUgPSBwYXJzZUludChfLmxhc3QocGdyZXBPdXRwdXQuc3BsaXQoL1xccysvKSksIDEwKSA9PT0gMDtcbiAgICAgIGlmICh0aGlzLl9pc1BncmVwQXZhaWxhYmxlKSB7XG4gICAgICAgIHRoaXMuX2NhblBncmVwVXNlRnVsbENtZExpbmVTZWFyY2ggPSAvXi1mXFxiL20udGVzdChwZ3JlcE91dHB1dCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9pc1BpZG9mQXZhaWxhYmxlID0gcGFyc2VJbnQoYXdhaXQgdGhpcy5zaGVsbChbJ3BpZG9mIC0taGVscCA+IC9kZXYvbnVsbDsgZWNobyAkPyddKSwgMTApID09PSAwO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAodGhpcy5faXNQZ3JlcEF2YWlsYWJsZSB8fCB0aGlzLl9pc1BpZG9mQXZhaWxhYmxlKSB7XG4gICAgICBjb25zdCBzaGVsbENvbW1hbmQgPSB0aGlzLl9pc1BncmVwQXZhaWxhYmxlXG4gICAgICAgID8gKHRoaXMuX2NhblBncmVwVXNlRnVsbENtZExpbmVTZWFyY2hcbiAgICAgICAgICA/IFsncGdyZXAnLCAnLWYnLCBfLmVzY2FwZVJlZ0V4cChgKFtbOmJsYW5rOl1dfF4pJHtuYW1lfShbWzpibGFuazpdXXwkKWApXVxuICAgICAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9hcHBpdW0vYXBwaXVtL2lzc3Vlcy8xMzg3MlxuICAgICAgICAgIDogW2BwZ3JlcCBeJHtfLmVzY2FwZVJlZ0V4cChuYW1lLnNsaWNlKC1NQVhfUEdSRVBfUEFUVEVSTl9MRU4pKX0kIGAgK1xuICAgICAgICAgICAgICBgfHwgcGdyZXAgXiR7Xy5lc2NhcGVSZWdFeHAobmFtZS5zbGljZSgwLCBNQVhfUEdSRVBfUEFUVEVSTl9MRU4pKX0kYF0pXG4gICAgICAgIDogWydwaWRvZicsIG5hbWVdO1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIChhd2FpdCB0aGlzLnNoZWxsKHNoZWxsQ29tbWFuZCkpXG4gICAgICAgICAgLnNwbGl0KC9cXHMrLylcbiAgICAgICAgICAubWFwKCh4KSA9PiBwYXJzZUludCh4LCAxMCkpXG4gICAgICAgICAgLmZpbHRlcigoeCkgPT4gXy5pc0ludGVnZXIoeCkpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAvLyBlcnJvciBjb2RlIDEgaXMgcmV0dXJuZWQgaWYgdGhlIHV0aWxpdHkgZGlkIG5vdCBmaW5kIGFueSBwcm9jZXNzZXNcbiAgICAgICAgLy8gd2l0aCB0aGUgZ2l2ZW4gbmFtZVxuICAgICAgICBpZiAoZS5jb2RlICE9PSAxKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgZXh0cmFjdCBwcm9jZXNzIElEIG9mICcke25hbWV9JzogJHtlLm1lc3NhZ2V9YCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKF8uaW5jbHVkZXMoZS5zdGRlcnIgfHwgZS5zdGRvdXQsICdzeW50YXggZXJyb3InKSkge1xuICAgICAgICAgIGxvZy53YXJuKGBHb3QgYW4gdW5leHBlY3RlZCByZXNwb25zZSBmcm9tIHRoZSBzaGVsbCBpbnRlcnByZXRlcjogJHtlLnN0ZGVyciB8fCBlLnN0ZG91dH1gKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBsb2cuZGVidWcoJ1VzaW5nIHBzLWJhc2VkIFBJRCBkZXRlY3Rpb24nKTtcbiAgY29uc3Qgc3Rkb3V0ID0gYXdhaXQgdGhpcy5saXN0UHJvY2Vzc1N0YXR1cygpO1xuICBjb25zdCB0aXRsZU1hdGNoID0gUFNfVElUTEVfUEFUVEVSTi5leGVjKHN0ZG91dCk7XG4gIGlmICghdGl0bGVNYXRjaCkge1xuICAgIGxvZy5kZWJ1ZyhzdGRvdXQpO1xuICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IGV4dHJhY3QgUElEIG9mICcke25hbWV9JyBmcm9tIHBzIG91dHB1dGApO1xuICB9XG4gIGNvbnN0IGFsbFRpdGxlcyA9IHRpdGxlTWF0Y2hbMV0udHJpbSgpLnNwbGl0KC9cXHMrLyk7XG4gIGNvbnN0IHBpZEluZGV4ID0gYWxsVGl0bGVzLmluZGV4T2YoUElEX0NPTFVNTl9USVRMRSk7XG4gIGNvbnN0IHBpZHMgPSBbXTtcbiAgY29uc3QgcHJvY2Vzc05hbWVSZWdleCA9IG5ldyBSZWdFeHAoYF4oLipcXFxcYlxcXFxkK1xcXFxiLipcXFxcYiR7Xy5lc2NhcGVSZWdFeHAobmFtZSl9XFxcXGIuKikkYCwgJ2dtJyk7XG4gIGxldCBtYXRjaGVkTGluZTtcbiAgd2hpbGUgKChtYXRjaGVkTGluZSA9IHByb2Nlc3NOYW1lUmVnZXguZXhlYyhzdGRvdXQpKSkge1xuICAgIGNvbnN0IGl0ZW1zID0gbWF0Y2hlZExpbmVbMV0udHJpbSgpLnNwbGl0KC9cXHMrLyk7XG4gICAgaWYgKHBpZEluZGV4ID49IGFsbFRpdGxlcy5sZW5ndGggfHwgaXNOYU4oaXRlbXNbcGlkSW5kZXhdKSkge1xuICAgICAgbG9nLmRlYnVnKHN0ZG91dCk7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBleHRyYWN0IFBJRCBvZiAnJHtuYW1lfScgZnJvbSAnJHttYXRjaGVkTGluZVsxXS50cmltKCl9J2ApO1xuICAgIH1cbiAgICBwaWRzLnB1c2gocGFyc2VJbnQoaXRlbXNbcGlkSW5kZXhdLCAxMCkpO1xuICB9XG4gIHJldHVybiBwaWRzO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIGxpc3Qgb2YgcHJvY2VzcyBpZHMgZm9yIHRoZSBwYXJ0aWN1bGFyIHByb2Nlc3Mgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gVGhlIHBhcnQgb2YgcHJvY2VzcyBuYW1lLlxuICogQHJldHVybiB7QXJyYXkuPG51bWJlcj59IFRoZSBsaXN0IG9mIG1hdGNoZWQgcHJvY2VzcyBJRHMgb3IgYW4gZW1wdHkgbGlzdC5cbiAqL1xubWV0aG9kcy5raWxsUHJvY2Vzc2VzQnlOYW1lID0gYXN5bmMgZnVuY3Rpb24ga2lsbFByb2Nlc3Nlc0J5TmFtZSAobmFtZSkge1xuICB0cnkge1xuICAgIGxvZy5kZWJ1ZyhgQXR0ZW1wdGluZyB0byBraWxsIGFsbCAke25hbWV9IHByb2Nlc3Nlc2ApO1xuICAgIGNvbnN0IHBpZHMgPSBhd2FpdCB0aGlzLmdldFBJRHNCeU5hbWUobmFtZSk7XG4gICAgaWYgKF8uaXNFbXB0eShwaWRzKSkge1xuICAgICAgbG9nLmluZm8oYE5vICcke25hbWV9JyBwcm9jZXNzIGhhcyBiZWVuIGZvdW5kYCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IEIuYWxsKHBpZHMubWFwKChwKSA9PiB0aGlzLmtpbGxQcm9jZXNzQnlQSUQocCkpKTtcbiAgICB9XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBraWxsICR7bmFtZX0gcHJvY2Vzc2VzLiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gIH1cbn07XG5cbi8qKlxuICogS2lsbCB0aGUgcGFydGljdWxhciBwcm9jZXNzIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqIFRoZSBjdXJyZW50IHVzZXIgaXMgYXV0b21hdGljYWxseSBzd2l0Y2hlZCB0byByb290IGlmIG5lY2Vzc2FyeSBpbiBvcmRlclxuICogdG8gcHJvcGVybHkga2lsbCB0aGUgcHJvY2Vzcy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IHBpZCAtIFRoZSBJRCBvZiB0aGUgcHJvY2VzcyB0byBiZSBraWxsZWQuXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHByb2Nlc3MgY2Fubm90IGJlIGtpbGxlZC5cbiAqL1xubWV0aG9kcy5raWxsUHJvY2Vzc0J5UElEID0gYXN5bmMgZnVuY3Rpb24ga2lsbFByb2Nlc3NCeVBJRCAocGlkKSB7XG4gIGxvZy5kZWJ1ZyhgQXR0ZW1wdGluZyB0byBraWxsIHByb2Nlc3MgJHtwaWR9YCk7XG4gIGNvbnN0IG5vUHJvY2Vzc0ZsYWcgPSAnTm8gc3VjaCBwcm9jZXNzJztcbiAgdHJ5IHtcbiAgICAvLyBDaGVjayBpZiB0aGUgcHJvY2VzcyBleGlzdHMgYW5kIHRocm93IGFuIGV4Y2VwdGlvbiBvdGhlcndpc2VcbiAgICBhd2FpdCB0aGlzLnNoZWxsKFsna2lsbCcsIHBpZF0pO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKF8uaW5jbHVkZXMoZS5zdGRlcnIsIG5vUHJvY2Vzc0ZsYWcpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghXy5pbmNsdWRlcyhlLnN0ZGVyciwgJ09wZXJhdGlvbiBub3QgcGVybWl0dGVkJykpIHtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICAgIGxvZy5pbmZvKGBDYW5ub3Qga2lsbCBQSUQgJHtwaWR9IGR1ZSB0byBpbnN1ZmZpY2llbnQgcGVybWlzc2lvbnMuIFJldHJ5aW5nIGFzIHJvb3RgKTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5zaGVsbChbJ2tpbGwnLCBwaWRdLCB7XG4gICAgICAgIHByaXZpbGVnZWQ6IHRydWVcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGUxKSB7XG4gICAgICBpZiAoXy5pbmNsdWRlcyhlMS5zdGRlcnIsIG5vUHJvY2Vzc0ZsYWcpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHRocm93IGUxO1xuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBCcm9hZGNhc3QgcHJvY2VzcyBraWxsaW5nIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaW50ZW50IC0gVGhlIG5hbWUgb2YgdGhlIGludGVudCB0byBicm9hZGNhc3QgdG8uXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvY2Vzc05hbWUgLSBUaGUgbmFtZSBvZiB0aGUga2lsbGVkIHByb2Nlc3MuXG4gKiBAdGhyb3dzIHtlcnJvcn0gSWYgdGhlIHByb2Nlc3Mgd2FzIG5vdCBraWxsZWQuXG4gKi9cbm1ldGhvZHMuYnJvYWRjYXN0UHJvY2Vzc0VuZCA9IGFzeW5jIGZ1bmN0aW9uIGJyb2FkY2FzdFByb2Nlc3NFbmQgKGludGVudCwgcHJvY2Vzc05hbWUpIHtcbiAgLy8gc3RhcnQgdGhlIGJyb2FkY2FzdCB3aXRob3V0IHdhaXRpbmcgZm9yIGl0IHRvIGZpbmlzaC5cbiAgdGhpcy5icm9hZGNhc3QoaW50ZW50KTtcbiAgLy8gd2FpdCBmb3IgdGhlIHByb2Nlc3MgdG8gZW5kXG4gIGxldCBzdGFydCA9IERhdGUubm93KCk7XG4gIGxldCB0aW1lb3V0TXMgPSA0MDAwMDtcbiAgdHJ5IHtcbiAgICB3aGlsZSAoKERhdGUubm93KCkgLSBzdGFydCkgPCB0aW1lb3V0TXMpIHtcbiAgICAgIGlmIChhd2FpdCB0aGlzLnByb2Nlc3NFeGlzdHMocHJvY2Vzc05hbWUpKSB7XG4gICAgICAgIC8vIGNvb2wgZG93blxuICAgICAgICBhd2FpdCBzbGVlcCg0MDApO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKGBQcm9jZXNzIG5ldmVyIGRpZWQgd2l0aGluICR7dGltZW91dE1zfSBtc2ApO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gYnJvYWRjYXN0IHByb2Nlc3MgZW5kLiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gIH1cbn07XG5cbi8qKlxuICogQnJvYWRjYXN0IGEgbWVzc2FnZSB0byB0aGUgZ2l2ZW4gaW50ZW50LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBpbnRlbnQgLSBUaGUgbmFtZSBvZiB0aGUgaW50ZW50IHRvIGJyb2FkY2FzdCB0by5cbiAqIEB0aHJvd3Mge2Vycm9yfSBJZiBpbnRlbnQgbmFtZSBpcyBub3QgYSB2YWxpZCBjbGFzcyBuYW1lLlxuICovXG5tZXRob2RzLmJyb2FkY2FzdCA9IGFzeW5jIGZ1bmN0aW9uIGJyb2FkY2FzdCAoaW50ZW50KSB7XG4gIGlmICghdGhpcy5pc1ZhbGlkQ2xhc3MoaW50ZW50KSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBpbnRlbnQgJHtpbnRlbnR9YCk7XG4gIH1cbiAgbG9nLmRlYnVnKGBCcm9hZGNhc3Rpbmc6ICR7aW50ZW50fWApO1xuICBhd2FpdCB0aGlzLnNoZWxsKFsnYW0nLCAnYnJvYWRjYXN0JywgJy1hJywgaW50ZW50XSk7XG59O1xuXG4vKipcbiAqIEtpbGwgQW5kcm9pZCBpbnN0cnVtZW50cyBpZiB0aGV5IGFyZSBjdXJyZW50bHkgcnVubmluZy5cbiAqL1xubWV0aG9kcy5lbmRBbmRyb2lkQ292ZXJhZ2UgPSBhc3luYyBmdW5jdGlvbiBlbmRBbmRyb2lkQ292ZXJhZ2UgKCkge1xuICBpZiAodGhpcy5pbnN0cnVtZW50UHJvYyAmJiB0aGlzLmluc3RydW1lbnRQcm9jLmlzUnVubmluZykge1xuICAgIGF3YWl0IHRoaXMuaW5zdHJ1bWVudFByb2Muc3RvcCgpO1xuICB9XG59O1xuXG4vKipcbiAqIEluc3RydW1lbnQgdGhlIHBhcnRpY3VsYXIgYWN0aXZpdHkuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHBrZyAtIFRoZSBuYW1lIG9mIHRoZSBwYWNrYWdlIHRvIGJlIGluc3RydW1lbnRlZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBhY3Rpdml0eSAtIFRoZSBuYW1lIG9mIHRoZSBtYWluIGFjdGl2aXR5IGluIHRoaXMgcGFja2FnZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpbnN0cnVtZW50V2l0aCAtIFRoZSBuYW1lIG9mIHRoZSBwYWNrYWdlIHRvIGluc3RydW1lbnRcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZSBhY3Rpdml0eSB3aXRoLlxuICogQHRocm93cyB7ZXJyb3J9IElmIGFueSBleGNlcHRpb24gaXMgcmVwb3J0ZWQgYnkgYWRiIHNoZWxsLlxuICovXG5tZXRob2RzLmluc3RydW1lbnQgPSBhc3luYyBmdW5jdGlvbiBpbnN0cnVtZW50IChwa2csIGFjdGl2aXR5LCBpbnN0cnVtZW50V2l0aCkge1xuICBpZiAoYWN0aXZpdHlbMF0gIT09ICcuJykge1xuICAgIHBrZyA9ICcnO1xuICB9XG4gIGxldCBwa2dBY3Rpdml0eSA9IChwa2cgKyBhY3Rpdml0eSkucmVwbGFjZSgvXFwuKy9nLCAnLicpOyAvLyBGaXggcGtnLi5hY3Rpdml0eSBlcnJvclxuICBsZXQgc3Rkb3V0ID0gYXdhaXQgdGhpcy5zaGVsbChbXG4gICAgJ2FtJywgJ2luc3RydW1lbnQnLFxuICAgICctZScsICdtYWluX2FjdGl2aXR5JyxcbiAgICBwa2dBY3Rpdml0eSxcbiAgICBpbnN0cnVtZW50V2l0aCxcbiAgXSk7XG4gIGlmIChzdGRvdXQuaW5kZXhPZignRXhjZXB0aW9uJykgIT09IC0xKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIGV4Y2VwdGlvbiBkdXJpbmcgaW5zdHJ1bWVudGF0aW9uLiBPcmlnaW5hbCBlcnJvciAke3N0ZG91dC5zcGxpdCgnXFxuJylbMF19YCk7XG4gIH1cbn07XG5cbi8qKlxuICogQ29sbGVjdCBBbmRyb2lkIGNvdmVyYWdlIGJ5IGluc3RydW1lbnRpbmcgdGhlIHBhcnRpY3VsYXIgYWN0aXZpdHkuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGluc3RydW1lbnRDbGFzcyAtIFRoZSBuYW1lIG9mIHRoZSBpbnN0cnVtZW50YXRpb24gY2xhc3MuXG4gKiBAcGFyYW0ge3N0cmluZ30gd2FpdFBrZyAtIFRoZSBuYW1lIG9mIHRoZSBwYWNrYWdlIHRvIGJlIGluc3RydW1lbnRlZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSB3YWl0QWN0aXZpdHkgLSBUaGUgbmFtZSBvZiB0aGUgbWFpbiBhY3Rpdml0eSBpbiB0aGlzIHBhY2thZ2UuXG4gKlxuICogQHJldHVybiB7cHJvbWlzZX0gVGhlIHByb21pc2UgaXMgc3VjY2Vzc2Z1bGx5IHJlc29sdmVkIGlmIHRoZSBpbnN0cnVtZW50YXRpb24gc3RhcnRzXG4gKiAgICAgICAgICAgICAgICAgICB3aXRob3V0IGVycm9ycy5cbiAqL1xubWV0aG9kcy5hbmRyb2lkQ292ZXJhZ2UgPSBhc3luYyBmdW5jdGlvbiBhbmRyb2lkQ292ZXJhZ2UgKGluc3RydW1lbnRDbGFzcywgd2FpdFBrZywgd2FpdEFjdGl2aXR5KSB7XG4gIGlmICghdGhpcy5pc1ZhbGlkQ2xhc3MoaW5zdHJ1bWVudENsYXNzKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBjbGFzcyAke2luc3RydW1lbnRDbGFzc31gKTtcbiAgfVxuICByZXR1cm4gYXdhaXQgbmV3IEIoYXN5bmMgKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGxldCBhcmdzID0gdGhpcy5leGVjdXRhYmxlLmRlZmF1bHRBcmdzXG4gICAgICAuY29uY2F0KFsnc2hlbGwnLCAnYW0nLCAnaW5zdHJ1bWVudCcsICctZScsICdjb3ZlcmFnZScsICd0cnVlJywgJy13J10pXG4gICAgICAuY29uY2F0KFtpbnN0cnVtZW50Q2xhc3NdKTtcbiAgICBsb2cuZGVidWcoYENvbGxlY3RpbmcgY292ZXJhZ2UgZGF0YSB3aXRoOiAke1t0aGlzLmV4ZWN1dGFibGUucGF0aF0uY29uY2F0KGFyZ3MpLmpvaW4oJyAnKX1gKTtcbiAgICB0cnkge1xuICAgICAgLy8gYW0gaW5zdHJ1bWVudCBydW5zIGZvciB0aGUgbGlmZSBvZiB0aGUgYXBwIHByb2Nlc3MuXG4gICAgICB0aGlzLmluc3RydW1lbnRQcm9jID0gbmV3IFN1YlByb2Nlc3ModGhpcy5leGVjdXRhYmxlLnBhdGgsIGFyZ3MpO1xuICAgICAgYXdhaXQgdGhpcy5pbnN0cnVtZW50UHJvYy5zdGFydCgwKTtcbiAgICAgIHRoaXMuaW5zdHJ1bWVudFByb2Mub24oJ291dHB1dCcsIChzdGRvdXQsIHN0ZGVycikgPT4ge1xuICAgICAgICBpZiAoc3RkZXJyKSB7XG4gICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgRmFpbGVkIHRvIHJ1biBpbnN0cnVtZW50YXRpb24uIE9yaWdpbmFsIGVycm9yOiAke3N0ZGVycn1gKSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgYXdhaXQgdGhpcy53YWl0Rm9yQWN0aXZpdHkod2FpdFBrZywgd2FpdEFjdGl2aXR5KTtcbiAgICAgIHJlc29sdmUoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QobmV3IEVycm9yKGBBbmRyb2lkIGNvdmVyYWdlIGZhaWxlZC4gT3JpZ2luYWwgZXJyb3I6ICR7ZS5tZXNzYWdlfWApKTtcbiAgICB9XG4gIH0pO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIHBhcnRpY3VsYXIgcHJvcGVydHkgb2YgdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wZXJ0eSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eS4gVGhpcyBuYW1lIHNob3VsZFxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgYmUga25vd24gdG8gX2FkYiBzaGVsbCBnZXRwcm9wXyB0b29sLlxuICpcbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIHZhbHVlIG9mIHRoZSBnaXZlbiBwcm9wZXJ0eS5cbiAqL1xubWV0aG9kcy5nZXREZXZpY2VQcm9wZXJ0eSA9IGFzeW5jIGZ1bmN0aW9uIGdldERldmljZVByb3BlcnR5IChwcm9wZXJ0eSkge1xuICBsZXQgc3Rkb3V0ID0gYXdhaXQgdGhpcy5zaGVsbChbJ2dldHByb3AnLCBwcm9wZXJ0eV0pO1xuICBsZXQgdmFsID0gc3Rkb3V0LnRyaW0oKTtcbiAgbG9nLmRlYnVnKGBDdXJyZW50IGRldmljZSBwcm9wZXJ0eSAnJHtwcm9wZXJ0eX0nOiAke3ZhbH1gKTtcbiAgcmV0dXJuIHZhbDtcbn07XG5cbi8qKlxuICogQHR5cGVkZWYge29iamVjdH0gc2V0UHJvcE9wdHNcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gcHJpdmlsZWdlZCAtIERvIHdlIHJ1biBzZXRQcm9wIGFzIGEgcHJpdmlsZWdlZCBjb21tYW5kPyBEZWZhdWx0IHRydWUuXG4gKi9cblxuLyoqXG4gKiBTZXQgdGhlIHBhcnRpY3VsYXIgcHJvcGVydHkgb2YgdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wZXJ0eSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eS4gVGhpcyBuYW1lIHNob3VsZFxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgYmUga25vd24gdG8gX2FkYiBzaGVsbCBzZXRwcm9wXyB0b29sLlxuICogQHBhcmFtIHtzdHJpbmd9IHZhbCAtIFRoZSBuZXcgcHJvcGVydHkgdmFsdWUuXG4gKiBAcGFyYW0ge3NldFByb3BPcHRzfSBvcHRzXG4gKlxuICogQHRocm93cyB7ZXJyb3J9IElmIF9zZXRwcm9wXyB1dGlsaXR5IGZhaWxzIHRvIGNoYW5nZSBwcm9wZXJ0eSB2YWx1ZS5cbiAqL1xubWV0aG9kcy5zZXREZXZpY2VQcm9wZXJ0eSA9IGFzeW5jIGZ1bmN0aW9uIHNldERldmljZVByb3BlcnR5IChwcm9wLCB2YWwsIG9wdHMgPSB7fSkge1xuICBjb25zdCB7cHJpdmlsZWdlZCA9IHRydWV9ID0gb3B0cztcbiAgbG9nLmRlYnVnKGBTZXR0aW5nIGRldmljZSBwcm9wZXJ0eSAnJHtwcm9wfScgdG8gJyR7dmFsfSdgKTtcbiAgYXdhaXQgdGhpcy5zaGVsbChbJ3NldHByb3AnLCBwcm9wLCB2YWxdLCB7XG4gICAgcHJpdmlsZWdlZCxcbiAgfSk7XG59O1xuXG4vKipcbiAqIEByZXR1cm4ge3N0cmluZ30gQ3VycmVudCBzeXN0ZW0gbGFuZ3VhZ2Ugb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICovXG5tZXRob2RzLmdldERldmljZVN5c0xhbmd1YWdlID0gYXN5bmMgZnVuY3Rpb24gZ2V0RGV2aWNlU3lzTGFuZ3VhZ2UgKCkge1xuICByZXR1cm4gYXdhaXQgdGhpcy5nZXREZXZpY2VQcm9wZXJ0eSgncGVyc2lzdC5zeXMubGFuZ3VhZ2UnKTtcbn07XG5cbi8qKlxuICogQHJldHVybiB7c3RyaW5nfSBDdXJyZW50IGNvdW50cnkgbmFtZSBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKi9cbm1ldGhvZHMuZ2V0RGV2aWNlU3lzQ291bnRyeSA9IGFzeW5jIGZ1bmN0aW9uIGdldERldmljZVN5c0NvdW50cnkgKCkge1xuICByZXR1cm4gYXdhaXQgdGhpcy5nZXREZXZpY2VQcm9wZXJ0eSgncGVyc2lzdC5zeXMuY291bnRyeScpO1xufTtcblxuLyoqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IEN1cnJlbnQgc3lzdGVtIGxvY2FsZSBuYW1lIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqL1xubWV0aG9kcy5nZXREZXZpY2VTeXNMb2NhbGUgPSBhc3luYyBmdW5jdGlvbiBnZXREZXZpY2VTeXNMb2NhbGUgKCkge1xuICByZXR1cm4gYXdhaXQgdGhpcy5nZXREZXZpY2VQcm9wZXJ0eSgncGVyc2lzdC5zeXMubG9jYWxlJyk7XG59O1xuXG4vKipcbiAqIEByZXR1cm4ge3N0cmluZ30gQ3VycmVudCBwcm9kdWN0IGxhbmd1YWdlIG5hbWUgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICovXG5tZXRob2RzLmdldERldmljZVByb2R1Y3RMYW5ndWFnZSA9IGFzeW5jIGZ1bmN0aW9uIGdldERldmljZVByb2R1Y3RMYW5ndWFnZSAoKSB7XG4gIHJldHVybiBhd2FpdCB0aGlzLmdldERldmljZVByb3BlcnR5KCdyby5wcm9kdWN0LmxvY2FsZS5sYW5ndWFnZScpO1xufTtcblxuLyoqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IEN1cnJlbnQgcHJvZHVjdCBjb3VudHJ5IG5hbWUgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICovXG5tZXRob2RzLmdldERldmljZVByb2R1Y3RDb3VudHJ5ID0gYXN5bmMgZnVuY3Rpb24gZ2V0RGV2aWNlUHJvZHVjdENvdW50cnkgKCkge1xuICByZXR1cm4gYXdhaXQgdGhpcy5nZXREZXZpY2VQcm9wZXJ0eSgncm8ucHJvZHVjdC5sb2NhbGUucmVnaW9uJyk7XG59O1xuXG4vKipcbiAqIEByZXR1cm4ge3N0cmluZ30gQ3VycmVudCBwcm9kdWN0IGxvY2FsZSBuYW1lIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqL1xubWV0aG9kcy5nZXREZXZpY2VQcm9kdWN0TG9jYWxlID0gYXN5bmMgZnVuY3Rpb24gZ2V0RGV2aWNlUHJvZHVjdExvY2FsZSAoKSB7XG4gIHJldHVybiBhd2FpdCB0aGlzLmdldERldmljZVByb3BlcnR5KCdyby5wcm9kdWN0LmxvY2FsZScpO1xufTtcblxuLyoqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBtb2RlbCBuYW1lIG9mIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqL1xubWV0aG9kcy5nZXRNb2RlbCA9IGFzeW5jIGZ1bmN0aW9uIGdldE1vZGVsICgpIHtcbiAgcmV0dXJuIGF3YWl0IHRoaXMuZ2V0RGV2aWNlUHJvcGVydHkoJ3JvLnByb2R1Y3QubW9kZWwnKTtcbn07XG5cbi8qKlxuICogQHJldHVybiB7c3RyaW5nfSBUaGUgbWFudWZhY3R1cmVyIG5hbWUgb2YgdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICovXG5tZXRob2RzLmdldE1hbnVmYWN0dXJlciA9IGFzeW5jIGZ1bmN0aW9uIGdldE1hbnVmYWN0dXJlciAoKSB7XG4gIHJldHVybiBhd2FpdCB0aGlzLmdldERldmljZVByb3BlcnR5KCdyby5wcm9kdWN0Lm1hbnVmYWN0dXJlcicpO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIGN1cnJlbnQgc2NyZWVuIHNpemUuXG4gKlxuICogQHJldHVybiB7c3RyaW5nfSBEZXZpY2Ugc2NyZWVuIHNpemUgYXMgc3RyaW5nIGluIGZvcm1hdCAnV3hIJyBvclxuICogICAgICAgICAgICAgICAgICBfbnVsbF8gaWYgaXQgY2Fubm90IGJlIGRldGVybWluZWQuXG4gKi9cbm1ldGhvZHMuZ2V0U2NyZWVuU2l6ZSA9IGFzeW5jIGZ1bmN0aW9uIGdldFNjcmVlblNpemUgKCkge1xuICBsZXQgc3Rkb3V0ID0gYXdhaXQgdGhpcy5zaGVsbChbJ3dtJywgJ3NpemUnXSk7XG4gIGxldCBzaXplID0gbmV3IFJlZ0V4cCgvUGh5c2ljYWwgc2l6ZTogKFteXFxyP1xcbl0rKSovZykuZXhlYyhzdGRvdXQpO1xuICBpZiAoc2l6ZSAmJiBzaXplLmxlbmd0aCA+PSAyKSB7XG4gICAgcmV0dXJuIHNpemVbMV0udHJpbSgpO1xuICB9XG4gIHJldHVybiBudWxsO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIGN1cnJlbnQgc2NyZWVuIGRlbnNpdHkgaW4gZHBpXG4gKlxuICogQHJldHVybiB7P251bWJlcn0gRGV2aWNlIHNjcmVlbiBkZW5zaXR5IGFzIGEgbnVtYmVyIG9yIF9udWxsXyBpZiBpdFxuICogICAgICAgICAgICAgICAgICBjYW5ub3QgYmUgZGV0ZXJtaW5lZFxuICovXG5tZXRob2RzLmdldFNjcmVlbkRlbnNpdHkgPSBhc3luYyBmdW5jdGlvbiBnZXRTY3JlZW5EZW5zaXR5ICgpIHtcbiAgbGV0IHN0ZG91dCA9IGF3YWl0IHRoaXMuc2hlbGwoWyd3bScsICdkZW5zaXR5J10pO1xuICBsZXQgZGVuc2l0eSA9IG5ldyBSZWdFeHAoL1BoeXNpY2FsIGRlbnNpdHk6IChbXlxccj9cXG5dKykqL2cpLmV4ZWMoc3Rkb3V0KTtcbiAgaWYgKGRlbnNpdHkgJiYgZGVuc2l0eS5sZW5ndGggPj0gMikge1xuICAgIGxldCBkZW5zaXR5TnVtYmVyID0gcGFyc2VJbnQoZGVuc2l0eVsxXS50cmltKCksIDEwKTtcbiAgICByZXR1cm4gaXNOYU4oZGVuc2l0eU51bWJlcikgPyBudWxsIDogZGVuc2l0eU51bWJlcjtcbiAgfVxuICByZXR1cm4gbnVsbDtcbn07XG5cbi8qKlxuICogU2V0dXAgSFRUUCBwcm94eSBpbiBkZXZpY2UgZ2xvYmFsIHNldHRpbmdzLlxuICogUmVhZCBodHRwczovL2FuZHJvaWQuZ29vZ2xlc291cmNlLmNvbS9wbGF0Zm9ybS9mcmFtZXdvcmtzL2Jhc2UvKy9hbmRyb2lkLTkuMC4wX3IyMS9jb3JlL2phdmEvYW5kcm9pZC9wcm92aWRlci9TZXR0aW5ncy5qYXZhIGZvciBlYWNoIHByb3BlcnR5XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHByb3h5SG9zdCAtIFRoZSBob3N0IG5hbWUgb2YgdGhlIHByb3h5LlxuICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBwcm94eVBvcnQgLSBUaGUgcG9ydCBudW1iZXIgdG8gYmUgc2V0LlxuICovXG5tZXRob2RzLnNldEh0dHBQcm94eSA9IGFzeW5jIGZ1bmN0aW9uIHNldEh0dHBQcm94eSAocHJveHlIb3N0LCBwcm94eVBvcnQpIHtcbiAgbGV0IHByb3h5ID0gYCR7cHJveHlIb3N0fToke3Byb3h5UG9ydH1gO1xuICBpZiAoXy5pc1VuZGVmaW5lZChwcm94eUhvc3QpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBDYWxsIHRvIHNldEh0dHBQcm94eSBtZXRob2Qgd2l0aCB1bmRlZmluZWQgcHJveHlfaG9zdDogJHtwcm94eX1gKTtcbiAgfVxuICBpZiAoXy5pc1VuZGVmaW5lZChwcm94eVBvcnQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBDYWxsIHRvIHNldEh0dHBQcm94eSBtZXRob2Qgd2l0aCB1bmRlZmluZWQgcHJveHlfcG9ydCAke3Byb3h5fWApO1xuICB9XG5cbiAgY29uc3QgaHR0cFByb3h5U2V0dGlucyA9IFtcbiAgICBbJ2h0dHBfcHJveHknLCBwcm94eV0sXG4gICAgWydnbG9iYWxfaHR0cF9wcm94eV9ob3N0JywgcHJveHlIb3N0XSxcbiAgICBbJ2dsb2JhbF9odHRwX3Byb3h5X3BvcnQnLCBwcm94eVBvcnRdXG4gIF07XG4gIGZvciAoY29uc3QgW3NldHRpbmdLZXksIHNldHRpbmdWYWx1ZV0gb2YgaHR0cFByb3h5U2V0dGlucykge1xuICAgIGF3YWl0IHRoaXMuc2V0U2V0dGluZygnZ2xvYmFsJywgc2V0dGluZ0tleSwgc2V0dGluZ1ZhbHVlKTtcbiAgfVxufTtcblxuLyoqXG4gKiBEZWxldGUgSFRUUCBwcm94eSBpbiBkZXZpY2UgZ2xvYmFsIHNldHRpbmdzLlxuICogUmVib290aW5nIHRoZSB0ZXN0IGRldmljZSBpcyBuZWNlc3NhcnkgdG8gYXBwbHkgdGhlIGNoYW5nZS5cbiAqL1xubWV0aG9kcy5kZWxldGVIdHRwUHJveHkgPSBhc3luYyBmdW5jdGlvbiBkZWxldGVIdHRwUHJveHkgKCkge1xuICBjb25zdCBodHRwUHJveHlTZXR0aW5zID0gW1xuICAgICdodHRwX3Byb3h5JyxcbiAgICAnZ2xvYmFsX2h0dHBfcHJveHlfaG9zdCcsXG4gICAgJ2dsb2JhbF9odHRwX3Byb3h5X3BvcnQnLFxuICAgICdnbG9iYWxfaHR0cF9wcm94eV9leGNsdXNpb25fbGlzdCcgLy8gYGdsb2JhbF9odHRwX3Byb3h5X2V4Y2x1c2lvbl9saXN0PWAgd2FzIGdlbmVyYXRlZCBieSBgc2V0dGluZ3MgZ2xvYmFsIGh0dG9fcHJveHkgeHh4eGBcbiAgXTtcbiAgZm9yIChjb25zdCBzZXR0aW5nIG9mIGh0dHBQcm94eVNldHRpbnMpIHtcbiAgICBhd2FpdCB0aGlzLnNoZWxsKFsnc2V0dGluZ3MnLCAnZGVsZXRlJywgJ2dsb2JhbCcsIHNldHRpbmddKTtcbiAgfVxufTtcblxuLyoqXG4gKiBTZXQgZGV2aWNlIHByb3BlcnR5LlxuICogW2FuZHJvaWQucHJvdmlkZXIuU2V0dGluZ3Nde0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLmFuZHJvaWQuY29tL3JlZmVyZW5jZS9hbmRyb2lkL3Byb3ZpZGVyL1NldHRpbmdzLmh0bWx9XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVzcGFjZSAtIG9uZSBvZiB7c3lzdGVtLCBzZWN1cmUsIGdsb2JhbH0sIGNhc2UtaW5zZW5zaXRpdmUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc2V0dGluZyAtIHByb3BlcnR5IG5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IHZhbHVlIC0gcHJvcGVydHkgdmFsdWUuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IGNvbW1hbmQgb3V0cHV0LlxuICovXG5tZXRob2RzLnNldFNldHRpbmcgPSBhc3luYyBmdW5jdGlvbiBzZXRTZXR0aW5nIChuYW1lc3BhY2UsIHNldHRpbmcsIHZhbHVlKSB7XG4gIHJldHVybiBhd2FpdCB0aGlzLnNoZWxsKFsnc2V0dGluZ3MnLCAncHV0JywgbmFtZXNwYWNlLCBzZXR0aW5nLCB2YWx1ZV0pO1xufTtcblxuLyoqXG4gKiBHZXQgZGV2aWNlIHByb3BlcnR5LlxuICogW2FuZHJvaWQucHJvdmlkZXIuU2V0dGluZ3Nde0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLmFuZHJvaWQuY29tL3JlZmVyZW5jZS9hbmRyb2lkL3Byb3ZpZGVyL1NldHRpbmdzLmh0bWx9XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVzcGFjZSAtIG9uZSBvZiB7c3lzdGVtLCBzZWN1cmUsIGdsb2JhbH0sIGNhc2UtaW5zZW5zaXRpdmUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc2V0dGluZyAtIHByb3BlcnR5IG5hbWUuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IHByb3BlcnR5IHZhbHVlLlxuICovXG5tZXRob2RzLmdldFNldHRpbmcgPSBhc3luYyBmdW5jdGlvbiBnZXRTZXR0aW5nIChuYW1lc3BhY2UsIHNldHRpbmcpIHtcbiAgcmV0dXJuIGF3YWl0IHRoaXMuc2hlbGwoWydzZXR0aW5ncycsICdnZXQnLCBuYW1lc3BhY2UsIHNldHRpbmddKTtcbn07XG5cbi8qKlxuICogUmV0cmlldmUgdGhlIGBhZGIgYnVncmVwb3J0YCBjb21tYW5kIG91dHB1dC4gVGhpc1xuICogb3BlcmF0aW9uIG1heSB0YWtlIHVwIHRvIHNldmVyYWwgbWludXRlcy5cbiAqXG4gKiBAcGFyYW0gez9udW1iZXJ9IHRpbWVvdXQgWzEyMDAwMF0gLSBDb21tYW5kIHRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBDb21tYW5kIHN0ZG91dFxuICovXG5tZXRob2RzLmJ1Z3JlcG9ydCA9IGFzeW5jIGZ1bmN0aW9uIGJ1Z3JlcG9ydCAodGltZW91dCA9IDEyMDAwMCkge1xuICByZXR1cm4gYXdhaXQgdGhpcy5hZGJFeGVjKFsnYnVncmVwb3J0J10sIHt0aW1lb3V0fSk7XG59O1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFNjcmVlbnJlY29yZE9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7P3N0cmluZ30gdmlkZW9TaXplIC0gVGhlIGZvcm1hdCBpcyB3aWR0aHhoZWlnaHQuXG4gKiAgICAgICAgICAgICAgICAgIFRoZSBkZWZhdWx0IHZhbHVlIGlzIHRoZSBkZXZpY2UncyBuYXRpdmUgZGlzcGxheSByZXNvbHV0aW9uIChpZiBzdXBwb3J0ZWQpLFxuICogICAgICAgICAgICAgICAgICAxMjgweDcyMCBpZiBub3QuIEZvciBiZXN0IHJlc3VsdHMsXG4gKiAgICAgICAgICAgICAgICAgIHVzZSBhIHNpemUgc3VwcG9ydGVkIGJ5IHlvdXIgZGV2aWNlJ3MgQWR2YW5jZWQgVmlkZW8gQ29kaW5nIChBVkMpIGVuY29kZXIuXG4gKiAgICAgICAgICAgICAgICAgIEZvciBleGFtcGxlLCBcIjEyODB4NzIwXCJcbiAqIEBwcm9wZXJ0eSB7P2Jvb2xlYW59IGJ1Z1JlcG9ydCAtIFNldCBpdCB0byBgdHJ1ZWAgaW4gb3JkZXIgdG8gZGlzcGxheSBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIG9uIHRoZSB2aWRlbyBvdmVybGF5LFxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VjaCBhcyBhIHRpbWVzdGFtcCwgdGhhdCBpcyBoZWxwZnVsIGluIHZpZGVvcyBjYXB0dXJlZCB0byBpbGx1c3RyYXRlIGJ1Z3MuXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUaGlzIG9wdGlvbiBpcyBvbmx5IHN1cHBvcnRlZCBzaW5jZSBBUEkgbGV2ZWwgMjcgKEFuZHJvaWQgUCkuXG4gKiBAcHJvcGVydHkgez9zdHJpbmd8bnVtYmVyfSB0aW1lTGltaXQgLSBUaGUgbWF4aW11bSByZWNvcmRpbmcgdGltZSwgaW4gc2Vjb25kcy5cbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRoZSBkZWZhdWx0IChhbmQgbWF4aW11bSkgdmFsdWUgaXMgMTgwICgzIG1pbnV0ZXMpLlxuICogQHByb3BlcnR5IHs/c3RyaW5nfG51bWJlcn0gYml0UmF0ZSAtIFRoZSB2aWRlbyBiaXQgcmF0ZSBmb3IgdGhlIHZpZGVvLCBpbiBtZWdhYml0cyBwZXIgc2Vjb25kLlxuICogICAgICAgICAgICAgICAgVGhlIGRlZmF1bHQgdmFsdWUgaXMgNC4gWW91IGNhbiBpbmNyZWFzZSB0aGUgYml0IHJhdGUgdG8gaW1wcm92ZSB2aWRlbyBxdWFsaXR5LFxuICogICAgICAgICAgICAgICAgYnV0IGRvaW5nIHNvIHJlc3VsdHMgaW4gbGFyZ2VyIG1vdmllIGZpbGVzLlxuICovXG5cbi8qKlxuICogSW5pdGlhdGUgc2NyZWVucmVjb3JkIHV0aWxpdHkgb24gdGhlIGRldmljZVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBkZXN0aW5hdGlvbiAtIEZ1bGwgcGF0aCB0byB0aGUgd3JpdGFibGUgbWVkaWEgZmlsZSBkZXN0aW5hdGlvblxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb24gdGhlIGRldmljZSBmaWxlIHN5c3RlbS5cbiAqIEBwYXJhbSB7P1NjcmVlbnJlY29yZE9wdGlvbnN9IG9wdGlvbnMgW3t9XVxuICogQHJldHVybnMge1N1YlByb2Nlc3N9IHNjcmVlbnJlY29yZCBwcm9jZXNzLCB3aGljaCBjYW4gYmUgdGhlbiBjb250cm9sbGVkIGJ5IHRoZSBjbGllbnQgY29kZVxuICovXG5tZXRob2RzLnNjcmVlbnJlY29yZCA9IGZ1bmN0aW9uIHNjcmVlbnJlY29yZCAoZGVzdGluYXRpb24sIG9wdGlvbnMgPSB7fSkge1xuICBjb25zdCBjbWQgPSBbJ3NjcmVlbnJlY29yZCddO1xuICBjb25zdCB7XG4gICAgdmlkZW9TaXplLFxuICAgIGJpdFJhdGUsXG4gICAgdGltZUxpbWl0LFxuICAgIGJ1Z1JlcG9ydCxcbiAgfSA9IG9wdGlvbnM7XG4gIGlmICh1dGlsLmhhc1ZhbHVlKHZpZGVvU2l6ZSkpIHtcbiAgICBjbWQucHVzaCgnLS1zaXplJywgdmlkZW9TaXplKTtcbiAgfVxuICBpZiAodXRpbC5oYXNWYWx1ZSh0aW1lTGltaXQpKSB7XG4gICAgY21kLnB1c2goJy0tdGltZS1saW1pdCcsIHRpbWVMaW1pdCk7XG4gIH1cbiAgaWYgKHV0aWwuaGFzVmFsdWUoYml0UmF0ZSkpIHtcbiAgICBjbWQucHVzaCgnLS1iaXQtcmF0ZScsIGJpdFJhdGUpO1xuICB9XG4gIGlmIChidWdSZXBvcnQpIHtcbiAgICBjbWQucHVzaCgnLS1idWdyZXBvcnQnKTtcbiAgfVxuICBjbWQucHVzaChkZXN0aW5hdGlvbik7XG5cbiAgY29uc3QgZnVsbENtZCA9IFtcbiAgICAuLi50aGlzLmV4ZWN1dGFibGUuZGVmYXVsdEFyZ3MsXG4gICAgJ3NoZWxsJyxcbiAgICAuLi5jbWRcbiAgXTtcbiAgbG9nLmRlYnVnKGBCdWlsZGluZyBzY3JlZW5yZWNvcmQgcHJvY2VzcyB3aXRoIHRoZSBjb21tYW5kIGxpbmU6IGFkYiAke3V0aWwucXVvdGUoZnVsbENtZCl9YCk7XG4gIHJldHVybiBuZXcgU3ViUHJvY2Vzcyh0aGlzLmV4ZWN1dGFibGUucGF0aCwgZnVsbENtZCk7XG59O1xuXG4vKipcbiAqIEV4ZWN1dGVzIHRoZSBnaXZlbiBmdW5jdGlvbiB3aXRoIHRoZSBnaXZlbiBpbnB1dCBtZXRob2QgY29udGV4dFxuICogYW5kIHRoZW4gcmVzdG9yZXMgdGhlIElNRSB0byB0aGUgb3JpZ2luYWwgdmFsdWVcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaW1lIC0gVmFsaWQgSU1FIGlkZW50aWZpZXJcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIC0gRnVuY3Rpb24gdG8gZXhlY3V0ZVxuICogQHJldHVybnMgeyp9IFRoZSByZXN1bHQgb2YgdGhlIGdpdmVuIGZ1bmN0aW9uXG4gKi9cbm1ldGhvZHMucnVuSW5JbWVDb250ZXh0ID0gYXN5bmMgZnVuY3Rpb24gcnVuSW5JbWVDb250ZXh0IChpbWUsIGZuKSB7XG4gIGNvbnN0IG9yaWdpbmFsSW1lID0gYXdhaXQgdGhpcy5kZWZhdWx0SU1FKCk7XG4gIGlmIChvcmlnaW5hbEltZSA9PT0gaW1lKSB7XG4gICAgbG9nLmRlYnVnKGBUaGUgb3JpZ2luYWwgSU1FIGlzIHRoZSBzYW1lIGFzICcke2ltZX0nLiBUaGVyZSBpcyBubyBuZWVkIHRvIHJlc2V0IGl0YCk7XG4gIH0gZWxzZSB7XG4gICAgYXdhaXQgdGhpcy5lbmFibGVJTUUoaW1lKTtcbiAgICBhd2FpdCB0aGlzLnNldElNRShpbWUpO1xuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9hcHBpdW0vYXBwaXVtL2lzc3Vlcy8xNTk0M1xuICAgIGF3YWl0IEIuZGVsYXkoNTAwKTtcbiAgfVxuICB0cnkge1xuICAgIHJldHVybiBhd2FpdCBmbigpO1xuICB9IGZpbmFsbHkge1xuICAgIGlmIChvcmlnaW5hbEltZSAhPT0gaW1lKSB7XG4gICAgICBhd2FpdCB0aGlzLnNldElNRShvcmlnaW5hbEltZSk7XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIEdldCB0eiBkYXRhYmFzZSB0aW1lIHpvbmUgZm9ybWF0dGVkIHRpbWV6b25lXG4gKlxuICogQHJldHVybnMge3N0cmluZ30gVFogZGF0YWJhc2UgVGltZSBab25lcyBmb3JtYXRcbiAqXG4gKiBAdGhyb3dzIHtlcnJvcn0gSWYgYW55IGV4Y2VwdGlvbiBpcyByZXBvcnRlZCBieSBhZGIgc2hlbGwuXG4gKi9cbm1ldGhvZHMuZ2V0VGltZVpvbmUgPSBhc3luYyBmdW5jdGlvbiBnZXRUaW1lWm9uZSAoKSB7XG4gIGxvZy5kZWJ1ZygnR2V0dGluZyBjdXJyZW50IHRpbWV6b25lJyk7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuZ2V0RGV2aWNlUHJvcGVydHkoJ3BlcnNpc3Quc3lzLnRpbWV6b25lJyk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIGdldHRpbmcgdGltZXpvbmUuIE9yaWdpbmFsIGVycm9yOiAke2UubWVzc2FnZX1gKTtcbiAgfVxufTtcblxuLyoqXG4gKiBSZXRyaWV2ZXMgdGhlIGxpc3Qgb2YgZmVhdHVyZXMgc3VwcG9ydGVkIGJ5IHRoZSBkZXZpY2UgdW5kZXIgdGVzdFxuICpcbiAqIEByZXR1cm5zIHtBcnJheTxzdHJpbmc+fSB0aGUgbGlzdCBvZiBzdXBwb3J0ZWQgZmVhdHVyZSBuYW1lcyBvciBhbiBlbXB0eSBsaXN0LlxuICogQW4gZXhhbXBsZSBhZGIgY29tbWFuZCBvdXRwdXQ6XG4gKiBgYGBcbiAqIGNtZFxuICogbHNfdjJcbiAqIGZpeGVkX3B1c2hfbWtkaXJcbiAqIHNoZWxsX3YyXG4gKiBhYmJcbiAqIHN0YXRfdjJcbiAqIGFwZXhcbiAqIGFiYl9leGVjXG4gKiByZW1vdW50X3NoZWxsXG4gKiBmaXhlZF9wdXNoX3N5bWxpbmtfdGltZXN0YW1wXG4gKiBgYGBcbiAqIEB0aHJvd3Mge0Vycm9yfSBpZiB0aGVyZSB3YXMgYW4gZXJyb3Igd2hpbGUgcmV0cmlldmluZyB0aGUgbGlzdFxuICovXG5tZXRob2RzLmxpc3RGZWF0dXJlcyA9IGFzeW5jIGZ1bmN0aW9uIGxpc3RGZWF0dXJlcyAoKSB7XG4gIHRoaXMuX21lbW9pemVkRmVhdHVyZXMgPSB0aGlzLl9tZW1vaXplZEZlYXR1cmVzXG4gICAgfHwgXy5tZW1vaXplKGFzeW5jICgpID0+IGF3YWl0IHRoaXMuYWRiRXhlYyhbJ2ZlYXR1cmVzJ10pLCAoKSA9PiB0aGlzLmN1ckRldmljZUlkKTtcbiAgdHJ5IHtcbiAgICByZXR1cm4gKGF3YWl0IHRoaXMuX21lbW9pemVkRmVhdHVyZXMoKSlcbiAgICAgIC5zcGxpdCgvXFxzKy8pXG4gICAgICAubWFwKCh4KSA9PiB4LnRyaW0oKSlcbiAgICAgIC5maWx0ZXIoQm9vbGVhbik7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoXy5pbmNsdWRlcyhlLnN0ZGVyciwgJ3Vua25vd24gY29tbWFuZCcpKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIHRocm93IGU7XG4gIH1cbn07XG5cbi8qKlxuICogQ2hlY2tzIHRoZSBzdGF0ZSBvZiBzdHJlYW1lZCBpbnN0YWxsIGZlYXR1cmUuXG4gKiBUaGlzIGZlYXR1cmUgYWxsb3dzIHRvIHNwZWVkIHVwIGFwayBpbnN0YWxsYXRpb25cbiAqIHNpbmNlIGl0IGRvZXMgbm90IHJlcXVpcmUgdGhlIG9yaWdpbmFsIGFwayB0byBiZSBwdXNoZWQgdG9cbiAqIHRoZSBkZXZpY2UgdW5kZXIgdGVzdCBmaXJzdCwgd2hpY2ggYWxzbyBzYXZlcyBzcGFjZS5cbiAqIEFsdGhvdWdoLCBpdCBpcyByZXF1aXJlZCB0aGF0IGJvdGggdGhlIGRldmljZSB1bmRlciB0ZXN0XG4gKiBhbmQgdGhlIGFkYiBzZXJ2ZXIgaGF2ZSB0aGUgbWVudGlvbmVkIGZ1bmN0aW9uYWxpdHkuXG4gKiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2Fvc3AtbWlycm9yL3BsYXRmb3JtX3N5c3RlbV9jb3JlL2Jsb2IvbWFzdGVyL2FkYi9jbGllbnQvYWRiX2luc3RhbGwuY3BwXG4gKiBmb3IgbW9yZSBkZXRhaWxzXG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59IGB0cnVlYCBpZiB0aGUgZmVhdHVyZSBpcyBzdXBwb3J0ZWQgYnkgYm90aCBhZGIgYW5kIHRoZVxuICogZGV2aWNlIHVuZGVyIHRlc3RcbiAqL1xubWV0aG9kcy5pc1N0cmVhbWVkSW5zdGFsbFN1cHBvcnRlZCA9IGFzeW5jIGZ1bmN0aW9uIGlzU3RyZWFtZWRJbnN0YWxsU3VwcG9ydGVkICgpIHtcbiAgY29uc3QgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YodGhpcyk7XG4gIHByb3RvLl9oZWxwT3V0cHV0ID0gcHJvdG8uX2hlbHBPdXRwdXQgfHwgYXdhaXQgdGhpcy5hZGJFeGVjKFsnaGVscCddKTtcbiAgcmV0dXJuIHByb3RvLl9oZWxwT3V0cHV0LmluY2x1ZGVzKCctLXN0cmVhbWluZycpXG4gICAgJiYgKGF3YWl0IHRoaXMubGlzdEZlYXR1cmVzKCkpLmluY2x1ZGVzKCdjbWQnKTtcbn07XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgaW5jcmVtZW50YWwgaW5zdGFsbCBmZWF0dXJlIGlzIHN1cHBvcnRlZCBieSBBREIuXG4gKiBSZWFkIGh0dHBzOi8vZGV2ZWxvcGVyLmFuZHJvaWQuY29tL3ByZXZpZXcvZmVhdHVyZXMjaW5jcmVtZW50YWxcbiAqIGZvciBtb3JlIGRldGFpbHMgb24gaXQuXG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59IGB0cnVlYCBpZiB0aGUgZmVhdHVyZSBpcyBzdXBwb3J0ZWQgYnkgYm90aCBhZGIgYW5kIHRoZVxuICogZGV2aWNlIHVuZGVyIHRlc3RcbiAqL1xubWV0aG9kcy5pc0luY3JlbWVudGFsSW5zdGFsbFN1cHBvcnRlZCA9IGFzeW5jIGZ1bmN0aW9uIGlzSW5jcmVtZW50YWxJbnN0YWxsU3VwcG9ydGVkICgpIHtcbiAgY29uc3Qge2JpbmFyeX0gPSBhd2FpdCB0aGlzLmdldFZlcnNpb24oKTtcbiAgaWYgKCFiaW5hcnkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIHV0aWwuY29tcGFyZVZlcnNpb25zKGJpbmFyeS52ZXJzaW9uLCAnPj0nLCAnMzAuMC4xJylcbiAgICAmJiAoYXdhaXQgdGhpcy5saXN0RmVhdHVyZXMoKSkuaW5jbHVkZXMoJ2FiYl9leGVjJyk7XG59O1xuXG4vKipcbiAqIFJldHJpZXZlcyB0aGUgbGlzdCBvZiBwYWNrYWdlcyBmcm9tIERvemUgd2hpdGVsaXN0IG9uIEFuZHJvaWQgOCtcbiAqXG4gKiBAcmV0dXJucyB7QXJyYXk8c3RyaW5nPn0gVGhlIGxpc3Qgb2Ygd2hpdGVsaXN0ZWQgcGFja2FnZXMuIEFuIGV4YW1wbGUgb3V0cHV0OlxuICogc3lzdGVtLGNvbS5hbmRyb2lkLnNoZWxsLDIwMDBcbiAqIHN5c3RlbSxjb20uZ29vZ2xlLmFuZHJvaWQuY2VsbGJyb2FkY2FzdHJlY2VpdmVyLDEwMTQzXG4gKiB1c2VyLGlvLmFwcGl1bS5zZXR0aW5ncywxMDE1N1xuICovXG5tZXRob2RzLmdldERldmljZUlkbGVXaGl0ZWxpc3QgPSBhc3luYyBmdW5jdGlvbiBnZXREZXZpY2VJZGxlV2hpdGVsaXN0ICgpIHtcbiAgaWYgKGF3YWl0IHRoaXMuZ2V0QXBpTGV2ZWwoKSA8IDIzKSB7XG4gICAgLy8gRG96ZSBtb2RlIGhhcyBvbmx5IGJlZW4gYWRkZWQgc2luY2UgQW5kcm9pZCA2XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgbG9nLmluZm8oJ0xpc3RpbmcgcGFja2FnZXMgaW4gRG96ZSB3aGl0ZWxpc3QnKTtcbiAgY29uc3Qgb3V0cHV0ID0gYXdhaXQgdGhpcy5zaGVsbChbJ2R1bXBzeXMnLCAnZGV2aWNlaWRsZScsICd3aGl0ZWxpc3QnXSk7XG4gIHJldHVybiBfLnRyaW0ob3V0cHV0KS5zcGxpdCgvXFxuLylcbiAgICAubWFwKChsaW5lKSA9PiBfLnRyaW0obGluZSkpXG4gICAgLmZpbHRlcihCb29sZWFuKTtcbn07XG5cbi8qKlxuICogQWRkcyBhbiBleGlzdGluZyBwYWNrYWdlKHMpIGludG8gdGhlIERvemUgd2hpdGVsaXN0IG9uIEFuZHJvaWQgOCtcbiAqXG4gKiBAcGFyYW0gIHsuLi5zdHJpbmd9IHBhY2thZ2VzIE9uZSBvciBtb3JlIHBhY2thZ2VzIHRvIGFkZC4gSWYgdGhlIHBhY2thZ2VcbiAqIGFscmVhZHkgZXhpc3RzIGluIHRoZSB3aGl0ZWxpc3QgdGhlbiBpdCBpcyBvbmx5IGdvaW5nIHRvIGJlIGFkZGVkIG9uY2UuXG4gKiBJZiB0aGUgcGFja2FnZSB3aXRoIHRoZSBnaXZlbiBuYW1lIGlzIG5vdCBpbnN0YWxsZWQvbm90IGtub3duIHRoZW4gYW4gZXJyb3JcbiAqIHdpbGwgYmUgdGhyb3duLlxuICogQHJldHVybnMge0Jvb2xlYW59IGB0cnVlYCBpZiB0aGUgY29tbWFuZCB0byBhZGQgcGFja2FnZShzKSBoYXMgYmVlbiBleGVjdXRlZFxuICovXG5tZXRob2RzLmFkZFRvRGV2aWNlSWRsZVdoaXRlbGlzdCA9IGFzeW5jIGZ1bmN0aW9uIGFkZFRvRGV2aWNlSWRsZVdoaXRlbGlzdCAoLi4ucGFja2FnZXMpIHtcbiAgaWYgKF8uaXNFbXB0eShwYWNrYWdlcykgfHwgYXdhaXQgdGhpcy5nZXRBcGlMZXZlbCgpIDwgMjMpIHtcbiAgICAvLyBEb3plIG1vZGUgaGFzIG9ubHkgYmVlbiBhZGRlZCBzaW5jZSBBbmRyb2lkIDZcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBsb2cuaW5mbyhgQWRkaW5nICR7dXRpbC5wbHVyYWxpemUoJ3BhY2thZ2UnLCBwYWNrYWdlcy5sZW5ndGgpfSAke0pTT04uc3RyaW5naWZ5KHBhY2thZ2VzKX0gdG8gRG96ZSB3aGl0ZWxpc3RgKTtcbiAgYXdhaXQgdGhpcy5zaGVsbENodW5rcygocGtnKSA9PiBbJ2R1bXBzeXMnLCAnZGV2aWNlaWRsZScsICd3aGl0ZWxpc3QnLCBgKyR7cGtnfWBdLCBwYWNrYWdlcyk7XG4gIHJldHVybiB0cnVlO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgbWV0aG9kcztcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFJQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFFQSxNQUFNQSx1QkFBdUIsR0FBRyxJQUFoQztBQUNBLE1BQU1DLHlCQUF5QixHQUFHLG1DQUFsQztBQUNBLE1BQU1DLG1CQUFtQixHQUFHLENBQzFCRCx5QkFEMEIsRUFFMUIscUJBRjBCLENBQTVCO0FBSUEsTUFBTUUscUJBQXFCLEdBQUcsRUFBOUI7QUFDQSxNQUFNQyxzQkFBc0IsR0FBRyxDQUM3Qiw4QkFENkIsRUFFN0IsMEJBRjZCLEVBRzdCLG1CQUg2QixDQUEvQjtBQUtBLE1BQU1DLGdCQUFnQixHQUFHLEtBQXpCO0FBQ0EsTUFBTUMseUJBQXlCLEdBQUcsTUFBbEM7QUFDQSxNQUFNQyxnQkFBZ0IsR0FBRyxJQUFJQyxNQUFKLENBQVksVUFBU0gsZ0JBQWlCLFdBQVVDLHlCQUEwQixTQUExRSxFQUFvRixHQUFwRixDQUF6QjtBQUVBLE1BQU1HLHdCQUF3QixHQUFHLG1CQUFqQztBQUVBLE1BQU1DLE9BQU8sR0FBRyxFQUFoQjs7QUFnQkFBLE9BQU8sQ0FBQ0MsV0FBUixHQUFzQixlQUFlQSxXQUFmLENBQTRCQyxjQUE1QixFQUE0Q0MsSUFBNUMsRUFBa0Q7RUFDdEUsTUFBTUMsUUFBUSxHQUFHLEVBQWpCO0VBQ0EsSUFBSUMsUUFBUSxHQUFHLEVBQWY7O0VBQ0EsS0FBSyxNQUFNQyxHQUFYLElBQWtCSCxJQUFsQixFQUF3QjtJQUN0QixNQUFNSSxPQUFPLEdBQUdMLGNBQWMsQ0FBQ0ksR0FBRCxDQUE5Qjs7SUFDQSxJQUFJLENBQUNFLGVBQUEsQ0FBRUMs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
|