adb-commands.js 166 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

require("source-map-support/register");

var _logger = _interopRequireDefault(require("../logger.js"));

var _helpers = require("../helpers.js");

var _path = _interopRequireDefault(require("path"));

var _lodash = _interopRequireDefault(require("lodash"));

var _appiumSupport = require("appium-support");

var _net = _interopRequireDefault(require("net"));

var _os = require("os");

var _logcat = _interopRequireDefault(require("../logcat"));

var _asyncbox = require("asyncbox");

var _teen_process = require("teen_process");

var _bluebird = _interopRequireDefault(require("bluebird"));

const MAX_SHELL_BUFFER_LENGTH = 1000;
const NOT_CHANGEABLE_PERM_ERROR = /not a changeable permission type/i;
const IGNORED_PERM_ERRORS = [NOT_CHANGEABLE_PERM_ERROR, /Unknown permission/i];
const MAX_PGREP_PATTERN_LEN = 15;
const HIDDEN_API_POLICY_KEYS = ['hidden_api_policy_pre_p_apps', 'hidden_api_policy_p_apps', 'hidden_api_policy'];
const PID_COLUMN_TITLE = 'PID';
const PROCESS_NAME_COLUMN_TITLE = 'NAME';
const PS_TITLE_PATTERN = new RegExp(`^(.*\\b${PID_COLUMN_TITLE}\\b.*\\b${PROCESS_NAME_COLUMN_TITLE}\\b.*)$`, 'm');
let methods = {};

methods.getAdbWithCorrectAdbPath = async function getAdbWithCorrectAdbPath() {
  this.executable.path = await this.getSdkBinaryPath('adb');
  return this.adb;
};

methods.initAapt = async function initAapt() {
  await this.getSdkBinaryPath('aapt');
};

methods.initAapt2 = async function initAapt2() {
  await this.getSdkBinaryPath('aapt2');
};

methods.initZipAlign = async function initZipAlign() {
  await this.getSdkBinaryPath('zipalign');
};

methods.initBundletool = async function initBundletool() {
  try {
    this.binaries.bundletool = await _appiumSupport.fs.which('bundletool.jar');
  } catch (err) {
    throw new Error('bundletool.jar binary is expected to be present in PATH. ' + 'Visit https://github.com/google/bundletool for more details.');
  }
};

methods.getApiLevel = async function getApiLevel() {
  if (!_lodash.default.isInteger(this._apiLevel)) {
    try {
      const strOutput = await this.getDeviceProperty('ro.build.version.sdk');
      let apiLevel = parseInt(strOutput.trim(), 10);
      const charCodeQ = 'q'.charCodeAt(0);
      const apiLevelDiff = apiLevel - 28;
      const codename = String.fromCharCode(charCodeQ + apiLevelDiff);

      if (apiLevelDiff >= 0 && (await this.getPlatformVersion()).toLowerCase() === codename) {
        _logger.default.debug(`Release version is ${codename.toUpperCase()} but found API Level ${apiLevel}. Setting API Level to ${apiLevel + 1}`);

        apiLevel++;
      }

      this._apiLevel = apiLevel;

      _logger.default.debug(`Device API level: ${this._apiLevel}`);

      if (isNaN(this._apiLevel)) {
        throw new Error(`The actual output '${strOutput}' cannot be converted to an integer`);
      }
    } catch (e) {
      throw new Error(`Error getting device API level. Original error: ${e.message}`);
    }
  }

  return this._apiLevel;
};

methods.getPlatformVersion = async function getPlatformVersion() {
  _logger.default.info('Getting device platform version');

  try {
    return await this.getDeviceProperty('ro.build.version.release');
  } catch (e) {
    throw new Error(`Error getting device platform version. Original error: ${e.message}`);
  }
};

methods.isDeviceConnected = async function isDeviceConnected() {
  let devices = await this.getConnectedDevices();
  return devices.length > 0;
};

methods.mkdir = async function mkdir(remotePath) {
  return await this.shell(['mkdir', '-p', remotePath]);
};

methods.isValidClass = function isValidClass(classString) {
  return new RegExp(/^[a-zA-Z0-9./_]+$/).exec(classString);
};

methods.forceStop = async function forceStop(pkg) {
  return await this.shell(['am', 'force-stop', pkg]);
};

methods.killPackage = async function killPackage(pkg) {
  return await this.shell(['am', 'kill', pkg]);
};

methods.clear = async function clear(pkg) {
  return await this.shell(['pm', 'clear', pkg]);
};

methods.grantAllPermissions = async function grantAllPermissions(pkg, apk) {
  const apiLevel = await this.getApiLevel();
  let targetSdk = 0;
  let dumpsysOutput = null;

  try {
    if (!apk) {
      dumpsysOutput = await this.shell(['dumpsys', 'package', pkg]);
      targetSdk = await this.targetSdkVersionUsingPKG(pkg, dumpsysOutput);
    } else {
      targetSdk = await this.targetSdkVersionFromManifest(apk);
    }
  } catch (e) {
    _logger.default.warn(`Ran into problem getting target SDK version; ignoring...`);
  }

  if (apiLevel >= 23 && targetSdk >= 23) {
    dumpsysOutput = dumpsysOutput || (await this.shell(['dumpsys', 'package', pkg]));
    const requestedPermissions = await this.getReqPermissions(pkg, dumpsysOutput);
    const grantedPermissions = await this.getGrantedPermissions(pkg, dumpsysOutput);

    const permissionsToGrant = _lodash.default.difference(requestedPermissions, grantedPermissions);

    if (_lodash.default.isEmpty(permissionsToGrant)) {
      _logger.default.info(`${pkg} contains no permissions available for granting`);
    } else {
      await this.grantPermissions(pkg, permissionsToGrant);
    }
  }
};

methods.grantPermissions = async function grantPermissions(pkg, permissions) {
  _logger.default.debug(`Granting permissions ${JSON.stringify(permissions)} to '${pkg}'`);

  const commands = [];
  let cmdChunk = [];

  for (const permission of permissions) {
    const nextCmd = ['pm', 'grant', pkg, permission, ';'];

    if (nextCmd.join(' ').length + cmdChunk.join(' ').length >= MAX_SHELL_BUFFER_LENGTH) {
      commands.push(cmdChunk);
      cmdChunk = [];
    }

    cmdChunk = [...cmdChunk, ...nextCmd];
  }

  if (!_lodash.default.isEmpty(cmdChunk)) {
    commands.push(cmdChunk);
  }

  _logger.default.debug(`Got the following command chunks to execute: ${JSON.stringify(commands)}`);

  let lastError = null;

  for (const cmd of commands) {
    try {
      await this.shell(cmd);
    } catch (e) {
      if (!IGNORED_PERM_ERRORS.some(msgRegex => msgRegex.test(e.stderr || e.message))) {
        lastError = e;
      }
    }
  }

  if (lastError) {
    throw lastError;
  }
};

methods.grantPermission = async function grantPermission(pkg, permission) {
  try {
    await this.shell(['pm', 'grant', pkg, permission]);
  } catch (e) {
    if (!NOT_CHANGEABLE_PERM_ERROR.test(e.stderr || e.message)) {
      throw e;
    }
  }
};

methods.revokePermission = async function revokePermission(pkg, permission) {
  try {
    await this.shell(['pm', 'revoke', pkg, permission]);
  } catch (e) {
    if (!NOT_CHANGEABLE_PERM_ERROR.test(e.stderr || e.message)) {
      throw e;
    }
  }
};

methods.getGrantedPermissions = async function getGrantedPermissions(pkg, cmdOutput = null) {
  _logger.default.debug('Retrieving granted permissions');

  const stdout = cmdOutput || (await this.shell(['dumpsys', 'package', pkg]));
  return (0, _helpers.extractMatchingPermissions)(stdout, ['install', 'runtime'], true);
};

methods.getDeniedPermissions = async function getDeniedPermissions(pkg, cmdOutput = null) {
  _logger.default.debug('Retrieving denied permissions');

  const stdout = cmdOutput || (await this.shell(['dumpsys', 'package', pkg]));
  return (0, _helpers.extractMatchingPermissions)(stdout, ['install', 'runtime'], false);
};

methods.getReqPermissions = async function getReqPermissions(pkg, cmdOutput = null) {
  _logger.default.debug('Retrieving requested permissions');

  const stdout = cmdOutput || (await this.shell(['dumpsys', 'package', pkg]));
  return (0, _helpers.extractMatchingPermissions)(stdout, ['requested']);
};

methods.getLocationProviders = async function getLocationProviders() {
  let stdout = await this.getSetting('secure', 'location_providers_allowed');
  return stdout.trim().split(',').map(p => p.trim()).filter(Boolean);
};

methods.toggleGPSLocationProvider = async function toggleGPSLocationProvider(enabled) {
  await this.setSetting('secure', 'location_providers_allowed', `${enabled ? '+' : '-'}gps`);
};

methods.setHiddenApiPolicy = async function setHiddenApiPolicy(value, ignoreError = false) {
  try {
    await this.shell(HIDDEN_API_POLICY_KEYS.map(k => `settings put global ${k} ${value}`).join(';'));
  } catch (e) {
    if (!ignoreError) {
      throw e;
    }

    _logger.default.info(`Failed to set setting keys '${HIDDEN_API_POLICY_KEYS}' to '${value}'. Original error: ${e.message}`);
  }
};

methods.setDefaultHiddenApiPolicy = async function setDefaultHiddenApiPolicy(ignoreError = false) {
  try {
    await this.shell(HIDDEN_API_POLICY_KEYS.map(k => `settings delete global ${k}`).join(';'));
  } catch (e) {
    if (!ignoreError) {
      throw e;
    }

    _logger.default.info(`Failed to delete keys '${HIDDEN_API_POLICY_KEYS}'. Original error: ${e.message}`);
  }
};

methods.stopAndClear = async function stopAndClear(pkg) {
  try {
    await this.forceStop(pkg);
    await this.clear(pkg);
  } catch (e) {
    throw new Error(`Cannot stop and clear ${pkg}. Original error: ${e.message}`);
  }
};

methods.availableIMEs = async function availableIMEs() {
  try {
    return (0, _helpers.getIMEListFromOutput)(await this.shell(['ime', 'list', '-a']));
  } catch (e) {
    throw new Error(`Error getting available IME's. Original error: ${e.message}`);
  }
};

methods.enabledIMEs = async function enabledIMEs() {
  try {
    return (0, _helpers.getIMEListFromOutput)(await this.shell(['ime', 'list']));
  } catch (e) {
    throw new Error(`Error getting enabled IME's. Original error: ${e.message}`);
  }
};

methods.enableIME = async function enableIME(imeId) {
  await this.shell(['ime', 'enable', imeId]);
};

methods.disableIME = async function disableIME(imeId) {
  await this.shell(['ime', 'disable', imeId]);
};

methods.setIME = async function setIME(imeId) {
  await this.shell(['ime', 'set', imeId]);
};

methods.defaultIME = async function defaultIME() {
  try {
    let engine = await this.getSetting('secure', 'default_input_method');

    if (engine === 'null') {
      return null;
    }

    return engine.trim();
  } catch (e) {
    throw new Error(`Error getting default IME. Original error: ${e.message}`);
  }
};

methods.keyevent = async function keyevent(keycode) {
  let code = parseInt(keycode, 10);
  await this.shell(['input', 'keyevent', code]);
};

methods.inputText = async function inputText(text) {
  text = text.replace(/\\/g, '\\\\').replace(/\(/g, '\(').replace(/\)/g, '\)').replace(/</g, '\<').replace(/>/g, '\>').replace(/\|/g, '\|').replace(/;/g, '\;').replace(/&/g, '\&').replace(/\*/g, '\*').replace(/~/g, '\~').replace(/"/g, '\"').replace(/'/g, "\'").replace(/ /g, '%s');
  await this.shell(['input', 'text', text]);
};

methods.clearTextField = async function clearTextField(length = 100) {
  _logger.default.debug(`Clearing up to ${length} characters`);

  if (length === 0) {
    return;
  }

  let args = ['input', 'keyevent'];

  for (let i = 0; i < length; i++) {
    args.push('67', '112');
  }

  await this.shell(args);
};

methods.lock = async function lock() {
  if (await this.isScreenLocked()) {
    _logger.default.debug('Screen is already locked. Doing nothing.');

    return;
  }

  _logger.default.debug('Pressing the KEYCODE_POWER button to lock screen');

  await this.keyevent(26);
  const timeoutMs = 5000;

  try {
    await (0, _asyncbox.waitForCondition)(async () => await this.isScreenLocked(), {
      waitMs: timeoutMs,
      intervalMs: 500
    });
  } catch (e) {
    throw new Error(`The device screen is still locked after ${timeoutMs}ms timeout`);
  }
};

methods.back = async function back() {
  _logger.default.debug('Pressing the BACK button');

  await this.keyevent(4);
};

methods.goToHome = async function goToHome() {
  _logger.default.debug('Pressing the HOME button');

  await this.keyevent(3);
};

methods.getAdbPath = function getAdbPath() {
  return this.executable.path;
};

methods.getScreenOrientation = async function getScreenOrientation() {
  let stdout = await this.shell(['dumpsys', 'input']);
  return (0, _helpers.getSurfaceOrientation)(stdout);
};

methods.isScreenLocked = async function isScreenLocked() {
  let stdout = await this.shell(['dumpsys', 'window']);

  if (process.env.APPIUM_LOG_DUMPSYS) {
    let dumpsysFile = _path.default.resolve(process.cwd(), 'dumpsys.log');

    _logger.default.debug(`Writing dumpsys output to ${dumpsysFile}`);

    await _appiumSupport.fs.writeFile(dumpsysFile, stdout);
  }

  return (0, _helpers.isShowingLockscreen)(stdout) || (0, _helpers.isCurrentFocusOnKeyguard)(stdout) || !(0, _helpers.isScreenOnFully)(stdout);
};

methods.isSoftKeyboardPresent = async function isSoftKeyboardPresent() {
  try {
    const stdout = await this.shell(['dumpsys', 'input_method']);
    const inputShownMatch = /mInputShown=(\w+)/.exec(stdout);
    const inputViewShownMatch = /mIsInputViewShown=(\w+)/.exec(stdout);
    return {
      isKeyboardShown: !!(inputShownMatch && inputShownMatch[1] === 'true'),
      canCloseKeyboard: !!(inputViewShownMatch && inputViewShownMatch[1] === 'true')
    };
  } catch (e) {
    throw new Error(`Error finding softkeyboard. Original error: ${e.message}`);
  }
};

methods.sendTelnetCommand = async function sendTelnetCommand(command) {
  _logger.default.debug(`Sending telnet command to device: ${command}`);

  let port = await this.getEmulatorPort();
  return await new _bluebird.default((resolve, reject) => {
    let conn = _net.default.createConnection(port, 'localhost'),
        connected = false,
        readyRegex = /^OK$/m,
        dataStream = '',
        res = null;

    conn.on('connect', () => {
      _logger.default.debug('Socket connection to device created');
    });
    conn.on('data', data => {
      data = data.toString('utf8');

      if (!connected) {
        if (readyRegex.test(data)) {
          connected = true;

          _logger.default.debug('Socket connection to device ready');

          conn.write(`${command}\n`);
        }
      } else {
        dataStream += data;

        if (readyRegex.test(data)) {
          res = dataStream.replace(readyRegex, '').trim();
          res = _lodash.default.last(res.trim().split('\n'));

          _logger.default.debug(`Telnet command got response: ${res}`);

          conn.write('quit\n');
        }
      }
    });
    conn.on('error', err => {
      _logger.default.debug(`Telnet command error: ${err.message}`);

      reject(err);
    });
    conn.on('close', () => {
      if (res === null) {
        reject(new Error('Never got a response from command'));
      } else {
        resolve(res);
      }
    });
  });
};

methods.isAirplaneModeOn = async function isAirplaneModeOn() {
  let stdout = await this.getSetting('global', 'airplane_mode_on');
  return parseInt(stdout, 10) !== 0;
};

methods.setAirplaneMode = async function setAirplaneMode(on) {
  await this.setSetting('global', 'airplane_mode_on', on ? 1 : 0);
};

methods.broadcastAirplaneMode = async function broadcastAirplaneMode(on) {
  await this.shell(['am', 'broadcast', '-a', 'android.intent.action.AIRPLANE_MODE', '--ez', 'state', on ? 'true' : 'false']);
};

methods.isWifiOn = async function isWifiOn() {
  let stdout = await this.getSetting('global', 'wifi_on');
  return parseInt(stdout, 10) !== 0;
};

methods.isDataOn = async function isDataOn() {
  let stdout = await this.getSetting('global', 'mobile_data');
  return parseInt(stdout, 10) !== 0;
};

methods.setWifiAndData = async function setWifiAndData({
  wifi,
  data
}, isEmulator = false) {
  if (_appiumSupport.util.hasValue(wifi)) {
    await this.setWifiState(wifi, isEmulator);
  }

  if (_appiumSupport.util.hasValue(data)) {
    await this.setDataState(data, isEmulator);
  }
};

methods.isAnimationOn = async function isAnimationOn() {
  let animator_duration_scale = await this.getSetting('global', 'animator_duration_scale');
  let transition_animation_scale = await this.getSetting('global', 'transition_animation_scale');
  let window_animation_scale = await this.getSetting('global', 'window_animation_scale');
  return _lodash.default.some([animator_duration_scale, transition_animation_scale, window_animation_scale], setting => setting !== '0.0');
};

methods.rimraf = async function rimraf(path) {
  await this.shell(['rm', '-rf', path]);
};

methods.push = async function push(localPath, remotePath, opts) {
  await this.mkdir(_path.default.posix.dirname(remotePath));
  await this.adbExec(['push', localPath, remotePath], opts);
};

methods.pull = async function pull(remotePath, localPath) {
  await this.adbExec(['pull', remotePath, localPath], {
    timeout: 60000
  });
};

methods.processExists = async function processExists(processName) {
  return !_lodash.default.isEmpty(await this.getPIDsByName(processName));
};

methods.getForwardList = async function getForwardList() {
  _logger.default.debug(`List forwarding ports`);

  const connections = await this.adbExec(['forward', '--list']);
  return connections.split(_os.EOL).filter(line => Boolean(line.trim()));
};

methods.forwardPort = async function forwardPort(systemPort, devicePort) {
  _logger.default.debug(`Forwarding system: ${systemPort} to device: ${devicePort}`);

  await this.adbExec(['forward', `tcp:${systemPort}`, `tcp:${devicePort}`]);
};

methods.removePortForward = async function removePortForward(systemPort) {
  _logger.default.debug(`Removing forwarded port socket connection: ${systemPort} `);

  await this.adbExec(['forward', `--remove`, `tcp:${systemPort}`]);
};

methods.getReverseList = async function getReverseList() {
  _logger.default.debug(`List reverse forwarding ports`);

  const connections = await this.adbExec(['reverse', '--list']);
  return connections.split(_os.EOL).filter(line => Boolean(line.trim()));
};

methods.reversePort = async function reversePort(devicePort, systemPort) {
  _logger.default.debug(`Forwarding device: ${devicePort} to system: ${systemPort}`);

  await this.adbExec(['reverse', `tcp:${devicePort}`, `tcp:${systemPort}`]);
};

methods.removePortReverse = async function removePortReverse(devicePort) {
  _logger.default.debug(`Removing reverse forwarded port socket connection: ${devicePort} `);

  await this.adbExec(['reverse', `--remove`, `tcp:${devicePort}`]);
};

methods.forwardAbstractPort = async function forwardAbstractPort(systemPort, devicePort) {
  _logger.default.debug(`Forwarding system: ${systemPort} to abstract device: ${devicePort}`);

  await this.adbExec(['forward', `tcp:${systemPort}`, `localabstract:${devicePort}`]);
};

methods.ping = async function ping() {
  let stdout = await this.shell(['echo', 'ping']);

  if (stdout.indexOf('ping') === 0) {
    return true;
  }

  throw new Error(`ADB ping failed, returned ${stdout}`);
};

methods.restart = async function restart() {
  try {
    await this.stopLogcat();
    await this.restartAdb();
    await this.waitForDevice(60);
    await this.startLogcat();
  } catch (e) {
    throw new Error(`Restart failed. Original error: ${e.message}`);
  }
};

methods.startLogcat = async function startLogcat() {
  if (!_lodash.default.isEmpty(this.logcat)) {
    throw new Error("Trying to start logcat capture but it's already started!");
  }

  this.logcat = new _logcat.default({
    adb: this.executable,
    debug: false,
    debugTrace: false,
    clearDeviceLogsOnStart: !!this.clearDeviceLogsOnStart
  });
  await this.logcat.startCapture();
};

methods.stopLogcat = async function stopLogcat() {
  if (_lodash.default.isEmpty(this.logcat)) {
    return;
  }

  try {
    await this.logcat.stopCapture();
  } finally {
    this.logcat = null;
  }
};

methods.getLogcatLogs = function getLogcatLogs() {
  if (_lodash.default.isEmpty(this.logcat)) {
    throw new Error("Can't get logcat logs since logcat hasn't started");
  }

  return this.logcat.getLogs();
};

methods.setLogcatListener = function setLogcatListener(listener) {
  if (_lodash.default.isEmpty(this.logcat)) {
    throw new Error("Logcat process hasn't been started");
  }

  this.logcat.on('output', listener);
};

methods.removeLogcatListener = function removeLogcatListener(listener) {
  if (_lodash.default.isEmpty(this.logcat)) {
    throw new Error("Logcat process hasn't been started");
  }

  this.logcat.removeListener('output', listener);
};

methods.getNameByPid = async function getNameByPid(pid) {
  if (isNaN(pid)) {
    throw new Error(`The PID value must be a valid number. '${pid}' is given instead`);
  }

  pid = parseInt(pid, 10);
  const stdout = await this.shell(['ps']);
  const titleMatch = PS_TITLE_PATTERN.exec(stdout);

  if (!titleMatch) {
    _logger.default.debug(stdout);

    throw new Error(`Could not get the process name for PID '${pid}'`);
  }

  const allTitles = titleMatch[1].trim().split(/\s+/);
  const pidIndex = allTitles.indexOf(PID_COLUMN_TITLE);
  const nameOffset = allTitles.indexOf(PROCESS_NAME_COLUMN_TITLE) - allTitles.length;
  const pidRegex = new RegExp(`^(.*\\b${pid}\\b.*)$`, 'gm');
  let matchedLine;

  while (matchedLine = pidRegex.exec(stdout)) {
    const items = matchedLine[1].trim().split(/\s+/);

    if (parseInt(items[pidIndex], 10) === pid && items[items.length + nameOffset]) {
      return items[items.length + nameOffset];
    }
  }

  _logger.default.debug(stdout);

  throw new Error(`Could not get the process name for PID '${pid}'`);
};

methods.getPIDsByName = async function getPIDsByName(name) {
  _logger.default.debug(`Getting IDs of all '${name}' processes`);

  if (!this.isValidClass(name)) {
    throw new Error(`Invalid process name: '${name}'`);
  }

  if ((await this.getApiLevel()) >= 23) {
    if (!_lodash.default.isBoolean(this._isPgrepAvailable)) {
      const pgrepOutput = _lodash.default.trim(await this.shell(['pgrep --help; echo $?']));

      this._isPgrepAvailable = parseInt(_lodash.default.last(pgrepOutput.split(/\s+/)), 10) === 0;

      if (this._isPgrepAvailable) {
        this._canPgrepUseFullCmdLineSearch = /^-f\b/m.test(pgrepOutput);
      } else {
        this._isPidofAvailable = parseInt(await this.shell(['pidof --help > /dev/null; echo $?']), 10) === 0;
      }
    }

    if (this._isPgrepAvailable || this._isPidofAvailable) {
      const shellCommand = this._isPgrepAvailable ? this._canPgrepUseFullCmdLineSearch ? ['pgrep', '-f', _lodash.default.escapeRegExp(name)] : [`pgrep ^${_lodash.default.escapeRegExp(name.slice(-MAX_PGREP_PATTERN_LEN))}$ || pgrep ^${_lodash.default.escapeRegExp(name.slice(0, MAX_PGREP_PATTERN_LEN))}$`] : ['pidof', name];

      try {
        return (await this.shell(shellCommand)).split(/\s+/).map(x => parseInt(x, 10)).filter(x => _lodash.default.isInteger(x));
      } catch (e) {
        if (e.code === 1) {
          return [];
        }

        throw new Error(`Could not extract process ID of '${name}': ${e.message}`);
      }
    }
  }

  _logger.default.debug('Using ps-based PID detection');

  const stdout = await this.shell(['ps']);
  const titleMatch = PS_TITLE_PATTERN.exec(stdout);

  if (!titleMatch) {
    _logger.default.debug(stdout);

    throw new Error(`Could not extract PID of '${name}' from ps output`);
  }

  const allTitles = titleMatch[1].trim().split(/\s+/);
  const pidIndex = allTitles.indexOf(PID_COLUMN_TITLE);
  const pids = [];
  const processNameRegex = new RegExp(`^(.*\\b\\d+\\b.*\\b${_lodash.default.escapeRegExp(name)}\\b.*)$`, 'gm');
  let matchedLine;

  while (matchedLine = processNameRegex.exec(stdout)) {
    const items = matchedLine[1].trim().split(/\s+/);

    if (pidIndex >= allTitles.length || isNaN(items[pidIndex])) {
      _logger.default.debug(stdout);

      throw new Error(`Could not extract PID of '${name}' from '${matchedLine[1].trim()}'`);
    }

    pids.push(parseInt(items[pidIndex], 10));
  }

  return pids;
};

methods.killProcessesByName = async function killProcessesByName(name) {
  try {
    _logger.default.debug(`Attempting to kill all ${name} processes`);

    let pids = await this.getPIDsByName(name);

    if (_lodash.default.isEmpty(pids)) {
      _logger.default.info(`No '${name}' process has been found`);

      return;
    }

    for (let pid of pids) {
      await this.killProcessByPID(pid);
    }
  } catch (e) {
    throw new Error(`Unable to kill ${name} processes. Original error: ${e.message}`);
  }
};

methods.killProcessByPID = async function killProcessByPID(pid) {
  _logger.default.debug(`Attempting to kill process ${pid}`);

  let wasRoot = false;
  let becameRoot = false;

  try {
    try {
      await this.shell(['kill', '-0', pid]);
    } catch (e) {
      if (_lodash.default.includes(e.stderr, 'No such process')) {
        return e.stderr;
      }

      if (!_lodash.default.includes(e.stderr, 'Operation not permitted')) {
        throw e;
      }

      try {
        wasRoot = await this.isRoot();
      } catch (ign) {}

      if (wasRoot) {
        throw e;
      }

      _logger.default.info(`Cannot kill PID ${pid} due to insufficient permissions. Retrying as root`);

      ({
        isSuccessful: becameRoot
      } = await this.root());

      try {
        await this.shell(['kill', '-0', pid]);
      } catch (e1) {
        if (_lodash.default.includes(e1.stderr, 'No such process')) {
          return e1.stderr;
        }

        throw e1;
      }
    }

    const timeoutMs = 1000;
    let stdout;

    try {
      await (0, _asyncbox.waitForCondition)(async () => {
        try {
          stdout = await this.shell(['kill', pid]);
          return false;
        } catch (e) {
          return true;
        }
      }, {
        waitMs: timeoutMs,
        intervalMs: 300
      });
    } catch (err) {
      _logger.default.warn(`Cannot kill process ${pid} in ${timeoutMs} ms. Trying to force kill...`);

      stdout = await this.shell(['kill', '-9', pid]);
    }

    return stdout;
  } finally {
    if (becameRoot) {
      await this.unroot();
    }
  }
};

methods.broadcastProcessEnd = async function broadcastProcessEnd(intent, processName) {
  this.broadcast(intent);
  let start = Date.now();
  let timeoutMs = 40000;

  try {
    while (Date.now() - start < timeoutMs) {
      if (await this.processExists(processName)) {
        await (0, _asyncbox.sleep)(400);
        continue;
      }

      return;
    }

    throw new Error(`Process never died within ${timeoutMs} ms`);
  } catch (e) {
    throw new Error(`Unable to broadcast process end. Original error: ${e.message}`);
  }
};

methods.broadcast = async function broadcast(intent) {
  if (!this.isValidClass(intent)) {
    throw new Error(`Invalid intent ${intent}`);
  }

  _logger.default.debug(`Broadcasting: ${intent}`);

  await this.shell(['am', 'broadcast', '-a', intent]);
};

methods.endAndroidCoverage = async function endAndroidCoverage() {
  if (this.instrumentProc && this.instrumentProc.isRunning) {
    await this.instrumentProc.stop();
  }
};

methods.instrument = async function instrument(pkg, activity, instrumentWith) {
  if (activity[0] !== '.') {
    pkg = '';
  }

  let pkgActivity = (pkg + activity).replace(/\.+/g, '.');
  let stdout = await this.shell(['am', 'instrument', '-e', 'main_activity', pkgActivity, instrumentWith]);

  if (stdout.indexOf('Exception') !== -1) {
    throw new Error(`Unknown exception during instrumentation. Original error ${stdout.split('\n')[0]}`);
  }
};

methods.androidCoverage = async function androidCoverage(instrumentClass, waitPkg, waitActivity) {
  if (!this.isValidClass(instrumentClass)) {
    throw new Error(`Invalid class ${instrumentClass}`);
  }

  return await new _bluebird.default(async (resolve, reject) => {
    let args = this.executable.defaultArgs.concat(['shell', 'am', 'instrument', '-e', 'coverage', 'true', '-w']).concat([instrumentClass]);

    _logger.default.debug(`Collecting coverage data with: ${[this.executable.path].concat(args).join(' ')}`);

    try {
      this.instrumentProc = new _teen_process.SubProcess(this.executable.path, args);
      await this.instrumentProc.start(0);
      this.instrumentProc.on('output', (stdout, stderr) => {
        if (stderr) {
          reject(new Error(`Failed to run instrumentation. Original error: ${stderr}`));
        }
      });
      await this.waitForActivity(waitPkg, waitActivity);
      resolve();
    } catch (e) {
      reject(new Error(`Android coverage failed. Original error: ${e.message}`));
    }
  });
};

methods.getDeviceProperty = async function getDeviceProperty(property) {
  let stdout = await this.shell(['getprop', property]);
  let val = stdout.trim();

  _logger.default.debug(`Current device property '${property}': ${val}`);

  return val;
};

methods.setDeviceProperty = async function setDeviceProperty(prop, val, opts = {}) {
  const {
    privileged = true
  } = opts;

  _logger.default.debug(`Setting device property '${prop}' to '${val}'`);

  await this.shell(['setprop', prop, val], {
    privileged
  });
};

methods.getDeviceSysLanguage = async function getDeviceSysLanguage() {
  return await this.getDeviceProperty('persist.sys.language');
};

methods.getDeviceSysCountry = async function getDeviceSysCountry() {
  return await this.getDeviceProperty('persist.sys.country');
};

methods.getDeviceSysLocale = async function getDeviceSysLocale() {
  return await this.getDeviceProperty('persist.sys.locale');
};

methods.getDeviceProductLanguage = async function getDeviceProductLanguage() {
  return await this.getDeviceProperty('ro.product.locale.language');
};

methods.getDeviceProductCountry = async function getDeviceProductCountry() {
  return await this.getDeviceProperty('ro.product.locale.region');
};

methods.getDeviceProductLocale = async function getDeviceProductLocale() {
  return await this.getDeviceProperty('ro.product.locale');
};

methods.getModel = async function getModel() {
  return await this.getDeviceProperty('ro.product.model');
};

methods.getManufacturer = async function getManufacturer() {
  return await this.getDeviceProperty('ro.product.manufacturer');
};

methods.getScreenSize = async function getScreenSize() {
  let stdout = await this.shell(['wm', 'size']);
  let size = new RegExp(/Physical size: ([^\r?\n]+)*/g).exec(stdout);

  if (size && size.length >= 2) {
    return size[1].trim();
  }

  return null;
};

methods.getScreenDensity = async function getScreenDensity() {
  let stdout = await this.shell(['wm', 'density']);
  let density = new RegExp(/Physical density: ([^\r?\n]+)*/g).exec(stdout);

  if (density && density.length >= 2) {
    let densityNumber = parseInt(density[1].trim(), 10);
    return isNaN(densityNumber) ? null : densityNumber;
  }

  return null;
};

methods.setHttpProxy = async function setHttpProxy(proxyHost, proxyPort) {
  let proxy = `${proxyHost}:${proxyPort}`;

  if (_lodash.default.isUndefined(proxyHost)) {
    throw new Error(`Call to setHttpProxy method with undefined proxy_host: ${proxy}`);
  }

  if (_lodash.default.isUndefined(proxyPort)) {
    throw new Error(`Call to setHttpProxy method with undefined proxy_port ${proxy}`);
  }

  const httpProxySettins = [['http_proxy', proxy], ['global_http_proxy_host', proxyHost], ['global_http_proxy_port', proxyPort]];

  for (const [settingKey, settingValue] of httpProxySettins) {
    await this.setSetting('global', settingKey, settingValue);
  }
};

methods.deleteHttpProxy = async function deleteHttpProxy() {
  const httpProxySettins = ['http_proxy', 'global_http_proxy_host', 'global_http_proxy_port', 'global_http_proxy_exclusion_list'];

  for (const setting of httpProxySettins) {
    await this.shell(['settings', 'delete', 'global', setting]);
  }
};

methods.setSetting = async function setSetting(namespace, setting, value) {
  return await this.shell(['settings', 'put', namespace, setting, value]);
};

methods.getSetting = async function getSetting(namespace, setting) {
  return await this.shell(['settings', 'get', namespace, setting]);
};

methods.bugreport = async function bugreport(timeout = 120000) {
  return await this.adbExec(['bugreport'], {
    timeout
  });
};

methods.screenrecord = function screenrecord(destination, options = {}) {
  const cmd = ['screenrecord'];
  const {
    videoSize,
    bitRate,
    timeLimit,
    bugReport
  } = options;

  if (_appiumSupport.util.hasValue(videoSize)) {
    cmd.push('--size', videoSize);
  }

  if (_appiumSupport.util.hasValue(timeLimit)) {
    cmd.push('--time-limit', timeLimit);
  }

  if (_appiumSupport.util.hasValue(bitRate)) {
    cmd.push('--bit-rate', bitRate);
  }

  if (bugReport) {
    cmd.push('--bugreport');
  }

  cmd.push(destination);
  const fullCmd = [...this.executable.defaultArgs, 'shell', ...cmd];

  _logger.default.debug(`Building screenrecord process with the command line: adb ${_appiumSupport.util.quote(fullCmd)}`);

  return new _teen_process.SubProcess(this.executable.path, fullCmd);
};

methods.runInImeContext = async function runInImeContext(ime, fn) {
  const originalIme = await this.defaultIME();

  if (originalIme === ime) {
    _logger.default.debug(`The original IME is the same as '${ime}'. There is no need to reset it`);
  } else {
    await this.setIME(ime);
  }

  try {
    return await fn();
  } finally {
    if (originalIme !== ime) {
      await this.setIME(originalIme);
    }
  }
};

methods.getTimeZone = async function getTimeZone() {
  _logger.default.debug('Getting current timezone');

  try {
    return await this.getDeviceProperty('persist.sys.timezone');
  } catch (e) {
    throw new Error(`Error getting timezone. Original error: ${e.message}`);
  }
};

methods.listFeatures = async function listFeatures() {
  this._memoizedFeatures = this._memoizedFeatures || _lodash.default.memoize(async () => await this.adbExec(['features']), () => this.curDeviceId);

  try {
    return (await this._memoizedFeatures()).split(/\s+/).map(x => x.trim()).filter(Boolean);
  } catch (e) {
    if (_lodash.default.includes(e.stderr, 'unknown command')) {
      return [];
    }

    throw e;
  }
};

methods.isStreamedInstallSupported = async function isStreamedInstallSupported() {
  const proto = Object.getPrototypeOf(this);
  proto._helpOutput = proto._helpOutput || (await this.adbExec(['help']));
  return proto._helpOutput.includes('--streaming') && (await this.listFeatures()).includes('cmd');
};

var _default = methods;
exports.default = _default;require('source-map-support').install();


//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi90b29scy9hZGItY29tbWFuZHMuanMiXSwibmFtZXMiOlsiTUFYX1NIRUxMX0JVRkZFUl9MRU5HVEgiLCJOT1RfQ0hBTkdFQUJMRV9QRVJNX0VSUk9SIiwiSUdOT1JFRF9QRVJNX0VSUk9SUyIsIk1BWF9QR1JFUF9QQVRURVJOX0xFTiIsIkhJRERFTl9BUElfUE9MSUNZX0tFWVMiLCJQSURfQ09MVU1OX1RJVExFIiwiUFJPQ0VTU19OQU1FX0NPTFVNTl9USVRMRSIsIlBTX1RJVExFX1BBVFRFUk4iLCJSZWdFeHAiLCJtZXRob2RzIiwiZ2V0QWRiV2l0aENvcnJlY3RBZGJQYXRoIiwiZXhlY3V0YWJsZSIsInBhdGgiLCJnZXRTZGtCaW5hcnlQYXRoIiwiYWRiIiwiaW5pdEFhcHQiLCJpbml0QWFwdDIiLCJpbml0WmlwQWxpZ24iLCJpbml0QnVuZGxldG9vbCIsImJpbmFyaWVzIiwiYnVuZGxldG9vbCIsImZzIiwid2hpY2giLCJlcnIiLCJFcnJvciIsImdldEFwaUxldmVsIiwiXyIsImlzSW50ZWdlciIsIl9hcGlMZXZlbCIsInN0ck91dHB1dCIsImdldERldmljZVByb3BlcnR5IiwiYXBpTGV2ZWwiLCJwYXJzZUludCIsInRyaW0iLCJjaGFyQ29kZVEiLCJjaGFyQ29kZUF0IiwiYXBpTGV2ZWxEaWZmIiwiY29kZW5hbWUiLCJTdHJpbmciLCJmcm9tQ2hhckNvZGUiLCJnZXRQbGF0Zm9ybVZlcnNpb24iLCJ0b0xvd2VyQ2FzZSIsImxvZyIsImRlYnVnIiwidG9VcHBlckNhc2UiLCJpc05hTiIsImUiLCJtZXNzYWdlIiwiaW5mbyIsImlzRGV2aWNlQ29ubmVjdGVkIiwiZGV2aWNlcyIsImdldENvbm5lY3RlZERldmljZXMiLCJsZW5ndGgiLCJta2RpciIsInJlbW90ZVBhdGgiLCJzaGVsbCIsImlzVmFsaWRDbGFzcyIsImNsYXNzU3RyaW5nIiwiZXhlYyIsImZvcmNlU3RvcCIsInBrZyIsImtpbGxQYWNrYWdlIiwiY2xlYXIiLCJncmFudEFsbFBlcm1pc3Npb25zIiwiYXBrIiwidGFyZ2V0U2RrIiwiZHVtcHN5c091dHB1dCIsInRhcmdldFNka1ZlcnNpb25Vc2luZ1BLRyIsInRhcmdldFNka1ZlcnNpb25Gcm9tTWFuaWZlc3QiLCJ3YXJuIiwicmVxdWVzdGVkUGVybWlzc2lvbnMiLCJnZXRSZXFQZXJtaXNzaW9ucyIsImdyYW50ZWRQZXJtaXNzaW9ucyIsImdldEdyYW50ZWRQZXJtaXNzaW9ucyIsInBlcm1pc3Npb25zVG9HcmFudCIsImRpZmZlcmVuY2UiLCJpc0VtcHR5IiwiZ3JhbnRQZXJtaXNzaW9ucyIsInBlcm1pc3Npb25zIiwiSlNPTiIsInN0cmluZ2lmeSIsImNvbW1hbmRzIiwiY21kQ2h1bmsiLCJwZXJtaXNzaW9uIiwibmV4dENtZCIsImpvaW4iLCJwdXNoIiwibGFzdEVycm9yIiwiY21kIiwic29tZSIsIm1zZ1JlZ2V4IiwidGVzdCIsInN0ZGVyciIsImdyYW50UGVybWlzc2lvbiIsInJldm9rZVBlcm1pc3Npb24iLCJjbWRPdXRwdXQiLCJzdGRvdXQiLCJnZXREZW5pZWRQZXJtaXNzaW9ucyIsImdldExvY2F0aW9uUHJvdmlkZXJzIiwiZ2V0U2V0dGluZyIsInNwbGl0IiwibWFwIiwicCIsImZpbHRlciIsIkJvb2xlYW4iLCJ0b2dnbGVHUFNMb2NhdGlvblByb3ZpZGVyIiwiZW5hYmxlZCIsInNldFNldHRpbmciLCJzZXRIaWRkZW5BcGlQb2xpY3kiLCJ2YWx1ZSIsImlnbm9yZUVycm9yIiwiayIsInNldERlZmF1bHRIaWRkZW5BcGlQb2xpY3kiLCJzdG9wQW5kQ2xlYXIiLCJhdmFpbGFibGVJTUVzIiwiZW5hYmxlZElNRXMiLCJlbmFibGVJTUUiLCJpbWVJZCIsImRpc2FibGVJTUUiLCJzZXRJTUUiLCJkZWZhdWx0SU1FIiwiZW5naW5lIiwia2V5ZXZlbnQiLCJrZXljb2RlIiwiY29kZSIsImlucHV0VGV4dCIsInRleHQiLCJyZXBsYWNlIiwiY2xlYXJUZXh0RmllbGQiLCJhcmdzIiwiaSIsImxvY2siLCJpc1NjcmVlbkxvY2tlZCIsInRpbWVvdXRNcyIsIndhaXRNcyIsImludGVydmFsTXMiLCJiYWNrIiwiZ29Ub0hvbWUiLCJnZXRBZGJQYXRoIiwiZ2V0U2NyZWVuT3JpZW50YXRpb24iLCJwcm9jZXNzIiwiZW52IiwiQVBQSVVNX0xPR19EVU1QU1lTIiwiZHVtcHN5c0ZpbGUiLCJyZXNvbHZlIiwiY3dkIiwid3JpdGVGaWxlIiwiaXNTb2Z0S2V5Ym9hcmRQcmVzZW50IiwiaW5wdXRTaG93bk1hdGNoIiwiaW5wdXRWaWV3U2hvd25NYXRjaCIsImlzS2V5Ym9hcmRTaG93biIsImNhbkNsb3NlS2V5Ym9hcmQiLCJzZW5kVGVsbmV0Q29tbWFuZCIsImNvbW1hbmQiLCJwb3J0IiwiZ2V0RW11bGF0b3JQb3J0IiwiQiIsInJlamVjdCIsImNvbm4iLCJuZXQiLCJjcmVhdGVDb25uZWN0aW9uIiwiY29ubmVjdGVkIiwicmVhZHlSZWdleCIsImRhdGFTdHJlYW0iLCJyZXMiLCJvbiIsImRhdGEiLCJ0b1N0cmluZyIsIndyaXRlIiwibGFzdCIsImlzQWlycGxhbmVNb2RlT24iLCJzZXRBaXJwbGFuZU1vZGUiLCJicm9hZGNhc3RBaXJwbGFuZU1vZGUiLCJpc1dpZmlPbiIsImlzRGF0YU9uIiwic2V0V2lmaUFuZERhdGEiLCJ3aWZpIiwiaXNFbXVsYXRvciIsInV0aWwiLCJoYXNWYWx1ZSIsInNldFdpZmlTdGF0ZSIsInNldERhdGFTdGF0ZSIsImlzQW5pbWF0aW9uT24iLCJhbmltYXRvcl9kdXJhdGlvbl9zY2FsZSIsInRyYW5zaXRpb25fYW5pbWF0aW9uX3NjYWxlIiwid2luZG93X2FuaW1hdGlvbl9zY2FsZSIsInNldHRpbmciLCJyaW1yYWYiLCJsb2NhbFBhdGgiLCJvcHRzIiwicG9zaXgiLCJkaXJuYW1lIiwiYWRiRXhlYyIsInB1bGwiLCJ0aW1lb3V0IiwicHJvY2Vzc0V4aXN0cyIsInByb2Nlc3NOYW1lIiwiZ2V0UElEc0J5TmFtZSIsImdldEZvcndhcmRMaXN0IiwiY29ubmVjdGlvbnMiLCJFT0wiLCJsaW5lIiwiZm9yd2FyZFBvcnQiLCJzeXN0ZW1Qb3J0IiwiZGV2aWNlUG9ydCIsInJlbW92ZVBvcnRGb3J3YXJkIiwiZ2V0UmV2ZXJzZUxpc3QiLCJyZXZlcnNlUG9ydCIsInJlbW92ZVBvcnRSZXZlcnNlIiwiZm9yd2FyZEFic3RyYWN0UG9ydCIsInBpbmciLCJpbmRleE9mIiwicmVzdGFydCIsInN0b3BMb2djYXQiLCJyZXN0YXJ0QWRiIiwid2FpdEZvckRldmljZSIsInN0YXJ0TG9nY2F0IiwibG9nY2F0IiwiTG9nY2F0IiwiZGVidWdUcmFjZSIsImNsZWFyRGV2aWNlTG9nc09uU3RhcnQiLCJzdGFydENhcHR1cmUiLCJzdG9wQ2FwdHVyZSIsImdldExvZ2NhdExvZ3MiLCJnZXRMb2dzIiwic2V0TG9nY2F0TGlzdGVuZXIiLCJsaXN0ZW5lciIsInJlbW92ZUxvZ2NhdExpc3RlbmVyIiwicmVtb3ZlTGlzdGVuZXIiLCJnZXROYW1lQnlQaWQiLCJwaWQiLCJ0aXRsZU1hdGNoIiwiYWxsVGl0bGVzIiwicGlkSW5kZXgiLCJuYW1lT2Zmc2V0IiwicGlkUmVnZXgiLCJtYXRjaGVkTGluZSIsIml0ZW1zIiwibmFtZSIsImlzQm9vbGVhbiIsIl9pc1BncmVwQXZhaWxhYmxlIiwicGdyZXBPdXRwdXQiLCJfY2FuUGdyZXBVc2VGdWxsQ21kTGluZVNlYXJjaCIsIl9pc1BpZG9mQXZhaWxhYmxlIiwic2hlbGxDb21tYW5kIiwiZXNjYXBlUmVnRXhwIiwic2xpY2UiLCJ4IiwicGlkcyIsInByb2Nlc3NOYW1lUmVnZXgiLCJraWxsUHJvY2Vzc2VzQnlOYW1lIiwia2lsbFByb2Nlc3NCeVBJRCIsIndhc1Jvb3QiLCJiZWNhbWVSb290IiwiaW5jbHVkZXMiLCJpc1Jvb3QiLCJpZ24iLCJpc1N1Y2Nlc3NmdWwiLCJyb290IiwiZTEiLCJ1bnJvb3QiLCJicm9hZGNhc3RQcm9jZXNzRW5kIiwiaW50ZW50IiwiYnJvYWRjYXN0Iiwic3RhcnQiLCJEYXRlIiwibm93IiwiZW5kQW5kcm9pZENvdmVyYWdlIiwiaW5zdHJ1bWVudFByb2MiLCJpc1J1bm5pbmciLCJzdG9wIiwiaW5zdHJ1bWVudCIsImFjdGl2aXR5IiwiaW5zdHJ1bWVudFdpdGgiLCJwa2dBY3Rpdml0eSIsImFuZHJvaWRDb3ZlcmFnZSIsImluc3RydW1lbnRDbGFzcyIsIndhaXRQa2ciLCJ3YWl0QWN0aXZpdHkiLCJkZWZhdWx0QXJncyIsImNvbmNhdCIsIlN1YlByb2Nlc3MiLCJ3YWl0Rm9yQWN0aXZpdHkiLCJwcm9wZXJ0eSIsInZhbCIsInNldERldmljZVByb3BlcnR5IiwicHJvcCIsInByaXZpbGVnZWQiLCJnZXREZXZpY2VTeXNMYW5ndWFnZSIsImdldERldmljZVN5c0NvdW50cnkiLCJnZXREZXZpY2VTeXNMb2NhbGUiLCJnZXREZXZpY2VQcm9kdWN0TGFuZ3VhZ2UiLCJnZXREZXZpY2VQcm9kdWN0Q291bnRyeSIsImdldERldmljZVByb2R1Y3RMb2NhbGUiLCJnZXRNb2RlbCIsImdldE1hbnVmYWN0dXJlciIsImdldFNjcmVlblNpemUiLCJzaXplIiwiZ2V0U2NyZWVuRGVuc2l0eSIsImRlbnNpdHkiLCJkZW5zaXR5TnVtYmVyIiwic2V0SHR0cFByb3h5IiwicHJveHlIb3N0IiwicHJveHlQb3J0IiwicHJveHkiLCJpc1VuZGVmaW5lZCIsImh0dHBQcm94eVNldHRpbnMiLCJzZXR0aW5nS2V5Iiwic2V0dGluZ1ZhbHVlIiwiZGVsZXRlSHR0cFByb3h5IiwibmFtZXNwYWNlIiwiYnVncmVwb3J0Iiwic2NyZWVucmVjb3JkIiwiZGVzdGluYXRpb24iLCJvcHRpb25zIiwidmlkZW9TaXplIiwiYml0UmF0ZSIsInRpbWVMaW1pdCIsImJ1Z1JlcG9ydCIsImZ1bGxDbWQiLCJxdW90ZSIsInJ1bkluSW1lQ29udGV4dCIsImltZSIsImZuIiwib3JpZ2luYWxJbWUiLCJnZXRUaW1lWm9uZSIsImxpc3RGZWF0dXJlcyIsIl9tZW1vaXplZEZlYXR1cmVzIiwibWVtb2l6ZSIsImN1ckRldmljZUlkIiwiaXNTdHJlYW1lZEluc3RhbGxTdXBwb3J0ZWQiLCJwcm90byIsIk9iamVjdCIsImdldFByb3Rv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QUErQjtBQUNwRCxPQUFLQyxpQkFBTCxHQUF5QixLQUFLQSxpQkFBTCxJQUNwQjdTLGdCQUFFOFMsT0FBRixDQUFVLFlBQVksTUFBTSxLQUFLeEksT0FBTCxDQUFhLENBQUMsVUFBRCxDQUFiLENBQTVCLEVBQXdELE1BQU0sS0FBS3lJLFdBQW5FLENBREw7O0FBRUEsTUFBSTtBQUNGLFdBQU8sQ0FBQyxNQUFNLEtBQUtGLGlCQUFMLEVBQVAsRUFDSm5PLEtBREksQ0FDRSxLQURGLEVBRUpDLEdBRkksQ0FFQ2tKLENBQUQsSUFBT0EsQ0FBQyxDQUFDdE4sSUFBRixFQUZQLEVBR0pzRSxNQUhJLENBR0dDLE9BSEgsQ0FBUDtBQUlELEdBTEQsQ0FLRSxPQUFPMUQsQ0FBUCxFQUFVO0FBQ1YsUUFBSXBCLGdCQUFFb08sUUFBRixDQUFXaE4sQ0FBQyxDQUFDOEMsTUFBYixFQUFxQixpQkFBckIsQ0FBSixFQUE2QztBQUMzQyxhQUFPLEVBQVA7QUFDRDs7QUFDRCxVQUFNOUMsQ0FBTjtBQUNEO0FBQ0YsQ0FkRDs7QUE2QkFyQyxPQUFPLENBQUNpVSwwQkFBUixHQUFxQyxlQUFlQSwwQkFBZixHQUE2QztBQUNoRixRQUFNQyxLQUFLLEdBQUdDLE1BQU0sQ0FBQ0MsY0FBUCxDQUFzQixJQUF0QixDQUFkO0FBQ0FGLEVBQUFBLEtBQUssQ0FBQ0csV0FBTixHQUFvQkgsS0FBSyxDQUFDRyxXQUFOLEtBQXFCLE1BQU0sS0FBSzlJLE9BQUwsQ0FBYSxDQUFDLE1BQUQsQ0FBYixDQUEzQixDQUFwQjtBQUNBLFNBQU8ySSxLQUFLLENBQUNHLFdBQU4sQ0FBa0JoRixRQUFsQixDQUEyQixhQUEzQixLQUE2QyxDQUFDLE1BQU0sS0FBS3dFLFlBQUwsRUFBUCxFQUE0QnhFLFFBQTVCLENBQXFDLEtBQXJDLENBQXBEO0FBQ0QsQ0FKRDs7ZUFNZXJQLE8iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgbG9nIGZyb20gJy4uL2xvZ2dlci5qcyc7XG5pbXBvcnQge1xuICBnZXRJTUVMaXN0RnJvbU91dHB1dCwgaXNTaG93aW5nTG9ja3NjcmVlbiwgaXNDdXJyZW50Rm9jdXNPbktleWd1YXJkLFxuICBnZXRTdXJmYWNlT3JpZW50YXRpb24sIGlzU2NyZWVuT25GdWxseSwgZXh0cmFjdE1hdGNoaW5nUGVybWlzc2lvbnMsXG59IGZyb20gJy4uL2hlbHBlcnMuanMnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHsgZnMsIHV0aWwgfSBmcm9tICdhcHBpdW0tc3VwcG9ydCc7XG5pbXBvcnQgbmV0IGZyb20gJ25ldCc7XG5pbXBvcnQgeyBFT0wgfSBmcm9tICdvcyc7XG5pbXBvcnQgTG9nY2F0IGZyb20gJy4uL2xvZ2NhdCc7XG5pbXBvcnQgeyBzbGVlcCwgd2FpdEZvckNvbmRpdGlvbiB9IGZyb20gJ2FzeW5jYm94JztcbmltcG9ydCB7IFN1YlByb2Nlc3MgfSBmcm9tICd0ZWVuX3Byb2Nlc3MnO1xuaW1wb3J0IEIgZnJvbSAnYmx1ZWJpcmQnO1xuXG5jb25zdCBNQVhfU0hFTExfQlVGRkVSX0xFTkdUSCA9IDEwMDA7XG5jb25zdCBOT1RfQ0hBTkdFQUJMRV9QRVJNX0VSUk9SID0gL25vdCBhIGNoYW5nZWFibGUgcGVybWlzc2lvbiB0eXBlL2k7XG5jb25zdCBJR05PUkVEX1BFUk1fRVJST1JTID0gW1xuICBOT1RfQ0hBTkdFQUJMRV9QRVJNX0VSUk9SLFxuICAvVW5rbm93biBwZXJtaXNzaW9uL2ksXG5dO1xuY29uc3QgTUFYX1BHUkVQX1BBVFRFUk5fTEVOID0gMTU7XG5jb25zdCBISURERU5fQVBJX1BPTElDWV9LRVlTID0gW1xuICAnaGlkZGVuX2FwaV9wb2xpY3lfcHJlX3BfYXBwcycsXG4gICdoaWRkZW5fYXBpX3BvbGljeV9wX2FwcHMnLFxuICAnaGlkZGVuX2FwaV9wb2xpY3knXG5dO1xuY29uc3QgUElEX0NPTFVNTl9USVRMRSA9ICdQSUQnO1xuY29uc3QgUFJPQ0VTU19OQU1FX0NPTFVNTl9USVRMRSA9ICdOQU1FJztcbmNvbnN0IFBTX1RJVExFX1BBVFRFUk4gPSBuZXcgUmVnRXhwKGBeKC4qXFxcXGIke1BJRF9DT0xVTU5fVElUTEV9XFxcXGIuKlxcXFxiJHtQUk9DRVNTX05BTUVfQ09MVU1OX1RJVExFfVxcXFxiLiopJGAsICdtJyk7XG5cblxubGV0IG1ldGhvZHMgPSB7fTtcblxuLyoqXG4gKiBHZXQgdGhlIHBhdGggdG8gYWRiIGV4ZWN1dGFibGUgYW1kIGFzc2lnbiBpdFxuICogdG8gdGhpcy5leGVjdXRhYmxlLnBhdGggYW5kIHRoaXMuYmluYXJpZXMuYWRiIHByb3BlcnRpZXMuXG4gKlxuICogQHJldHVybiB7c3RyaW5nfSBGdWxsIHBhdGggdG8gYWRiIGV4ZWN1dGFibGUuXG4gKi9cbm1ldGhvZHMuZ2V0QWRiV2l0aENvcnJlY3RBZGJQYXRoID0gYXN5bmMgZnVuY3Rpb24gZ2V0QWRiV2l0aENvcnJlY3RBZGJQYXRoICgpIHtcbiAgdGhpcy5leGVjdXRhYmxlLnBhdGggPSBhd2FpdCB0aGlzLmdldFNka0JpbmFyeVBhdGgoJ2FkYicpO1xuICByZXR1cm4gdGhpcy5hZGI7XG59O1xuXG4vKipcbiAqIEdldCB0aGUgZnVsbCBwYXRoIHRvIGFhcHQgdG9vbCBhbmQgYXNzaWduIGl0IHRvXG4gKiB0aGlzLmJpbmFyaWVzLmFhcHQgcHJvcGVydHlcbiAqL1xubWV0aG9kcy5pbml0QWFwdCA9IGFzeW5jIGZ1bmN0aW9uIGluaXRBYXB0ICgpIHtcbiAgYXdhaXQgdGhpcy5nZXRTZGtCaW5hcnlQYXRoKCdhYXB0Jyk7XG59O1xuXG4vKipcbiAqIEdldCB0aGUgZnVsbCBwYXRoIHRvIGFhcHQyIHRvb2wgYW5kIGFzc2lnbiBpdCB0b1xuICogdGhpcy5iaW5hcmllcy5hYXB0MiBwcm9wZXJ0eVxuICovXG5tZXRob2RzLmluaXRBYXB0MiA9IGFzeW5jIGZ1bmN0aW9uIGluaXRBYXB0MiAoKSB7XG4gIGF3YWl0IHRoaXMuZ2V0U2RrQmluYXJ5UGF0aCgnYWFwdDInKTtcbn07XG5cbi8qKlxuICogR2V0IHRoZSBmdWxsIHBhdGggdG8gemlwYWxpZ24gdG9vbCBhbmQgYXNzaWduIGl0IHRvXG4gKiB0aGlzLmJpbmFyaWVzLnppcGFsaWduIHByb3BlcnR5XG4gKi9cbm1ldGhvZHMuaW5pdFppcEFsaWduID0gYXN5bmMgZnVuY3Rpb24gaW5pdFppcEFsaWduICgpIHtcbiAgYXdhaXQgdGhpcy5nZXRTZGtCaW5hcnlQYXRoKCd6aXBhbGlnbicpO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIGZ1bGwgcGF0aCB0byBidW5kbGV0b29sIGJpbmFyeSBhbmQgYXNzaWduIGl0IHRvXG4gKiB0aGlzLmJpbmFyaWVzLmJ1bmRsZXRvb2wgcHJvcGVydHlcbiAqL1xubWV0aG9kcy5pbml0QnVuZGxldG9vbCA9IGFzeW5jIGZ1bmN0aW9uIGluaXRCdW5kbGV0b29sICgpIHtcbiAgdHJ5IHtcbiAgICB0aGlzLmJpbmFyaWVzLmJ1bmRsZXRvb2wgPSBhd2FpdCBmcy53aGljaCgnYnVuZGxldG9vbC5qYXInKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdidW5kbGV0b29sLmphciBiaW5hcnkgaXMgZXhwZWN0ZWQgdG8gYmUgcHJlc2VudCBpbiBQQVRILiAnICtcbiAgICAgICdWaXNpdCBodHRwczovL2dpdGh1Yi5jb20vZ29vZ2xlL2J1bmRsZXRvb2wgZm9yIG1vcmUgZGV0YWlscy4nKTtcbiAgfVxufTtcblxuLyoqXG4gKiBSZXRyaWV2ZSB0aGUgQVBJIGxldmVsIG9mIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqXG4gKiBAcmV0dXJuIHtudW1iZXJ9IFRoZSBBUEkgbGV2ZWwgYXMgaW50ZWdlciBudW1iZXIsIGZvciBleGFtcGxlIDIxIGZvclxuICogICAgICAgICAgICAgICAgICBBbmRyb2lkIExvbGxpcG9wLiBUaGUgcmVzdWx0IG9mIHRoaXMgbWV0aG9kIGlzIGNhY2hlZCwgc28gYWxsIHRoZSBmdXJ0aGVyXG4gKiBjYWxscyByZXR1cm4gdGhlIHNhbWUgdmFsdWUgYXMgdGhlIGZpcnN0IG9uZS5cbiAqL1xubWV0aG9kcy5nZXRBcGlMZXZlbCA9IGFzeW5jIGZ1bmN0aW9uIGdldEFwaUxldmVsICgpIHtcbiAgaWYgKCFfLmlzSW50ZWdlcih0aGlzLl9hcGlMZXZlbCkpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3Qgc3RyT3V0cHV0ID0gYXdhaXQgdGhpcy5nZXREZXZpY2VQcm9wZXJ0eSgncm8uYnVpbGQudmVyc2lvbi5zZGsnKTtcbiAgICAgIGxldCBhcGlMZXZlbCA9IHBhcnNlSW50KHN0ck91dHB1dC50cmltKCksIDEwKTtcblxuICAgICAgLy8gV29ya2Fyb3VuZCBmb3IgcHJldmlldy9iZXRhIHBsYXRmb3JtIEFQSSBsZXZlbFxuICAgICAgY29uc3QgY2hhckNvZGVRID0gJ3EnLmNoYXJDb2RlQXQoMCk7XG4gICAgICAvLyAyOCBpcyB0aGUgZmlyc3QgQVBJIExldmVsLCB3aGVyZSBBbmRyb2lkIFNESyBzdGFydGVkIHJldHVybmluZyBsZXR0ZXJzIGluIHJlc3BvbnNlIHRvIGdldFBsYXRmb3JtVmVyc2lvblxuICAgICAgY29uc3QgYXBpTGV2ZWxEaWZmID0gYXBpTGV2ZWwgLSAyODtcbiAgICAgIGNvbnN0IGNvZGVuYW1lID0gU3RyaW5nLmZyb21DaGFyQ29kZShjaGFyQ29kZVEgKyBhcGlMZXZlbERpZmYpO1xuICAgICAgaWYgKGFwaUxldmVsRGlmZiA+PSAwICYmIChhd2FpdCB0aGlzLmdldFBsYXRmb3JtVmVyc2lvbigpKS50b0xvd2VyQ2FzZSgpID09PSBjb2RlbmFtZSkge1xuICAgICAgICBsb2cuZGVidWcoYFJlbGVhc2UgdmVyc2lvbiBpcyAke2NvZGVuYW1lLnRvVXBwZXJDYXNlKCl9IGJ1dCBmb3VuZCBBUEkgTGV2ZWwgJHthcGlMZXZlbH0uIFNldHRpbmcgQVBJIExldmVsIHRvICR7YXBpTGV2ZWwgKyAxfWApO1xuICAgICAgICBhcGlMZXZlbCsrO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9hcGlMZXZlbCA9IGFwaUxldmVsO1xuICAgICAgbG9nLmRlYnVnKGBEZXZpY2UgQVBJIGxldmVsOiAke3RoaXMuX2FwaUxldmVsfWApO1xuICAgICAgaWYgKGlzTmFOKHRoaXMuX2FwaUxldmVsKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZSBhY3R1YWwgb3V0cHV0ICcke3N0ck91dHB1dH0nIGNhbm5vdCBiZSBjb252ZXJ0ZWQgdG8gYW4gaW50ZWdlcmApO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgZ2V0dGluZyBkZXZpY2UgQVBJIGxldmVsLiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gICAgfVxuICB9XG4gIHJldHVybiB0aGlzLl9hcGlMZXZlbDtcbn07XG5cbi8qKlxuICogUmV0cmlldmUgdGhlIHBsYXRmb3JtIHZlcnNpb24gb2YgdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIHBsYXRmb3JtIHZlcnNpb24gYXMgYSBzdHJpbmcsIGZvciBleGFtcGxlICc1LjAnIGZvclxuICogQW5kcm9pZCBMb2xsaXBvcC5cbiAqL1xubWV0aG9kcy5nZXRQbGF0Zm9ybVZlcnNpb24gPSBhc3luYyBmdW5jdGlvbiBnZXRQbGF0Zm9ybVZlcnNpb24gKCkge1xuICBsb2cuaW5mbygnR2V0dGluZyBkZXZpY2UgcGxhdGZvcm0gdmVyc2lvbicpO1xuICB0cnkge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLmdldERldmljZVByb3BlcnR5KCdyby5idWlsZC52ZXJzaW9uLnJlbGVhc2UnKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgZ2V0dGluZyBkZXZpY2UgcGxhdGZvcm0gdmVyc2lvbi4gT3JpZ2luYWwgZXJyb3I6ICR7ZS5tZXNzYWdlfWApO1xuICB9XG59O1xuXG4vKipcbiAqIFZlcmlmeSB3aGV0aGVyIGEgZGV2aWNlIGlzIGNvbm5lY3RlZC5cbiAqXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIGF0IGxlYXN0IG9uZSBkZXZpY2UgaXMgdmlzaWJsZSB0byBhZGIuXG4gKi9cbm1ldGhvZHMuaXNEZXZpY2VDb25uZWN0ZWQgPSBhc3luYyBmdW5jdGlvbiBpc0RldmljZUNvbm5lY3RlZCAoKSB7XG4gIGxldCBkZXZpY2VzID0gYXdhaXQgdGhpcy5nZXRDb25uZWN0ZWREZXZpY2VzKCk7XG4gIHJldHVybiBkZXZpY2VzLmxlbmd0aCA+IDA7XG59O1xuXG4vKipcbiAqIFJlY3Vyc2l2ZWx5IGNyZWF0ZSBhIG5ldyBmb2xkZXIgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSByZW1vdGVQYXRoIC0gVGhlIG5ldyBwYXRoIHRvIGJlIGNyZWF0ZWQuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IG1rZGlyIGNvbW1hbmQgb3V0cHV0LlxuICovXG5tZXRob2RzLm1rZGlyID0gYXN5bmMgZnVuY3Rpb24gbWtkaXIgKHJlbW90ZVBhdGgpIHtcbiAgcmV0dXJuIGF3YWl0IHRoaXMuc2hlbGwoWydta2RpcicsICctcCcsIHJlbW90ZVBhdGhdKTtcbn07XG5cbi8qKlxuICogVmVyaWZ5IHdoZXRoZXIgdGhlIGdpdmVuIGFyZ3VtZW50IGlzIGFcbiAqIHZhbGlkIGNsYXNzIG5hbWUuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzU3RyaW5nIC0gVGhlIGFjdHVhbCBjbGFzcyBuYW1lIHRvIGJlIHZlcmlmaWVkLlxuICogQHJldHVybiB7P0FycmF5LjxNYXRjaD59IFRoZSByZXN1bHQgb2YgUmVnZXhwLmV4ZWMgb3BlcmF0aW9uXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgb3IgX251bGxfIGlmIG5vIG1hdGNoZXMgYXJlIGZvdW5kLlxuICovXG5tZXRob2RzLmlzVmFsaWRDbGFzcyA9IGZ1bmN0aW9uIGlzVmFsaWRDbGFzcyAoY2xhc3NTdHJpbmcpIHtcbiAgLy8gc29tZS5wYWNrYWdlL3NvbWUucGFja2FnZS5BY3Rpdml0eVxuICByZXR1cm4gbmV3IFJlZ0V4cCgvXlthLXpBLVowLTkuL19dKyQvKS5leGVjKGNsYXNzU3RyaW5nKTtcbn07XG5cbi8qKlxuICogRm9yY2UgYXBwbGljYXRpb24gdG8gc3RvcCBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHBrZyAtIFRoZSBwYWNrYWdlIG5hbWUgdG8gYmUgc3RvcHBlZC5cbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIG91dHB1dCBvZiB0aGUgY29ycmVzcG9uZGluZyBhZGIgY29tbWFuZC5cbiAqL1xubWV0aG9kcy5mb3JjZVN0b3AgPSBhc3luYyBmdW5jdGlvbiBmb3JjZVN0b3AgKHBrZykge1xuICByZXR1cm4gYXdhaXQgdGhpcy5zaGVsbChbJ2FtJywgJ2ZvcmNlLXN0b3AnLCBwa2ddKTtcbn07XG5cbi8qXG4gKiBLaWxsIGFwcGxpY2F0aW9uXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHBrZyAtIFRoZSBwYWNrYWdlIG5hbWUgdG8gYmUgc3RvcHBlZC5cbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIG91dHB1dCBvZiB0aGUgY29ycmVzcG9uZGluZyBhZGIgY29tbWFuZC5cbiAqL1xubWV0aG9kcy5raWxsUGFja2FnZSA9IGFzeW5jIGZ1bmN0aW9uIGtpbGxQYWNrYWdlIChwa2cpIHtcbiAgcmV0dXJuIGF3YWl0IHRoaXMuc2hlbGwoWydhbScsICdraWxsJywgcGtnXSk7XG59O1xuXG4vKipcbiAqIENsZWFyIHRoZSB1c2VyIGRhdGEgb2YgdGhlIHBhcnRpY3VsYXIgYXBwbGljYXRpb24gb24gdGhlIGRldmljZVxuICogdW5kZXIgdGVzdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcGtnIC0gVGhlIHBhY2thZ2UgbmFtZSB0byBiZSBjbGVhcmVkLlxuICogQHJldHVybiB7c3RyaW5nfSBUaGUgb3V0cHV0IG9mIHRoZSBjb3JyZXNwb25kaW5nIGFkYiBjb21tYW5kLlxuICovXG5tZXRob2RzLmNsZWFyID0gYXN5bmMgZnVuY3Rpb24gY2xlYXIgKHBrZykge1xuICByZXR1cm4gYXdhaXQgdGhpcy5zaGVsbChbJ3BtJywgJ2NsZWFyJywgcGtnXSk7XG59O1xuXG4vKipcbiAqIEdyYW50IGFsbCBwZXJtaXNzaW9ucyByZXF1ZXN0ZWQgYnkgdGhlIHBhcnRpY3VsYXIgcGFja2FnZS5cbiAqIFRoaXMgbWV0aG9kIGlzIG9ubHkgdXNlZnVsIG9uIEFuZHJvaWQgNi4wKyBhbmQgZm9yIGFwcGxpY2F0aW9uc1xuICogdGhhdCBzdXBwb3J0IGNvbXBvbmVudHMtYmFzZWQgcGVybWlzc2lvbnMgc2V0dGluZy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcGtnIC0gVGhlIHBhY2thZ2UgbmFtZSB0byBiZSBwcm9jZXNzZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gYXBrIC0gVGhlIHBhdGggdG8gdGhlIGFjdHVhbCBhcGsgZmlsZS5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGVyZSB3YXMgYW4gZXJyb3Igd2hpbGUgZ3JhbnRpbmcgcGVybWlzc2lvbnNcbiAqL1xubWV0aG9kcy5ncmFudEFsbFBlcm1pc3Npb25zID0gYXN5bmMgZnVuY3Rpb24gZ3JhbnRBbGxQZXJtaXNzaW9ucyAocGtnLCBhcGspIHtcbiAgY29uc3QgYXBpTGV2ZWwgPSBhd2FpdCB0aGlzLmdldEFwaUxldmVsKCk7XG4gIGxldCB0YXJnZXRTZGsgPSAwO1xuICBsZXQgZHVtcHN5c091dHB1dCA9IG51bGw7XG4gIHRyeSB7XG4gICAgaWYgKCFhcGspIHtcbiAgICAgIC8qKlxuICAgICAgICogSWYgYXBrIG5vdCBwcm92aWRlZCwgY29uc2lkZXJpbmcgYXBrIGFscmVhZHkgaW5zdGFsbGVkIG9uIHRoZSBkZXZpY2VcbiAgICAgICAqIGFuZCBmZXRjaGluZyB0YXJnZXRTZGsgdXNpbmcgcGFja2FnZSBuYW1lLlxuICAgICAgICovXG4gICAgICBkdW1wc3lzT3V0cHV0ID0gYXdhaXQgdGhpcy5zaGVsbChbJ2R1bXBzeXMnLCAncGFja2FnZScsIHBrZ10pO1xuICAgICAgdGFyZ2V0U2RrID0gYXdhaXQgdGhpcy50YXJnZXRTZGtWZXJzaW9uVXNpbmdQS0cocGtnLCBkdW1wc3lzT3V0cHV0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGFyZ2V0U2RrID0gYXdhaXQgdGhpcy50YXJnZXRTZGtWZXJzaW9uRnJvbU1hbmlmZXN0KGFwayk7XG4gICAgfVxuICB9IGNhdGNoIChlKSB7XG4gICAgLy9hdm9pZGluZyBsb2dnaW5nIGVycm9yIHN0YWNrLCBhcyBjYWxsaW5nIGxpYnJhcnkgZnVuY3Rpb24gd291bGQgaGF2ZSBsb2dnZWRcbiAgICBsb2cud2FybihgUmFuIGludG8gcHJvYmxlbSBnZXR0aW5nIHRhcmdldCBTREsgdmVyc2lvbjsgaWdub3JpbmcuLi5gKTtcbiAgfVxuICBpZiAoYXBpTGV2ZWwgPj0gMjMgJiYgdGFyZ2V0U2RrID49IDIzKSB7XG4gICAgLyoqXG4gICAgICogSWYgdGhlIGRldmljZSBpcyBydW5uaW5nIEFuZHJvaWQgNi4wKEFQSSAyMykgb3IgaGlnaGVyLCBhbmQgeW91ciBhcHAncyB0YXJnZXQgU0RLIGlzIDIzIG9yIGhpZ2hlcjpcbiAgICAgKiBUaGUgYXBwIGhhcyB0byBsaXN0IHRoZSBwZXJtaXNzaW9ucyBpbiB0aGUgbWFuaWZlc3QuXG4gICAgICogcmVmZXI6IGh0dHBzOi8vZGV2ZWxvcGVyLmFuZHJvaWQuY29tL3RyYWluaW5nL3Blcm1pc3Npb25zL3JlcXVlc3RpbmcuaHRtbFxuICAgICAqL1xuICAgIGR1bXBzeXNPdXRwdXQgPSBkdW1wc3lzT3V0cHV0IHx8IGF3YWl0IHRoaXMuc2hlbGwoWydkdW1wc3lzJywgJ3BhY2thZ2UnLCBwa2ddKTtcbiAgICBjb25zdCByZXF1ZXN0ZWRQZXJtaXNzaW9ucyA9IGF3YWl0IHRoaXMuZ2V0UmVxUGVybWlzc2lvbnMocGtnLCBkdW1wc3lzT3V0cHV0KTtcbiAgICBjb25zdCBncmFudGVkUGVybWlzc2lvbnMgPSBhd2FpdCB0aGlzLmdldEdyYW50ZWRQZXJtaXNzaW9ucyhwa2csIGR1bXBzeXNPdXRwdXQpO1xuICAgIGNvbnN0IHBlcm1pc3Npb25zVG9HcmFudCA9IF8uZGlmZmVyZW5jZShyZXF1ZXN0ZWRQZXJtaXNzaW9ucywgZ3JhbnRlZFBlcm1pc3Npb25zKTtcbiAgICBpZiAoXy5pc0VtcHR5KHBlcm1pc3Npb25zVG9HcmFudCkpIHtcbiAgICAgIGxvZy5pbmZvKGAke3BrZ30gY29udGFpbnMgbm8gcGVybWlzc2lvbnMgYXZhaWxhYmxlIGZvciBncmFudGluZ2ApO1xuICAgIH0gZWxzZSB7XG4gICAgICBhd2FpdCB0aGlzLmdyYW50UGVybWlzc2lvbnMocGtnLCBwZXJtaXNzaW9uc1RvR3JhbnQpO1xuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBHcmFudCBtdWx0aXBsZSBwZXJtaXNzaW9ucyBmb3IgdGhlIHBhcnRpY3VsYXIgcGFja2FnZS5cbiAqIFRoaXMgY2FsbCBpcyBtb3JlIHBlcmZvcm1hbnQgdGhhbiBgZ3JhbnRQZXJtaXNzaW9uYCBvbmUsIHNpbmNlIGl0IGNvbWJpbmVzXG4gKiBtdWx0aXBsZSBgYWRiIHNoZWxsYCBjYWxscyBpbnRvIGEgc2luZ2xlIGNvbW1hbmQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHBrZyAtIFRoZSBwYWNrYWdlIG5hbWUgdG8gYmUgcHJvY2Vzc2VkLlxuICogQHBhcmFtIHtBcnJheTxzdHJpbmc+fSBwZXJtaXNzaW9ucyAtIFRoZSBsaXN0IG9mIHBlcm1pc3Npb25zIHRvIGJlIGdyYW50ZWQuXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlcmUgd2FzIGFuIGVycm9yIHdoaWxlIGNoYW5naW5nIHBlcm1pc3Npb25zLlxuICovXG5tZXRob2RzLmdyYW50UGVybWlzc2lvbnMgPSBhc3luYyBmdW5jdGlvbiBncmFudFBlcm1pc3Npb25zIChwa2csIHBlcm1pc3Npb25zKSB7XG4gIC8vIEFzIGl0IGNvbnN1bWVzIG1vcmUgdGltZSBmb3IgZ3JhbnRpbmcgZWFjaCBwZXJtaXNzaW9uLFxuICAvLyB0cnlpbmcgdG8gZ3JhbnQgYWxsIHBlcm1pc3Npb24gYnkgZm9ybWluZyBlcXVpdmFsZW50IGNvbW1hbmQuXG4gIC8vIEFsc28sIGl0IGlzIG5lY2Vzc2FyeSB0byBzcGxpdCBsb25nIGNvbW1hbmRzIGludG8gY2h1bmtzLCBzaW5jZSB0aGUgbWF4aW11bSBsZW5ndGggb2ZcbiAgLy8gYWRiIHNoZWxsIGJ1ZmZlciBpcyBsaW1pdGVkXG4gIGxvZy5kZWJ1ZyhgR3JhbnRpbmcgcGVybWlzc2lvbnMgJHtKU09OLnN0cmluZ2lmeShwZXJtaXNzaW9ucyl9IHRvICcke3BrZ30nYCk7XG4gIGNvbnN0IGNvbW1hbmRzID0gW107XG4gIGxldCBjbWRDaHVuayA9IFtdO1xuICBmb3IgKGNvbnN0IHBlcm1pc3Npb24gb2YgcGVybWlzc2lvbnMpIHtcbiAgICBjb25zdCBuZXh0Q21kID0gWydwbScsICdncmFudCcsIHBrZywgcGVybWlzc2lvbiwgJzsnXTtcbiAgICBpZiAobmV4dENtZC5qb2luKCcgJykubGVuZ3RoICsgY21kQ2h1bmsuam9pbignICcpLmxlbmd0aCA+PSBNQVhfU0hFTExfQlVGRkVSX0xFTkdUSCkge1xuICAgICAgY29tbWFuZHMucHVzaChjbWRDaHVuayk7XG4gICAgICBjbWRDaHVuayA9IFtdO1xuICAgIH1cbiAgICBjbWRDaHVuayA9IFsuLi5jbWRDaHVuaywgLi4ubmV4dENtZF07XG4gIH1cbiAgaWYgKCFfLmlzRW1wdHkoY21kQ2h1bmspKSB7XG4gICAgY29tbWFuZHMucHVzaChjbWRDaHVuayk7XG4gIH1cbiAgbG9nLmRlYnVnKGBHb3QgdGhlIGZvbGxvd2luZyBjb21tYW5kIGNodW5rcyB0byBleGVjdXRlOiAke0pTT04uc3RyaW5naWZ5KGNvbW1hbmRzKX1gKTtcbiAgbGV0IGxhc3RFcnJvciA9IG51bGw7XG4gIGZvciAoY29uc3QgY21kIG9mIGNvbW1hbmRzKSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuc2hlbGwoY21kKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvLyB0aGlzIGlzIHRvIGdpdmUgdGhlIG1ldGhvZCBhIGNoYW5jZSB0byBhc3NpZ24gYWxsIHRoZSByZXF1ZXN0ZWQgcGVybWlzc2lvbnNcbiAgICAgIC8vIGJlZm9yZSB0byBxdWl0IGluIGNhc2Ugd2UnZCBsaWtlIHRvIGlnbm9yZSB0aGUgZXJyb3Igb24gdGhlIGhpZ2hlciBsZXZlbFxuICAgICAgaWYgKCFJR05PUkVEX1BFUk1fRVJST1JTLnNvbWUoKG1zZ1JlZ2V4KSA9PiBtc2dSZWdleC50ZXN0KGUuc3RkZXJyIHx8IGUubWVzc2FnZSkpKSB7XG4gICAgICAgIGxhc3RFcnJvciA9IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGlmIChsYXN0RXJyb3IpIHtcbiAgICB0aHJvdyBsYXN0RXJyb3I7XG4gIH1cbn07XG5cbi8qKlxuICogR3JhbnQgc2luZ2xlIHBlcm1pc3Npb24gZm9yIHRoZSBwYXJ0aWN1bGFyIHBhY2thZ2UuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHBrZyAtIFRoZSBwYWNrYWdlIG5hbWUgdG8gYmUgcHJvY2Vzc2VkLlxuICogQHBhcmFtIHtzdHJpbmd9IHBlcm1pc3Npb24gLSBUaGUgZnVsbCBuYW1lIG9mIHRoZSBwZXJtaXNzaW9uIHRvIGJlIGdyYW50ZWQuXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlcmUgd2FzIGFuIGVycm9yIHdoaWxlIGNoYW5naW5nIHBlcm1pc3Npb25zLlxuICovXG5tZXRob2RzLmdyYW50UGVybWlzc2lvbiA9IGFzeW5jIGZ1bmN0aW9uIGdyYW50UGVybWlzc2lvbiAocGtnLCBwZXJtaXNzaW9uKSB7XG4gIHRyeSB7XG4gICAgYXdhaXQgdGhpcy5zaGVsbChbJ3BtJywgJ2dyYW50JywgcGtnLCBwZXJtaXNzaW9uXSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoIU5PVF9DSEFOR0VBQkxFX1BFUk1fRVJST1IudGVzdChlLnN0ZGVyciB8fCBlLm1lc3NhZ2UpKSB7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBSZXZva2Ugc2luZ2xlIHBlcm1pc3Npb24gZnJvbSB0aGUgcGFydGljdWxhciBwYWNrYWdlLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwa2cgLSBUaGUgcGFja2FnZSBuYW1lIHRvIGJlIHByb2Nlc3NlZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwZXJtaXNzaW9uIC0gVGhlIGZ1bGwgbmFtZSBvZiB0aGUgcGVybWlzc2lvbiB0byBiZSByZXZva2VkLlxuICogQHRocm93cyB7RXJyb3J9IElmIHRoZXJlIHdhcyBhbiBlcnJvciB3aGlsZSBjaGFuZ2luZyBwZXJtaXNzaW9ucy5cbiAqL1xubWV0aG9kcy5yZXZva2VQZXJtaXNzaW9uID0gYXN5bmMgZnVuY3Rpb24gcmV2b2tlUGVybWlzc2lvbiAocGtnLCBwZXJtaXNzaW9uKSB7XG4gIHRyeSB7XG4gICAgYXdhaXQgdGhpcy5zaGVsbChbJ3BtJywgJ3Jldm9rZScsIHBrZywgcGVybWlzc2lvbl0pO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKCFOT1RfQ0hBTkdFQUJMRV9QRVJNX0VSUk9SLnRlc3QoZS5zdGRlcnIgfHwgZS5tZXNzYWdlKSkge1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gIH1cbn07XG5cbi8qKlxuICogUmV0cmlldmUgdGhlIGxpc3Qgb2YgZ3JhbnRlZCBwZXJtaXNzaW9ucyBmb3IgdGhlIHBhcnRpY3VsYXIgcGFja2FnZS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcGtnIC0gVGhlIHBhY2thZ2UgbmFtZSB0byBiZSBwcm9jZXNzZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gY21kT3V0cHV0IFtudWxsXSAtIE9wdGlvbmFsIHBhcmFtZXRlciBjb250YWluaW5nIGNvbW1hbmQgb3V0cHV0IG9mXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9kdW1wc3lzIHBhY2thZ2VfIGNvbW1hbmQuIEl0IG1heSBzcGVlZCB1cCB0aGUgbWV0aG9kIGV4ZWN1dGlvbi5cbiAqIEByZXR1cm4ge0FycmF5PFN0cmluZz59IFRoZSBsaXN0IG9mIGdyYW50ZWQgcGVybWlzc2lvbnMgb3IgYW4gZW1wdHkgbGlzdC5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGVyZSB3YXMgYW4gZXJyb3Igd2hpbGUgY2hhbmdpbmcgcGVybWlzc2lvbnMuXG4gKi9cbm1ldGhvZHMuZ2V0R3JhbnRlZFBlcm1pc3Npb25zID0gYXN5bmMgZnVuY3Rpb24gZ2V0R3JhbnRlZFBlcm1pc3Npb25zIChwa2csIGNtZE91dHB1dCA9IG51bGwpIHtcbiAgbG9nLmRlYnVnKCdSZXRyaWV2aW5nIGdyYW50ZWQgcGVybWlzc2lvbnMnKTtcbiAgY29uc3Qgc3Rkb3V0ID0gY21kT3V0cHV0IHx8IGF3YWl0IHRoaXMuc2hlbGwoWydkdW1wc3lzJywgJ3BhY2thZ2UnLCBwa2ddKTtcbiAgcmV0dXJuIGV4dHJhY3RNYXRjaGluZ1Blcm1pc3Npb25zKHN0ZG91dCwgWydpbnN0YWxsJywgJ3J1bnRpbWUnXSwgdHJ1ZSk7XG59O1xuXG4vKipcbiAqIFJldHJpZXZlIHRoZSBsaXN0IG9mIGRlbmllZCBwZXJtaXNzaW9ucyBmb3IgdGhlIHBhcnRpY3VsYXIgcGFja2FnZS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcGtnIC0gVGhlIHBhY2thZ2UgbmFtZSB0byBiZSBwcm9jZXNzZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gY21kT3V0cHV0IFtudWxsXSAtIE9wdGlvbmFsIHBhcmFtZXRlciBjb250YWluaW5nIGNvbW1hbmQgb3V0cHV0IG9mXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9kdW1wc3lzIHBhY2thZ2VfIGNvbW1hbmQuIEl0IG1heSBzcGVlZCB1cCB0aGUgbWV0aG9kIGV4ZWN1dGlvbi5cbiAqIEByZXR1cm4ge0FycmF5PFN0cmluZz59IFRoZSBsaXN0IG9mIGRlbmllZCBwZXJtaXNzaW9ucyBvciBhbiBlbXB0eSBsaXN0LlxuICovXG5tZXRob2RzLmdldERlbmllZFBlcm1pc3Npb25zID0gYXN5bmMgZnVuY3Rpb24gZ2V0RGVuaWVkUGVybWlzc2lvbnMgKHBrZywgY21kT3V0cHV0ID0gbnVsbCkge1xuICBsb2cuZGVidWcoJ1JldHJpZXZpbmcgZGVuaWVkIHBlcm1pc3Npb25zJyk7XG4gIGNvbnN0IHN0ZG91dCA9IGNtZE91dHB1dCB8fCBhd2FpdCB0aGlzLnNoZWxsKFsnZHVtcHN5cycsICdwYWNrYWdlJywgcGtnXSk7XG4gIHJldHVybiBleHRyYWN0TWF0Y2hpbmdQZXJtaXNzaW9ucyhzdGRvdXQsIFsnaW5zdGFsbCcsICdydW50aW1lJ10sIGZhbHNlKTtcbn07XG5cbi8qKlxuICogUmV0cmlldmUgdGhlIGxpc3Qgb2YgcmVxdWVzdGVkIHBlcm1pc3Npb25zIGZvciB0aGUgcGFydGljdWxhciBwYWNrYWdlLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwa2cgLSBUaGUgcGFja2FnZSBuYW1lIHRvIGJlIHByb2Nlc3NlZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjbWRPdXRwdXQgW251bGxdIC0gT3B0aW9uYWwgcGFyYW1ldGVyIGNvbnRhaW5pbmcgY29tbWFuZCBvdXRwdXQgb2ZcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX2R1bXBzeXMgcGFja2FnZV8gY29tbWFuZC4gSXQgbWF5IHNwZWVkIHVwIHRoZSBtZXRob2QgZXhlY3V0aW9uLlxuICogQHJldHVybiB7QXJyYXk8U3RyaW5nPn0gVGhlIGxpc3Qgb2YgcmVxdWVzdGVkIHBlcm1pc3Npb25zIG9yIGFuIGVtcHR5IGxpc3QuXG4gKi9cbm1ldGhvZHMuZ2V0UmVxUGVybWlzc2lvbnMgPSBhc3luYyBmdW5jdGlvbiBnZXRSZXFQZXJtaXNzaW9ucyAocGtnLCBjbWRPdXRwdXQgPSBudWxsKSB7XG4gIGxvZy5kZWJ1ZygnUmV0cmlldmluZyByZXF1ZXN0ZWQgcGVybWlzc2lvbnMnKTtcbiAgY29uc3Qgc3Rkb3V0ID0gY21kT3V0cHV0IHx8IGF3YWl0IHRoaXMuc2hlbGwoWydkdW1wc3lzJywgJ3BhY2thZ2UnLCBwa2ddKTtcbiAgcmV0dXJuIGV4dHJhY3RNYXRjaGluZ1Blcm1pc3Npb25zKHN0ZG91dCwgWydyZXF1ZXN0ZWQnXSk7XG59O1xuXG4vKipcbiAqIFJldHJpZXZlIHRoZSBsaXN0IG9mIGxvY2F0aW9uIHByb3ZpZGVycyBmb3IgdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEByZXR1cm4ge0FycmF5LjxTdHJpbmc+fSBUaGUgbGlzdCBvZiBhdmFpbGFibGUgbG9jYXRpb24gcHJvdmlkZXJzIG9yIGFuIGVtcHR5IGxpc3QuXG4gKi9cbm1ldGhvZHMuZ2V0TG9jYXRpb25Qcm92aWRlcnMgPSBhc3luYyBmdW5jdGlvbiBnZXRMb2NhdGlvblByb3ZpZGVycyAoKSB7XG4gIGxldCBzdGRvdXQgPSBhd2FpdCB0aGlzLmdldFNldHRpbmcoJ3NlY3VyZScsICdsb2NhdGlvbl9wcm92aWRlcnNfYWxsb3dlZCcpO1xuICByZXR1cm4gc3Rkb3V0LnRyaW0oKS5zcGxpdCgnLCcpXG4gICAgLm1hcCgocCkgPT4gcC50cmltKCkpXG4gICAgLmZpbHRlcihCb29sZWFuKTtcbn07XG5cbi8qKlxuICogVG9nZ2xlIHRoZSBzdGF0ZSBvZiBHUFMgbG9jYXRpb24gcHJvdmlkZXIuXG4gKlxuICogQHBhcmFtIHtib29sZWFufSBlbmFibGVkIC0gV2hldGhlciB0byBlbmFibGUgKHRydWUpIG9yIGRpc2FibGUgKGZhbHNlKSB0aGUgR1BTIHByb3ZpZGVyLlxuICovXG5tZXRob2RzLnRvZ2dsZUdQU0xvY2F0aW9uUHJvdmlkZXIgPSBhc3luYyBmdW5jdGlvbiB0b2dnbGVHUFNMb2NhdGlvblByb3ZpZGVyIChlbmFibGVkKSB7XG4gIGF3YWl0IHRoaXMuc2V0U2V0dGluZygnc2VjdXJlJywgJ2xvY2F0aW9uX3Byb3ZpZGVyc19hbGxvd2VkJywgYCR7ZW5hYmxlZCA/ICcrJyA6ICctJ31ncHNgKTtcbn07XG5cbi8qKlxuICogU2V0IGhpZGRlbiBhcGkgcG9saWN5IHRvIG1hbmFnZSBhY2Nlc3MgdG8gbm9uLVNESyBBUElzLlxuICogaHR0cHM6Ly9kZXZlbG9wZXIuYW5kcm9pZC5jb20vcHJldmlldy9yZXN0cmljdGlvbnMtbm9uLXNkay1pbnRlcmZhY2VzXG4gKlxuICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfSB2YWx1ZSAtIFRoZSBBUEkgZW5mb3JjZW1lbnQgcG9saWN5LlxuICogICAgIEZvciBBbmRyb2lkIFBcbiAqICAgICAwOiBEaXNhYmxlIG5vbi1TREsgQVBJIHVzYWdlIGRldGVjdGlvbi4gVGhpcyB3aWxsIGFsc28gZGlzYWJsZSBsb2dnaW5nLCBhbmQgYWxzbyBicmVhayB0aGUgc3RyaWN0IG1vZGUgQVBJLFxuICogICAgICAgIGRldGVjdE5vblNka0FwaVVzYWdlKCkuIE5vdCByZWNvbW1lbmRlZC5cbiAqICAgICAxOiBcIkp1c3Qgd2FyblwiIC0gcGVybWl0IGFjY2VzcyB0byBhbGwgbm9uLVNESyBBUElzLCBidXQga2VlcCB3YXJuaW5ncyBpbiB0aGUgbG9nLlxuICogICAgICAgIFRoZSBzdHJpY3QgbW9kZSBBUEkgd2lsbCBrZWVwIHdvcmtpbmcuXG4gKiAgICAgMjogRGlzYWxsb3cgdXNhZ2Ugb2YgZGFyayBncmV5IGFuZCBibGFjayBsaXN0ZWQgQVBJcy5cbiAqICAgICAzOiBEaXNhbGxvdyB1c2FnZSBvZiBibGFja2xpc3RlZCBBUElzLCBidXQgYWxsb3cgdXNhZ2Ugb2YgZGFyayBncmV5IGxpc3RlZCBBUElzLlxuICpcbiAqICAgICBGb3IgQW5kcm9pZCBRXG4gKiAgICAgaHR0cHM6Ly9kZXZlbG9wZXIuYW5kcm9pZC5jb20vcHJldmlldy9ub24tc2RrLXEjZW5hYmxlLW5vbi1zZGstYWNjZXNzXG4gKiAgICAgMDogRGlzYWJsZSBhbGwgZGV0ZWN0aW9uIG9mIG5vbi1TREsgaW50ZXJmYWNlcy4gVXNpbmcgdGhpcyBzZXR0aW5nIGRpc2FibGVzIGFsbCBsb2cgbWVzc2FnZXMgZm9yIG5vbi1TREsgaW50ZXJmYWNlIHVzYWdlXG4gKiAgICAgICAgYW5kIHByZXZlbnRzIHlvdSBmcm9tIHRlc3RpbmcgeW91ciBhcHAgdXNpbmcgdGhlIFN0cmljdE1vZGUgQVBJLiBUaGlzIHNldHRpbmcgaXMgbm90IHJlY29tbWVuZGVkLlxuICogICAgIDE6IEVuYWJsZSBhY2Nlc3MgdG8gYWxsIG5vbi1TREsgaW50ZXJmYWNlcywgYnV0IHByaW50IGxvZyBtZXNzYWdlcyB3aXRoIHdhcm5pbmdzIGZvciBhbnkgbm9uLVNESyBpbnRlcmZhY2UgdXNhZ2UuXG4gKiAgICAgICAgVXNpbmcgdGhpcyBzZXR0aW5nIGFsc28gYWxsb3dzIHlvdSB0byB0ZXN0IHlvdXIgYXBwIHVzaW5nIHRoZSBTdHJpY3RNb2RlIEFQSS5cbiAqICAgICAyOiBEaXNhbGxvdyB1c2FnZSBvZiBub24tU0RLIGludGVyZmFjZXMgdGhhdCBiZWxvbmcgdG8gZWl0aGVyIHRoZSBibGFjayBsaXN0XG4gKiAgICAgICAgb3IgdG8gYSByZXN0cmljdGVkIGdyZXlsaXN0IGZvciB5b3VyIHRhcmdldCBBUEkgbGV2ZWwuXG4gKlxuICogQHBhcmFtIHtib29sZWFufSBpZ25vcmVFcnJvciBbZmFsc2VdIFdoZXRoZXIgdG8gaWdub3JlIGFuIGV4Y2VwdGlvbiBpbiAnYWRiIHNoZWxsIHNldHRpbmdzIHB1dCBnbG9iYWwnIGNvbW1hbmRcbiAqIEB0aHJvd3Mge2Vycm9yfSBJZiB0aGVyZSB3YXMgYW4gZXJyb3IgYW5kIGlnbm9yZUVycm9yIHdhcyB0cnVlIHdoaWxlIGV4ZWN1dGluZyAnYWRiIHNoZWxsIHNldHRpbmdzIHB1dCBnbG9iYWwnXG4gKiAgICAgICAgICAgICAgICAgY29tbWFuZCBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKi9cbm1ldGhvZHMuc2V0SGlkZGVuQXBpUG9saWN5ID0gYXN5bmMgZnVuY3Rpb24gc2V0SGlkZGVuQXBpUG9saWN5ICh2YWx1ZSwgaWdub3JlRXJyb3IgPSBmYWxzZSkge1xuICB0cnkge1xuICAgIGF3YWl0IHRoaXMuc2hlbGwoSElEREVOX0FQSV9QT0xJQ1lfS0VZUy5tYXAoKGspID0+IGBzZXR0aW5ncyBwdXQgZ2xvYmFsICR7a30gJHt2YWx1ZX1gKS5qb2luKCc7JykpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKCFpZ25vcmVFcnJvcikge1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gICAgbG9nLmluZm8oYEZhaWxlZCB0byBzZXQgc2V0dGluZyBrZXlzICcke0hJRERFTl9BUElfUE9MSUNZX0tFWVN9JyB0byAnJHt2YWx1ZX0nLiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gIH1cbn07XG5cbi8qKlxuICogUmVzZXQgYWNjZXNzIHRvIG5vbi1TREsgQVBJcyB0byBpdHMgZGVmYXVsdCBzZXR0aW5nLlxuICogaHR0cHM6Ly9kZXZlbG9wZXIuYW5kcm9pZC5jb20vcHJldmlldy9yZXN0cmljdGlvbnMtbm9uLXNkay1pbnRlcmZhY2VzXG4gKlxuICogQHBhcmFtIHtib29sZWFufSBpZ25vcmVFcnJvciBbZmFsc2VdIFdoZXRoZXIgdG8gaWdub3JlIGFuIGV4Y2VwdGlvbiBpbiAnYWRiIHNoZWxsIHNldHRpbmdzIGRlbGV0ZSBnbG9iYWwnIGNvbW1hbmRcbiAqIEB0aHJvd3Mge2Vycm9yfSBJZiB0aGVyZSB3YXMgYW4gZXJyb3IgYW5kIGlnbm9yZUVycm9yIHdhcyB0cnVlIHdoaWxlIGV4ZWN1dGluZyAnYWRiIHNoZWxsIHNldHRpbmdzIGRlbGV0ZSBnbG9iYWwnXG4gKiAgICAgICAgICAgICAgICAgY29tbWFuZCBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKi9cbm1ldGhvZHMuc2V0RGVmYXVsdEhpZGRlbkFwaVBvbGljeSA9IGFzeW5jIGZ1bmN0aW9uIHNldERlZmF1bHRIaWRkZW5BcGlQb2xpY3kgKGlnbm9yZUVycm9yID0gZmFsc2UpIHtcbiAgdHJ5IHtcbiAgICBhd2FpdCB0aGlzLnNoZWxsKEhJRERFTl9BUElfUE9MSUNZX0tFWVMubWFwKChrKSA9PiBgc2V0dGluZ3MgZGVsZXRlIGdsb2JhbCAke2t9YCkuam9pbignOycpKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmICghaWdub3JlRXJyb3IpIHtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICAgIGxvZy5pbmZvKGBGYWlsZWQgdG8gZGVsZXRlIGtleXMgJyR7SElEREVOX0FQSV9QT0xJQ1lfS0VZU30nLiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gIH1cbn07XG5cbi8qKlxuICogU3RvcCB0aGUgcGFydGljdWxhciBwYWNrYWdlIGlmIGl0IGlzIHJ1bm5pbmcgYW5kIGNsZWFycyBpdHMgYXBwbGljYXRpb24gZGF0YS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcGtnIC0gVGhlIHBhY2thZ2UgbmFtZSB0byBiZSBwcm9jZXNzZWQuXG4gKi9cbm1ldGhvZHMuc3RvcEFuZENsZWFyID0gYXN5bmMgZnVuY3Rpb24gc3RvcEFuZENsZWFyIChwa2cpIHtcbiAgdHJ5IHtcbiAgICBhd2FpdCB0aGlzLmZvcmNlU3RvcChwa2cpO1xuICAgIGF3YWl0IHRoaXMuY2xlYXIocGtnKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHN0b3AgYW5kIGNsZWFyICR7cGtnfS4gT3JpZ2luYWwgZXJyb3I6ICR7ZS5tZXNzYWdlfWApO1xuICB9XG59O1xuXG4vKipcbiAqIFJldHJpZXZlIHRoZSBsaXN0IG9mIGF2YWlsYWJsZSBpbnB1dCBtZXRob2RzIChJTUVzKSBmb3IgdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEByZXR1cm4ge0FycmF5LjxTdHJpbmc+fSBUaGUgbGlzdCBvZiBJTUUgbmFtZXMgb3IgYW4gZW1wdHkgbGlzdC5cbiAqL1xubWV0aG9kcy5hdmFpbGFibGVJTUVzID0gYXN5bmMgZnVuY3Rpb24gYXZhaWxhYmxlSU1FcyAoKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGdldElNRUxpc3RGcm9tT3V0cHV0KGF3YWl0IHRoaXMuc2hlbGwoWydpbWUnLCAnbGlzdCcsICctYSddKSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIGdldHRpbmcgYXZhaWxhYmxlIElNRSdzLiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gIH1cbn07XG5cbi8qKlxuICogUmV0cmlldmUgdGhlIGxpc3Qgb2YgZW5hYmxlZCBpbnB1dCBtZXRob2RzIChJTUVzKSBmb3IgdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEByZXR1cm4ge0FycmF5LjxTdHJpbmc+fSBUaGUgbGlzdCBvZiBlbmFibGVkIElNRSBuYW1lcyBvciBhbiBlbXB0eSBsaXN0LlxuICovXG5tZXRob2RzLmVuYWJsZWRJTUVzID0gYXN5bmMgZnVuY3Rpb24gZW5hYmxlZElNRXMgKCkge1xuICB0cnkge1xuICAgIHJldHVybiBnZXRJTUVMaXN0RnJvbU91dHB1dChhd2FpdCB0aGlzLnNoZWxsKFsnaW1lJywgJ2xpc3QnXSkpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciBnZXR0aW5nIGVuYWJsZWQgSU1FJ3MuIE9yaWdpbmFsIGVycm9yOiAke2UubWVzc2FnZX1gKTtcbiAgfVxufTtcblxuLyoqXG4gKiBFbmFibGUgdGhlIHBhcnRpY3VsYXIgaW5wdXQgbWV0aG9kIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaW1lSWQgLSBPbmUgb2YgZXhpc3RpbmcgSU1FIGlkcy5cbiAqL1xubWV0aG9kcy5lbmFibGVJTUUgPSBhc3luYyBmdW5jdGlvbiBlbmFibGVJTUUgKGltZUlkKSB7XG4gIGF3YWl0IHRoaXMuc2hlbGwoWydpbWUnLCAnZW5hYmxlJywgaW1lSWRdKTtcbn07XG5cbi8qKlxuICogRGlzYWJsZSB0aGUgcGFydGljdWxhciBpbnB1dCBtZXRob2Qgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBpbWVJZCAtIE9uZSBvZiBleGlzdGluZyBJTUUgaWRzLlxuICovXG5tZXRob2RzLmRpc2FibGVJTUUgPSBhc3luYyBmdW5jdGlvbiBkaXNhYmxlSU1FIChpbWVJZCkge1xuICBhd2FpdCB0aGlzLnNoZWxsKFsnaW1lJywgJ2Rpc2FibGUnLCBpbWVJZF0pO1xufTtcblxuLyoqXG4gKiBTZXQgdGhlIHBhcnRpY3VsYXIgaW5wdXQgbWV0aG9kIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaW1lSWQgLSBPbmUgb2YgZXhpc3RpbmcgSU1FIGlkcy5cbiAqL1xubWV0aG9kcy5zZXRJTUUgPSBhc3luYyBmdW5jdGlvbiBzZXRJTUUgKGltZUlkKSB7XG4gIGF3YWl0IHRoaXMuc2hlbGwoWydpbWUnLCAnc2V0JywgaW1lSWRdKTtcbn07XG5cbi8qKlxuICogR2V0IHRoZSBkZWZhdWx0IGlucHV0IG1ldGhvZCBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHJldHVybiB7P3N0cmluZ30gVGhlIG5hbWUgb2YgdGhlIGRlZmF1bHQgaW5wdXQgbWV0aG9kXG4gKi9cbm1ldGhvZHMuZGVmYXVsdElNRSA9IGFzeW5jIGZ1bmN0aW9uIGRlZmF1bHRJTUUgKCkge1xuICB0cnkge1xuICAgIGxldCBlbmdpbmUgPSBhd2FpdCB0aGlzLmdldFNldHRpbmcoJ3NlY3VyZScsICdkZWZhdWx0X2lucHV0X21ldGhvZCcpO1xuICAgIGlmIChlbmdpbmUgPT09ICdudWxsJykge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHJldHVybiBlbmdpbmUudHJpbSgpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciBnZXR0aW5nIGRlZmF1bHQgSU1FLiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gIH1cbn07XG5cbi8qKlxuICogU2VuZCB0aGUgcGFydGljdWxhciBrZXljb2RlIHRvIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGtleWNvZGUgLSBUaGUgYWN0dWFsIGtleSBjb2RlIHRvIGJlIHNlbnQuXG4gKi9cbm1ldGhvZHMua2V5ZXZlbnQgPSBhc3luYyBmdW5jdGlvbiBrZXlldmVudCAoa2V5Y29kZSkge1xuICAvLyBrZXljb2RlIG11c3QgYmUgYW4gaW50LlxuICBsZXQgY29kZSA9IHBhcnNlSW50KGtleWNvZGUsIDEwKTtcbiAgYXdhaXQgdGhpcy5zaGVsbChbJ2lucHV0JywgJ2tleWV2ZW50JywgY29kZV0pO1xufTtcblxuLyoqXG4gKiBTZW5kIHRoZSBwYXJ0aWN1bGFyIHRleHQgdG8gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IC0gVGhlIGFjdHVhbCB0ZXh0IHRvIGJlIHNlbnQuXG4gKi9cbm1ldGhvZHMuaW5wdXRUZXh0ID0gYXN5bmMgZnVuY3Rpb24gaW5wdXRUZXh0ICh0ZXh0KSB7XG4gIC8qIGVzbGludC1kaXNhYmxlIG5vLXVzZWxlc3MtZXNjYXBlICovXG4gIC8vIG5lZWQgdG8gZXNjYXBlIHdoaXRlc3BhY2UgYW5kICggKSA8ID4gfCA7ICYgKiBcXCB+IFwiICdcbiAgdGV4dCA9IHRleHRcbiAgICAgICAgICAucmVwbGFjZSgvXFxcXC9nLCAnXFxcXFxcXFwnKVxuICAgICAgICAgIC5yZXBsYWNlKC9cXCgvZywgJ1xcKCcpXG4gICAgICAgICAgLnJlcGxhY2UoL1xcKS9nLCAnXFwpJylcbiAgICAgICAgICAucmVwbGFjZSgvPC9nLCAnXFw8JylcbiAgICAgICAgICAucmVwbGFjZSgvPi9nLCAnXFw+JylcbiAgICAgICAgICAucmVwbGFjZSgvXFx8L2csICdcXHwnKVxuICAgICAgICAgIC5yZXBsYWNlKC87L2csICdcXDsnKVxuICAgICAgICAgIC5yZXBsYWNlKC8mL2csICdcXCYnKVxuICAgICAgICAgIC5yZXBsYWNlKC9cXCovZywgJ1xcKicpXG4gICAgICAgICAgLnJlcGxhY2UoL34vZywgJ1xcficpXG4gICAgICAgICAgLnJlcGxhY2UoL1wiL2csICdcXFwiJylcbiAgICAgICAgICAucmVwbGFjZSgvJy9nLCBcIlxcJ1wiKVxuICAgICAgICAgIC5yZXBsYWNlKC8gL2csICclcycpO1xuICAvKiBlc2xpbnQtZGlzYWJsZSBuby11c2VsZXNzLWVzY2FwZSAqL1xuICBhd2FpdCB0aGlzLnNoZWxsKFsnaW5wdXQnLCAndGV4dCcsIHRleHRdKTtcbn07XG5cbi8qKlxuICogQ2xlYXIgdGhlIGFjdGl2ZSB0ZXh0IGZpZWxkIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdCBieSBzZW5kaW5nXG4gKiBzcGVjaWFsIGtleWV2ZW50cyB0byBpdC5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gbGVuZ3RoIFsxMDBdIC0gVGhlIG1heGltdW0gbGVuZ3RoIG9mIHRoZSB0ZXh0IGluIHRoZSBmaWVsZCB0byBiZSBjbGVhcmVkLlxuICovXG5tZXRob2RzLmNsZWFyVGV4dEZpZWxkID0gYXN5bmMgZnVuY3Rpb24gY2xlYXJUZXh0RmllbGQgKGxlbmd0aCA9IDEwMCkge1xuICAvLyBhc3N1bWVzIHRoYXQgdGhlIEVkaXRUZXh0IGZpZWxkIGFscmVhZHkgaGFzIGZvY3VzXG4gIGxvZy5kZWJ1ZyhgQ2xlYXJpbmcgdXAgdG8gJHtsZW5ndGh9IGNoYXJhY3RlcnNgKTtcbiAgaWYgKGxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybjtcbiAgfVxuICBsZXQgYXJncyA9IFsnaW5wdXQnLCAna2V5ZXZlbnQnXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgIC8vIHdlIGNhbm5vdCBrbm93IHdoZXJlIHRoZSBjdXJzb3IgaXMgaW4gdGhlIHRleHQgZmllbGQsIHNvIGRlbGV0ZSBib3RoIGJlZm9yZVxuICAgIC8vIGFuZCBhZnRlciBzbyB0aGF0IHdlIGdldCByaWQgb2YgZXZlcnl0aGluZ1xuICAgIC8vIGh0dHBzOi8vZGV2ZWxvcGVyLmFuZHJvaWQuY29tL3JlZmVyZW5jZS9hbmRyb2lkL3ZpZXcvS2V5RXZlbnQuaHRtbCNLRVlDT0RFX0RFTFxuICAgIC8vIGh0dHBzOi8vZGV2ZWxvcGVyLmFuZHJvaWQuY29tL3JlZmVyZW5jZS9hbmRyb2lkL3ZpZXcvS2V5RXZlbnQuaHRtbCNLRVlDT0RFX0ZPUldBUkRfREVMXG4gICAgYXJncy5wdXNoKCc2NycsICcxMTInKTtcbiAgfVxuICBhd2FpdCB0aGlzLnNoZWxsKGFyZ3MpO1xufTtcblxuLyoqXG4gKiBTZW5kIHRoZSBzcGVjaWFsIGtleWNvZGUgdG8gdGhlIGRldmljZSB1bmRlciB0ZXN0IGluIG9yZGVyIHRvIGxvY2sgaXQuXG4gKi9cbm1ldGhvZHMubG9jayA9IGFzeW5jIGZ1bmN0aW9uIGxvY2sgKCkge1xuICBpZiAoYXdhaXQgdGhpcy5pc1NjcmVlbkxvY2tlZCgpKSB7XG4gICAgbG9nLmRlYnVnKCdTY3JlZW4gaXMgYWxyZWFkeSBsb2NrZWQuIERvaW5nIG5vdGhpbmcuJyk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGxvZy5kZWJ1ZygnUHJlc3NpbmcgdGhlIEtFWUNPREVfUE9XRVIgYnV0dG9uIHRvIGxvY2sgc2NyZWVuJyk7XG4gIGF3YWl0IHRoaXMua2V5ZXZlbnQoMjYpO1xuXG4gIGNvbnN0IHRpbWVvdXRNcyA9IDUwMDA7XG4gIHRyeSB7XG4gICAgYXdhaXQgd2FpdEZvckNvbmRpdGlvbihhc3luYyAoKSA9PiBhd2FpdCB0aGlzLmlzU2NyZWVuTG9ja2VkKCksIHtcbiAgICAgIHdhaXRNczogdGltZW91dE1zLFxuICAgICAgaW50ZXJ2YWxNczogNTAwLFxuICAgIH0pO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBUaGUgZGV2aWNlIHNjcmVlbiBpcyBzdGlsbCBsb2NrZWQgYWZ0ZXIgJHt0aW1lb3V0TXN9bXMgdGltZW91dGApO1xuICB9XG59O1xuXG4vKipcbiAqIFNlbmQgdGhlIHNwZWNpYWwga2V5Y29kZSB0byB0aGUgZGV2aWNlIHVuZGVyIHRlc3QgaW4gb3JkZXIgdG8gZW11bGF0ZVxuICogQmFjayBidXR0b24gdGFwLlxuICovXG5tZXRob2RzLmJhY2sgPSBhc3luYyBmdW5jdGlvbiBiYWNrICgpIHtcbiAgbG9nLmRlYnVnKCdQcmVzc2luZyB0aGUgQkFDSyBidXR0b24nKTtcbiAgYXdhaXQgdGhpcy5rZXlldmVudCg0KTtcbn07XG5cbi8qKlxuICogU2VuZCB0aGUgc3BlY2lhbCBrZXljb2RlIHRvIHRoZSBkZXZpY2UgdW5kZXIgdGVzdCBpbiBvcmRlciB0byBlbXVsYXRlXG4gKiBIb21lIGJ1dHRvbiB0YXAuXG4gKi9cbm1ldGhvZHMuZ29Ub0hvbWUgPSBhc3luYyBmdW5jdGlvbiBnb1RvSG9tZSAoKSB7XG4gIGxvZy5kZWJ1ZygnUHJlc3NpbmcgdGhlIEhPTUUgYnV0dG9uJyk7XG4gIGF3YWl0IHRoaXMua2V5ZXZlbnQoMyk7XG59O1xuXG4vKipcbiAqIEByZXR1cm4ge3N0cmluZ30gdGhlIGFjdHVhbCBwYXRoIHRvIGFkYiBleGVjdXRhYmxlLlxuICovXG5tZXRob2RzLmdldEFkYlBhdGggPSBmdW5jdGlvbiBnZXRBZGJQYXRoICgpIHtcbiAgcmV0dXJuIHRoaXMuZXhlY3V0YWJsZS5wYXRoO1xufTtcblxuLyoqXG4gKiBSZXRyaWV2ZSBjdXJyZW50IHNjcmVlbiBvcmllbnRhdGlvbiBvZiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHJldHVybiB7bnVtYmVyfSBUaGUgY3VycmVudCBvcmllbnRhdGlvbiBlbmNvZGVkIGFzIGFuIGludGVnZXIgbnVtYmVyLlxuICovXG5tZXRob2RzLmdldFNjcmVlbk9yaWVudGF0aW9uID0gYXN5bmMgZnVuY3Rpb24gZ2V0U2NyZWVuT3JpZW50YXRpb24gKCkge1xuICBsZXQgc3Rkb3V0ID0gYXdhaXQgdGhpcy5zaGVsbChbJ2R1bXBzeXMnLCAnaW5wdXQnXSk7XG4gIHJldHVybiBnZXRTdXJmYWNlT3JpZW50YXRpb24oc3Rkb3V0KTtcbn07XG5cbi8qKlxuICogUmV0cmlldmUgdGhlIHNjcmVlbiBsb2NrIHN0YXRlIG9mIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIHRoZSBkZXZpY2UgaXMgbG9ja2VkLlxuICovXG5tZXRob2RzLmlzU2NyZWVuTG9ja2VkID0gYXN5bmMgZnVuY3Rpb24gaXNTY3JlZW5Mb2NrZWQgKCkge1xuICBsZXQgc3Rkb3V0ID0gYXdhaXQgdGhpcy5zaGVsbChbJ2R1bXBzeXMnLCAnd2luZG93J10pO1xuICBpZiAocHJvY2Vzcy5lbnYuQVBQSVVNX0xPR19EVU1QU1lTKSB7XG4gICAgLy8gb3B0aW9uYWwgZGVidWdnaW5nXG4gICAgLy8gaWYgdGhlIG1ldGhvZCBpcyBub3Qgd29ya2luZywgdHVybiBpdCBvbiBhbmQgc2VuZCB1cyB0aGUgb3V0cHV0XG4gICAgbGV0IGR1bXBzeXNGaWxlID0gcGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksICdkdW1wc3lzLmxvZycpO1xuICAgIGxvZy5kZWJ1ZyhgV3JpdGluZyBkdW1wc3lzIG91dHB1dCB0byAke2R1bXBzeXNGaWxlfWApO1xuICAgIGF3YWl0IGZzLndyaXRlRmlsZShkdW1wc3lzRmlsZSwgc3Rkb3V0KTtcbiAgfVxuICByZXR1cm4gKGlzU2hvd2luZ0xvY2tzY3JlZW4oc3Rkb3V0KSB8fCBpc0N1cnJlbnRGb2N1c09uS2V5Z3VhcmQoc3Rkb3V0KSB8fFxuICAgICAgICAgICFpc1NjcmVlbk9uRnVsbHkoc3Rkb3V0KSk7XG59O1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IEtleWJvYXJkU3RhdGVcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gaXNLZXlib2FyZFNob3duIC0gV2hldGhlciBzb2Z0IGtleWJvYXJkIGlzIGN1cnJlbnRseSB2aXNpYmxlLlxuICogQHByb3BlcnR5IHtib29sZWFufSBjYW5DbG9zZUtleWJvYXJkIC0gV2hldGhlciB0aGUga2V5Ym9hcmQgY2FuIGJlIGNsb3NlZC5cbiAqL1xuXG4vKipcbiAqIFJldHJpZXZlIHRoZSBzdGF0ZSBvZiB0aGUgc29mdHdhcmUga2V5Ym9hcmQgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEByZXR1cm4ge0tleWJvYXJkU3RhdGV9IFRoZSBrZXlib2FyZCBzdGF0ZS5cbiAqL1xubWV0aG9kcy5pc1NvZnRLZXlib2FyZFByZXNlbnQgPSBhc3luYyBmdW5jdGlvbiBpc1NvZnRLZXlib2FyZFByZXNlbnQgKCkge1xuICB0cnkge1xuICAgIGNvbnN0IHN0ZG91dCA9IGF3YWl0IHRoaXMuc2hlbGwoWydkdW1wc3lzJywgJ2lucHV0X21ldGhvZCddKTtcbiAgICBjb25zdCBpbnB1dFNob3duTWF0Y2ggPSAvbUlucHV0U2hvd249KFxcdyspLy5leGVjKHN0ZG91dCk7XG4gICAgY29uc3QgaW5wdXRWaWV3U2hvd25NYXRjaCA9IC9tSXNJbnB1dFZpZXdTaG93bj0oXFx3KykvLmV4ZWMoc3Rkb3V0KTtcbiAgICByZXR1cm4ge1xuICAgICAgaXNLZXlib2FyZFNob3duOiAhIShpbnB1dFNob3duTWF0Y2ggJiYgaW5wdXRTaG93bk1hdGNoWzFdID09PSAndHJ1ZScpLFxuICAgICAgY2FuQ2xvc2VLZXlib2FyZDogISEoaW5wdXRWaWV3U2hvd25NYXRjaCAmJiBpbnB1dFZpZXdTaG93bk1hdGNoWzFdID09PSAndHJ1ZScpLFxuICAgIH07XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIGZpbmRpbmcgc29mdGtleWJvYXJkLiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gIH1cbn07XG5cbi8qKlxuICogU2VuZCBhbiBhcmJpdHJhcnkgVGVsbmV0IGNvbW1hbmQgdG8gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBjb21tYW5kIC0gVGhlIGNvbW1hbmQgdG8gYmUgc2VudC5cbiAqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBhY3R1YWwgb3V0cHV0IG9mIHRoZSBnaXZlbiBjb21tYW5kLlxuICovXG5tZXRob2RzLnNlbmRUZWxuZXRDb21tYW5kID0gYXN5bmMgZnVuY3Rpb24gc2VuZFRlbG5ldENvbW1hbmQgKGNvbW1hbmQpIHtcbiAgbG9nLmRlYnVnKGBTZW5kaW5nIHRlbG5ldCBjb21tYW5kIHRvIGRldmljZTogJHtjb21tYW5kfWApO1xuICBsZXQgcG9ydCA9IGF3YWl0IHRoaXMuZ2V0RW11bGF0b3JQb3J0KCk7XG4gIHJldHVybiBhd2FpdCBuZXcgQigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgbGV0IGNvbm4gPSBuZXQuY3JlYXRlQ29ubmVjdGlvbihwb3J0LCAnbG9jYWxob3N0JyksXG4gICAgICAgIGNvbm5lY3RlZCA9IGZhbHNlLFxuICAgICAgICByZWFkeVJlZ2V4ID0gL15PSyQvbSxcbiAgICAgICAgZGF0YVN0cmVhbSA9ICcnLFxuICAgICAgICByZXMgPSBudWxsO1xuICAgIGNvbm4ub24oJ2Nvbm5lY3QnLCAoKSA9PiB7XG4gICAgICBsb2cuZGVidWcoJ1NvY2tldCBjb25uZWN0aW9uIHRvIGRldmljZSBjcmVhdGVkJyk7XG4gICAgfSk7XG4gICAgY29ubi5vbignZGF0YScsIChkYXRhKSA9PiB7XG4gICAgICBkYXRhID0gZGF0YS50b1N0cmluZygndXRmOCcpO1xuICAgICAgaWYgKCFjb25uZWN0ZWQpIHtcbiAgICAgICAgaWYgKHJlYWR5UmVnZXgudGVzdChkYXRhKSkge1xuICAgICAgICAgIGNvbm5lY3RlZCA9IHRydWU7XG4gICAgICAgICAgbG9nLmRlYnVnKCdTb2NrZXQgY29ubmVjdGlvbiB0byBkZXZpY2UgcmVhZHknKTtcbiAgICAgICAgICBjb25uLndyaXRlKGAke2NvbW1hbmR9XFxuYCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRhdGFTdHJlYW0gKz0gZGF0YTtcbiAgICAgICAgaWYgKHJlYWR5UmVnZXgudGVzdChkYXRhKSkge1xuICAgICAgICAgIHJlcyA9IGRhdGFTdHJlYW0ucmVwbGFjZShyZWFkeVJlZ2V4LCAnJykudHJpbSgpO1xuICAgICAgICAgIHJlcyA9IF8ubGFzdChyZXMudHJpbSgpLnNwbGl0KCdcXG4nKSk7XG4gICAgICAgICAgbG9nLmRlYnVnKGBUZWxuZXQgY29tbWFuZCBnb3QgcmVzcG9uc2U6ICR7cmVzfWApO1xuICAgICAgICAgIGNvbm4ud3JpdGUoJ3F1aXRcXG4nKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIGNvbm4ub24oJ2Vycm9yJywgKGVycikgPT4geyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIHByb21pc2UvcHJlZmVyLWF3YWl0LXRvLWNhbGxiYWNrc1xuICAgICAgbG9nLmRlYnVnKGBUZWxuZXQgY29tbWFuZCBlcnJvcjogJHtlcnIubWVzc2FnZX1gKTtcbiAgICAgIHJlamVjdChlcnIpO1xuICAgIH0pO1xuICAgIGNvbm4ub24oJ2Nsb3NlJywgKCkgPT4ge1xuICAgICAgaWYgKHJlcyA9PT0gbnVsbCkge1xuICAgICAgICByZWplY3QobmV3IEVycm9yKCdOZXZlciBnb3QgYSByZXNwb25zZSBmcm9tIGNvbW1hbmQnKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXNvbHZlKHJlcyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufTtcblxuLyoqXG4gKiBDaGVjayB0aGUgc3RhdGUgb2YgQWlycGxhbmUgbW9kZSBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiBBaXJwbGFuZSBtb2RlIGlzIGVuYWJsZWQuXG4gKi9cbm1ldGhvZHMuaXNBaXJwbGFuZU1vZGVPbiA9IGFzeW5jIGZ1bmN0aW9uIGlzQWlycGxhbmVNb2RlT24gKCkge1xuICBsZXQgc3Rkb3V0ID0gYXdhaXQgdGhpcy5nZXRTZXR0aW5nKCdnbG9iYWwnLCAnYWlycGxhbmVfbW9kZV9vbicpO1xuICByZXR1cm4gcGFyc2VJbnQoc3Rkb3V0LCAxMCkgIT09IDA7XG59O1xuXG4vKipcbiAqIENoYW5nZSB0aGUgc3RhdGUgb2YgQWlycGxhbmUgbW9kZSBpbiBTZXR0aW5ncyBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHBhcmFtIHtib29sZWFufSBvbiAtIFRydWUgdG8gZW5hYmxlIHRoZSBBaXJwbGFuZSBtb2RlIGluIFNldHRpbmdzIGFuZCBmYWxzZSB0byBkaXNhYmxlIGl0LlxuICovXG5tZXRob2RzLnNldEFpcnBsYW5lTW9kZSA9IGFzeW5jIGZ1bmN0aW9uIHNldEFpcnBsYW5lTW9kZSAob24pIHtcbiAgYXdhaXQgdGhpcy5zZXRTZXR0aW5nKCdnbG9iYWwnLCAnYWlycGxhbmVfbW9kZV9vbicsIG9uID8gMSA6IDApO1xufTtcblxuLyoqXG4gKiBCcm9hZGNhc3QgdGhlIHN0YXRlIG9mIEFpcnBsYW5lIG1vZGUgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICogVGhpcyBtZXRob2Qgc2hvdWxkIGJlIGNhbGxlZCBhZnRlciB7QGxpbmsgI3NldEFpcnBsYW5lTW9kZX0sIG90aGVyd2lzZVxuICogdGhlIG1vZGUgY2hhbmdlIGlzIG5vdCBnb2luZyB0byBiZSBhcHBsaWVkIGZvciB0aGUgZGV2aWNlLlxuICpcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gb24gLSBUcnVlIHRvIGJyb2FkY2FzdCBlbmFibGUgYW5kIGZhbHNlIHRvIGJyb2FkY2FzdCBkaXNhYmxlLlxuICovXG5tZXRob2RzLmJyb2FkY2FzdEFpcnBsYW5lTW9kZSA9IGFzeW5jIGZ1bmN0aW9uIGJyb2FkY2FzdEFpcnBsYW5lTW9kZSAob24pIHtcbiAgYXdhaXQgdGhpcy5zaGVsbChbXG4gICAgJ2FtJywgJ2Jyb2FkY2FzdCcsXG4gICAgJy1hJywgJ2FuZHJvaWQuaW50ZW50LmFjdGlvbi5BSVJQTEFORV9NT0RFJyxcbiAgICAnLS1leicsICdzdGF0ZScsIG9uID8gJ3RydWUnIDogJ2ZhbHNlJ1xuICBdKTtcbn07XG5cbi8qKlxuICogQ2hlY2sgdGhlIHN0YXRlIG9mIFdpRmkgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgV2lGaSBpcyBlbmFibGVkLlxuICovXG5tZXRob2RzLmlzV2lmaU9uID0gYXN5bmMgZnVuY3Rpb24gaXNXaWZpT24gKCkge1xuICBsZXQgc3Rkb3V0ID0gYXdhaXQgdGhpcy5nZXRTZXR0aW5nKCdnbG9iYWwnLCAnd2lmaV9vbicpO1xuICByZXR1cm4gKHBhcnNlSW50KHN0ZG91dCwgMTApICE9PSAwKTtcbn07XG5cbi8qKlxuICogQ2hlY2sgdGhlIHN0YXRlIG9mIERhdGEgdHJhbnNmZXIgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgRGF0YSB0cmFuc2ZlciBpcyBlbmFibGVkLlxuICovXG5tZXRob2RzLmlzRGF0YU9uID0gYXN5bmMgZnVuY3Rpb24gaXNEYXRhT24gKCkge1xuICBsZXQgc3Rkb3V0ID0gYXdhaXQgdGhpcy5nZXRTZXR0aW5nKCdnbG9iYWwnLCAnbW9iaWxlX2RhdGEnKTtcbiAgcmV0dXJuIChwYXJzZUludChzdGRvdXQsIDEwKSAhPT0gMCk7XG59O1xuXG4vKipcbiAqIENoYW5nZSB0aGUgc3RhdGUgb2YgV2lGaSBhbmQvb3IgRGF0YSB0cmFuc2ZlciBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHBhcmFtIHtib29sZWFufSB3aWZpIC0gVHJ1ZSB0byBlbmFibGUgYW5kIGZhbHNlIHRvIGRpc2FibGUgV2lGaS5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gZGF0YSAtIFRydWUgdG8gZW5hYmxlIGFuZCBmYWxzZSB0byBkaXNhYmxlIERhdGEgdHJhbnNmZXIuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGlzRW11bGF0b3IgW2ZhbHNlXSAtIFNldCBpdCB0byB0cnVlIGlmIHRoZSBkZXZpY2UgdW5kZXIgdGVzdFxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpcyBhbiBlbXVsYXRvciByYXRoZXIgdGhhbiBhIHJlYWwgZGV2aWNlLlxuICovXG5tZXRob2RzLnNldFdpZmlBbmREYXRhID0gYXN5bmMgZnVuY3Rpb24gc2V0V2lmaUFuZERhdGEgKHt3aWZpLCBkYXRhfSwgaXNFbXVsYXRvciA9IGZhbHNlKSB7XG4gIGlmICh1dGlsLmhhc1ZhbHVlKHdpZmkpKSB7XG4gICAgYXdhaXQgdGhpcy5zZXRXaWZpU3RhdGUod2lmaSwgaXNFbXVsYXRvcik7XG4gIH1cbiAgaWYgKHV0aWwuaGFzVmFsdWUoZGF0YSkpIHtcbiAgICBhd2FpdCB0aGlzLnNldERhdGFTdGF0ZShkYXRhLCBpc0VtdWxhdG9yKTtcbiAgfVxufTtcblxuLyoqXG4gKiBDaGVjayB0aGUgc3RhdGUgb2YgYW5pbWF0aW9uIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIGF0IGxlYXN0IG9uZSBvZiBhbmltYXRpb24gc2NhbGUgc2V0dGluZ3NcbiAqICAgICAgICAgICAgICAgICAgIGlzIG5vdCBlcXVhbCB0byAnMC4wJy5cbiAqL1xubWV0aG9kcy5pc0FuaW1hdGlvbk9uID0gYXN5bmMgZnVuY3Rpb24gaXNBbmltYXRpb25PbiAoKSB7XG4gIGxldCBhbmltYXRvcl9kdXJhdGlvbl9zY2FsZSA9IGF3YWl0IHRoaXMuZ2V0U2V0dGluZygnZ2xvYmFsJywgJ2FuaW1hdG9yX2R1cmF0aW9uX3NjYWxlJyk7XG4gIGxldCB0cmFuc2l0aW9uX2FuaW1hdGlvbl9zY2FsZSA9IGF3YWl0IHRoaXMuZ2V0U2V0dGluZygnZ2xvYmFsJywgJ3RyYW5zaXRpb25fYW5pbWF0aW9uX3NjYWxlJyk7XG4gIGxldCB3aW5kb3dfYW5pbWF0aW9uX3NjYWxlID0gYXdhaXQgdGhpcy5nZXRTZXR0aW5nKCdnbG9iYWwnLCAnd2luZG93X2FuaW1hdGlvbl9zY2FsZScpO1xuICByZXR1cm4gXy5zb21lKFthbmltYXRvcl9kdXJhdGlvbl9zY2FsZSwgdHJhbnNpdGlvbl9hbmltYXRpb25fc2NhbGUsIHdpbmRvd19hbmltYXRpb25fc2NhbGVdLFxuICAgICAgICAgICAgICAgIChzZXR0aW5nKSA9PiBzZXR0aW5nICE9PSAnMC4wJyk7XG59O1xuXG4vKipcbiAqIEZvcmNlZnVsbHkgcmVjdXJzaXZlbHkgcmVtb3ZlIGEgcGF0aCBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKiBCZSBjYXJlZnVsIHdoaWxlIGNhbGxpbmcgdGhpcyBtZXRob2QuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHBhdGggLSBUaGUgcGF0aCB0byBiZSByZW1vdmVkIHJlY3Vyc2l2ZWx5LlxuICovXG5tZXRob2RzLnJpbXJhZiA9IGFzeW5jIGZ1bmN0aW9uIHJpbXJhZiAocGF0aCkge1xuICBhd2FpdCB0aGlzLnNoZWxsKFsncm0nLCAnLXJmJywgcGF0aF0pO1xufTtcblxuLyoqXG4gKiBTZW5kIGEgZmlsZSB0byB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGxvY2FsUGF0aCAtIFRoZSBwYXRoIHRvIHRoZSBmaWxlIG9uIHRoZSBsb2NhbCBmaWxlIHN5c3RlbS5cbiAqIEBwYXJhbSB7c3RyaW5nfSByZW1vdGVQYXRoIC0gVGhlIGRlc3RpbmF0aW9uIHBhdGggb24gdGhlIHJlbW90ZSBkZXZpY2UuXG4gKiBAcGFyYW0ge29iamVjdH0gb3B0cyAtIEFkZGl0aW9uYWwgb3B0aW9ucyBtYXBwaW5nLiBTZWVcbiAqICAgICAgICAgICAgICAgICAgICAgICAgaHR0cHM6Ly9naXRodWIuY29tL2FwcGl1bS9ub2RlLXRlZW5fcHJvY2VzcyxcbiAqICAgICAgICAgICAgICAgICAgICAgICAgX2V4ZWNfIG1ldGhvZCBvcHRpb25zLCBmb3IgbW9yZSBpbmZvcm1hdGlvbiBhYm91dCBhdmFpbGFibGVcbiAqICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5cbiAqL1xubWV0aG9kcy5wdXNoID0gYXN5bmMgZnVuY3Rpb24gcHVzaCAobG9jYWxQYXRoLCByZW1vdGVQYXRoLCBvcHRzKSB7XG4gIGF3YWl0IHRoaXMubWtkaXIocGF0aC5wb3NpeC5kaXJuYW1lKHJlbW90ZVBhdGgpKTtcbiAgYXdhaXQgdGhpcy5hZGJFeGVjKFsncHVzaCcsIGxvY2FsUGF0aCwgcmVtb3RlUGF0aF0sIG9wdHMpO1xufTtcblxuLyoqXG4gKiBSZWNlaXZlIGEgZmlsZSBmcm9tIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcmVtb3RlUGF0aCAtIFRoZSBzb3VyY2UgcGF0aCBvbiB0aGUgcmVtb3RlIGRldmljZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBsb2NhbFBhdGggLSBUaGUgZGVzdGluYXRpb24gcGF0aCB0byB0aGUgZmlsZSBvbiB0aGUgbG9jYWwgZmlsZSBzeXN0ZW0uXG4gKi9cbm1ldGhvZHMucHVsbCA9IGFzeW5jIGZ1bmN0aW9uIHB1bGwgKHJlbW90ZVBhdGgsIGxvY2FsUGF0aCkge1xuICAvLyBwdWxsIGZvbGRlciBjYW4gdGFrZSBtb3JlIHRpbWUsIGluY3JlYXNpbmcgdGltZSBvdXQgdG8gNjAgc2Vjc1xuICBhd2FpdCB0aGlzLmFkYkV4ZWMoWydwdWxsJywgcmVtb3RlUGF0aCwgbG9jYWxQYXRoXSwge3RpbWVvdXQ6IDYwMDAwfSk7XG59O1xuXG4vKipcbiAqIENoZWNrIHdoZXRoZXIgdGhlIHByb2Nlc3Mgd2l0aCB0aGUgcGFydGljdWxhciBuYW1lIGlzIHJ1bm5pbmcgb24gdGhlIGRldmljZVxuICogdW5kZXIgdGVzdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvY2Vzc05hbWUgLSBUaGUgbmFtZSBvZiB0aGUgcHJvY2VzcyB0byBiZSBjaGVja2VkLlxuICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgZ2l2ZW4gcHJvY2VzcyBpcyBydW5uaW5nLlxuICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBnaXZlbiBwcm9jZXNzIG5hbWUgaXMgbm90IGEgdmFsaWQgY2xhc3MgbmFtZS5cbiAqL1xubWV0aG9kcy5wcm9jZXNzRXhpc3RzID0gYXN5bmMgZnVuY3Rpb24gcHJvY2Vzc0V4aXN0cyAocHJvY2Vzc05hbWUpIHtcbiAgcmV0dXJuICFfLmlzRW1wdHkoYXdhaXQgdGhpcy5nZXRQSURzQnlOYW1lKHByb2Nlc3NOYW1lKSk7XG59O1xuXG4vKipcbiAqIEdldCBUQ1AgcG9ydCBmb3J3YXJkaW5nIHdpdGggYWRiIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqIEByZXR1cm4ge0FycmF5LjxTdHJpbmc+fSBUaGUgb3V0cHV0IG9mIHRoZSBjb3JyZXNwb25kaW5nIGFkYiBjb21tYW5kLiBBbiBhcnJheSBjb250YWlucyBlYWNoIGZvcndhcmRpbmcgbGluZSBvZiBvdXRwdXRcbiAqL1xubWV0aG9kcy5nZXRGb3J3YXJkTGlzdCA9IGFzeW5jIGZ1bmN0aW9uIGdldEZvcndhcmRMaXN0ICgpIHtcbiAgbG9nLmRlYnVnKGBMaXN0IGZvcndhcmRpbmcgcG9ydHNgKTtcbiAgY29uc3QgY29ubmVjdGlvbnMgPSBhd2FpdCB0aGlzLmFkYkV4ZWMoWydmb3J3YXJkJywgJy0tbGlzdCddKTtcbiAgcmV0dXJuIGNvbm5lY3Rpb25zLnNwbGl0KEVPTCkuZmlsdGVyKChsaW5lKSA9PiBCb29sZWFuKGxpbmUudHJpbSgpKSk7XG59O1xuXG4vKipcbiAqIFNldHVwIFRDUCBwb3J0IGZvcndhcmRpbmcgd2l0aCBhZGIgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gc3lzdGVtUG9ydCAtIFRoZSBudW1iZXIgb2YgdGhlIGxvY2FsIHN5c3RlbSBwb3J0LlxuICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBkZXZpY2VQb3J0IC0gVGhlIG51bWJlciBvZiB0aGUgcmVtb3RlIGRldmljZSBwb3J0LlxuICovXG5tZXRob2RzLmZvcndhcmRQb3J0ID0gYXN5bmMgZnVuY3Rpb24gZm9yd2FyZFBvcnQgKHN5c3RlbVBvcnQsIGRldmljZVBvcnQpIHtcbiAgbG9nLmRlYnVnKGBGb3J3YXJkaW5nIHN5c3RlbTogJHtzeXN0ZW1Qb3J0fSB0byBkZXZpY2U6ICR7ZGV2aWNlUG9ydH1gKTtcbiAgYXdhaXQgdGhpcy5hZGJFeGVjKFsnZm9yd2FyZCcsIGB0Y3A6JHtzeXN0ZW1Qb3J0fWAsIGB0Y3A6JHtkZXZpY2VQb3J0fWBdKTtcbn07XG5cbi8qKlxuICogUmVtb3ZlIFRDUCBwb3J0IGZvcndhcmRpbmcgd2l0aCBhZGIgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LiBUaGUgZm9yd2FyZGluZ1xuICogZm9yIHRoZSBnaXZlbiBwb3J0IHNob3VsZCBiZSBzZXR1cCB3aXRoIHtAbGluayAjZm9yd2FyZFBvcnR9IGZpcnN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gc3lzdGVtUG9ydCAtIFRoZSBudW1iZXIgb2YgdGhlIGxvY2FsIHN5c3RlbSBwb3J0XG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0byByZW1vdmUgZm9yd2FyZGluZyBvbi5cbiAqL1xubWV0aG9kcy5yZW1vdmVQb3J0Rm9yd2FyZCA9IGFzeW5jIGZ1bmN0aW9uIHJlbW92ZVBvcnRGb3J3YXJkIChzeXN0ZW1Qb3J0KSB7XG4gIGxvZy5kZWJ1ZyhgUmVtb3ZpbmcgZm9yd2FyZGVkIHBvcnQgc29ja2V0IGNvbm5lY3Rpb246ICR7c3lzdGVtUG9ydH0gYCk7XG4gIGF3YWl0IHRoaXMuYWRiRXhlYyhbJ2ZvcndhcmQnLCBgLS1yZW1vdmVgLCBgdGNwOiR7c3lzdGVtUG9ydH1gXSk7XG59O1xuXG4vKipcbiAqIEdldCBUQ1AgcG9ydCBmb3J3YXJkaW5nIHdpdGggYWRiIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqIEByZXR1cm4ge0FycmF5LjxTdHJpbmc+fSBUaGUgb3V0cHV0IG9mIHRoZSBjb3JyZXNwb25kaW5nIGFkYiBjb21tYW5kLiBBbiBhcnJheSBjb250YWlucyBlYWNoIGZvcndhcmRpbmcgbGluZSBvZiBvdXRwdXRcbiAqL1xubWV0aG9kcy5nZXRSZXZlcnNlTGlzdCA9IGFzeW5jIGZ1bmN0aW9uIGdldFJldmVyc2VMaXN0ICgpIHtcbiAgbG9nLmRlYnVnKGBMaXN0IHJldmVyc2UgZm9yd2FyZGluZyBwb3J0c2ApO1xuICBjb25zdCBjb25uZWN0aW9ucyA9IGF3YWl0IHRoaXMuYWRiRXhlYyhbJ3JldmVyc2UnLCAnLS1saXN0J10pO1xuICByZXR1cm4gY29ubmVjdGlvbnMuc3BsaXQoRU9MKS5maWx0ZXIoKGxpbmUpID0+IEJvb2xlYW4obGluZS50cmltKCkpKTtcbn07XG5cbi8qKlxuICogU2V0dXAgVENQIHBvcnQgZm9yd2FyZGluZyB3aXRoIGFkYiBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKiBPbmx5IGF2YWlsYWJsZSBmb3IgQVBJIDIxKy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGRldmljZVBvcnQgLSBUaGUgbnVtYmVyIG9mIHRoZSByZW1vdGUgZGV2aWNlIHBvcnQuXG4gKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IHN5c3RlbVBvcnQgLSBUaGUgbnVtYmVyIG9mIHRoZSBsb2NhbCBzeXN0ZW0gcG9ydC5cbiAqL1xubWV0aG9kcy5yZXZlcnNlUG9ydCA9IGFzeW5jIGZ1bmN0aW9uIHJldmVyc2VQb3J0IChkZXZpY2VQb3J0LCBzeXN0ZW1Qb3J0KSB7XG4gIGxvZy5kZWJ1ZyhgRm9yd2FyZGluZyBkZXZpY2U6ICR7ZGV2aWNlUG9ydH0gdG8gc3lzdGVtOiAke3N5c3RlbVBvcnR9YCk7XG4gIGF3YWl0IHRoaXMuYWRiRXhlYyhbJ3JldmVyc2UnLCBgdGNwOiR7ZGV2aWNlUG9ydH1gLCBgdGNwOiR7c3lzdGVtUG9ydH1gXSk7XG59O1xuXG4vKipcbiAqIFJlbW92ZSBUQ1AgcG9ydCBmb3J3YXJkaW5nIHdpdGggYWRiIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC4gVGhlIGZvcndhcmRpbmdcbiAqIGZvciB0aGUgZ2l2ZW4gcG9ydCBzaG91bGQgYmUgc2V0dXAgd2l0aCB7QGxpbmsgI2ZvcndhcmRQb3J0fSBmaXJzdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGRldmljZVBvcnQgLSBUaGUgbnVtYmVyIG9mIHRoZSByZW1vdGUgZGV2aWNlIHBvcnRcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvIHJlbW92ZSBmb3J3YXJkaW5nIG9uLlxuICovXG5tZXRob2RzLnJlbW92ZVBvcnRSZXZlcnNlID0gYXN5bmMgZnVuY3Rpb24gcmVtb3ZlUG9ydFJldmVyc2UgKGRldmljZVBvcnQpIHtcbiAgbG9nLmRlYnVnKGBSZW1vdmluZyByZXZlcnNlIGZvcndhcmRlZCBwb3J0IHNvY2tldCBjb25uZWN0aW9uOiAke2RldmljZVBvcnR9IGApO1xuICBhd2FpdCB0aGlzLmFkYkV4ZWMoWydyZXZlcnNlJywgYC0tcmVtb3ZlYCwgYHRjcDoke2RldmljZVBvcnR9YF0pO1xufTtcblxuLyoqXG4gKiBTZXR1cCBUQ1AgcG9ydCBmb3J3YXJkaW5nIHdpdGggYWRiIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC4gVGhlIGRpZmZlcmVuY2VcbiAqIGJldHdlZW4ge0BsaW5rICNmb3J3YXJkUG9ydH0gaXMgdGhhdCB0aGlzIG1ldGhvZCBkb2VzIHNldHVwIGZvciBhbiBhYnN0cmFjdFxuICogbG9jYWwgcG9ydC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IHN5c3RlbVBvcnQgLSBUaGUgbnVtYmVyIG9mIHRoZSBsb2NhbCBzeXN0ZW0gcG9ydC5cbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gZGV2aWNlUG9ydCAtIFRoZSBudW1iZXIgb2YgdGhlIHJlbW90ZSBkZXZpY2UgcG9ydC5cbiAqL1xubWV0aG9kcy5mb3J3YXJkQWJzdHJhY3RQb3J0ID0gYXN5bmMgZnVuY3Rpb24gZm9yd2FyZEFic3RyYWN0UG9ydCAoc3lzdGVtUG9ydCwgZGV2aWNlUG9ydCkge1xuICBsb2cuZGVidWcoYEZvcndhcmRpbmcgc3lzdGVtOiAke3N5c3RlbVBvcnR9IHRvIGFic3RyYWN0IGRldmljZTogJHtkZXZpY2VQb3J0fWApO1xuICBhd2FpdCB0aGlzLmFkYkV4ZWMoWydmb3J3YXJkJywgYHRjcDoke3N5c3RlbVBvcnR9YCwgYGxvY2FsYWJzdHJhY3Q6JHtkZXZpY2VQb3J0fWBdKTtcbn07XG5cbi8qKlxuICogRXhlY3V0ZSBwaW5nIHNoZWxsIGNvbW1hbmQgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgdGhlIGNvbW1hbmQgb3V0cHV0IGNvbnRhaW5zICdwaW5nJyBzdWJzdHJpbmcuXG4gKiBAdGhyb3dzIHtlcnJvcn0gSWYgdGhlcmUgd2FzIGFuIGVycm9yIHdoaWxlIGV4ZWN1dGluZyAncGluZycgY29tbWFuZCBvbiB0aGVcbiAqICAgICAgICAgICAgICAgICBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqL1xubWV0aG9kcy5waW5nID0gYXN5bmMgZnVuY3Rpb24gcGluZyAoKSB7XG4gIGxldCBzdGRvdXQgPSBhd2FpdCB0aGlzLnNoZWxsKFsnZWNobycsICdwaW5nJ10pO1xuICBpZiAoc3Rkb3V0LmluZGV4T2YoJ3BpbmcnKSA9PT0gMCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHRocm93IG5ldyBFcnJvcihgQURCIHBpbmcgZmFpbGVkLCByZXR1cm5lZCAke3N0ZG91dH1gKTtcbn07XG5cbi8qKlxuICogUmVzdGFydCB0aGUgZGV2aWNlIHVuZGVyIHRlc3QgdXNpbmcgYWRiIGNvbW1hbmRzLlxuICpcbiAqIEB0aHJvd3Mge2Vycm9yfSBJZiBzdGFydCBmYWlscy5cbiAqL1xubWV0aG9kcy5yZXN0YXJ0ID0gYXN5bmMgZnVuY3Rpb24gcmVzdGFydCAoKSB7XG4gIHRyeSB7XG4gICAgYXdhaXQgdGhpcy5zdG9wTG9nY2F0KCk7XG4gICAgYXdhaXQgdGhpcy5yZXN0YXJ0QWRiKCk7XG4gICAgYXdhaXQgdGhpcy53YWl0Rm9yRGV2aWNlKDYwKTtcbiAgICBhd2FpdCB0aGlzLnN0YXJ0TG9nY2F0KCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFJlc3RhcnQgZmFpbGVkLiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gIH1cbn07XG5cbi8qKlxuICogU3RhcnQgdGhlIGxvZ2NhdCBwcm9jZXNzIHRvIGdhdGhlciBsb2dzLlxuICpcbiAqIEB0aHJvd3Mge2Vycm9yfSBJZiByZXN0YXJ0IGZhaWxzLlxuICovXG5tZXRob2RzLnN0YXJ0TG9nY2F0ID0gYXN5bmMgZnVuY3Rpb24gc3RhcnRMb2djYXQgKCkge1xuICBpZiAoIV8uaXNFbXB0eSh0aGlzLmxvZ2NhdCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJUcnlpbmcgdG8gc3RhcnQgbG9nY2F0IGNhcHR1cmUgYnV0IGl0J3MgYWxyZWFkeSBzdGFydGVkIVwiKTtcbiAgfVxuICB0aGlzLmxvZ2NhdCA9IG5ldyBMb2djYXQoe1xuICAgIGFkYjogdGhpcy5leGVjdXRhYmxlLFxuICAgIGRlYnVnOiBmYWxzZSxcbiAgICBkZWJ1Z1RyYWNlOiBmYWxzZSxcbiAgICBjbGVhckRldmljZUxvZ3NPblN0YXJ0OiAhIXRoaXMuY2xlYXJEZXZpY2VMb2dzT25TdGFydCxcbiAgfSk7XG4gIGF3YWl0IHRoaXMubG9nY2F0LnN0YXJ0Q2FwdHVyZSgpO1xufTtcblxuLyoqXG4gKiBTdG9wIHRoZSBhY3RpdmUgbG9nY2F0IHByb2Nlc3Mgd2hpY2ggZ2F0aGVycyBsb2dzLlxuICogVGhlIGNhbGwgd2lsbCBiZSBpZ25vcmVkIGlmIG5vIGxvZ2NhdCBwcm9jZXNzIGlzIHJ1bm5pbmcuXG4gKi9cbm1ldGhvZHMuc3RvcExvZ2NhdCA9IGFzeW5jIGZ1bmN0aW9uIHN0b3BMb2djYXQgKCkge1xuICBpZiAoXy5pc0VtcHR5KHRoaXMubG9nY2F0KSkge1xuICAgIHJldHVybjtcbiAgfVxuICB0cnkge1xuICAgIGF3YWl0IHRoaXMubG9nY2F0LnN0b3BDYXB0dXJlKCk7XG4gIH0gZmluYWxseSB7XG4gICAgdGhpcy5sb2djYXQgPSBudWxsO1xuICB9XG59O1xuXG4vKipcbiAqIFJldHJpZXZlIHRoZSBvdXRwdXQgZnJvbSB0aGUgY3VycmVudGx5IHJ1bm5pbmcgbG9nY2F0IHByb2Nlc3MuXG4gKiBUaGUgbG9nY2F0IHByb2Nlc3Mgc2hvdWxkIGJlIGV4ZWN1dGVkIGJ5IHsybGluayAjc3RhcnRMb2djYXR9IG1ldGhvZC5cbiAqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBjb2xsZWN0ZWQgbG9nY2F0IG91dHB1dC5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiBsb2djYXQgcHJvY2VzcyBpcyBub3QgcnVubmluZy5cbiAqL1xubWV0aG9kcy5nZXRMb2djYXRMb2dzID0gZnVuY3Rpb24gZ2V0TG9nY2F0TG9ncyAoKSB7XG4gIGlmIChfLmlzRW1wdHkodGhpcy5sb2djYXQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuJ3QgZ2V0IGxvZ2NhdCBsb2dzIHNpbmNlIGxvZ2NhdCBoYXNuJ3Qgc3RhcnRlZFwiKTtcbiAgfVxuICByZXR1cm4gdGhpcy5sb2djYXQuZ2V0TG9ncygpO1xufTtcblxuLyoqXG4gKiBTZXQgdGhlIGNhbGxiYWNrIGZvciB0aGUgbG9nY2F0IG91dHB1dCBldmVudC5cbiAqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciAtIFRoZSBsaXN0ZW5lciBmdW5jdGlvbiwgd2hpY2ggYWNjZXB0cyBvbmUgYXJndW1lbnQuIFRoZSBhcmd1bWVudCBpc1xuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhIGxvZyByZWNvcmQgb2JqZWN0IHdpdGggYHRpbWVzdGFtcGAsIGBsZXZlbGAgYW5kIGBtZXNzYWdlYCBwcm9wZXJ0aWVzLlxuICogQHRocm93cyB7RXJyb3J9IElmIGxvZ2NhdCBwcm9jZXNzIGlzIG5vdCBydW5uaW5nLlxuICovXG5tZXRob2RzLnNldExvZ2NhdExpc3RlbmVyID0gZnVuY3Rpb24gc2V0TG9nY2F0TGlzdGVuZXIgKGxpc3RlbmVyKSB7XG4gIGlmIChfLmlzRW1wdHkodGhpcy5sb2djYXQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiTG9nY2F0IHByb2Nlc3MgaGFzbid0IGJlZW4gc3RhcnRlZFwiKTtcbiAgfVxuICB0aGlzLmxvZ2NhdC5vbignb3V0cHV0JywgbGlzdGVuZXIpO1xufTtcblxuLyoqXG4gKiBSZW1vdmVzIHRoZSBwcmV2aW91c2x5IHNldCBjYWxsYmFjayBmb3IgdGhlIGxvZ2NhdCBvdXRwdXQgZXZlbnQuXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgLSBUaGUgbGlzdGVuZXIgZnVuY3Rpb24sIHdoaWNoIGhhcyBiZWVuIHByZXZpb3VzbHlcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzc2VkIHRvIGBzZXRMb2djYXRMaXN0ZW5lcmBcbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiBsb2djYXQgcHJvY2VzcyBpcyBub3QgcnVubmluZy5cbiAqL1xubWV0aG9kcy5yZW1vdmVMb2djYXRMaXN0ZW5lciA9IGZ1bmN0aW9uIHJlbW92ZUxvZ2NhdExpc3RlbmVyIChsaXN0ZW5lcikge1xuICBpZiAoXy5pc0VtcHR5KHRoaXMubG9nY2F0KSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkxvZ2NhdCBwcm9jZXNzIGhhc24ndCBiZWVuIHN0YXJ0ZWRcIik7XG4gIH1cbiAgdGhpcy5sb2djYXQucmVtb3ZlTGlzdGVuZXIoJ291dHB1dCcsIGxpc3RlbmVyKTtcbn07XG5cbi8qKlxuICogUmV0dXJucyBwcm9jZXNzIG5hbWUgZm9yIHRoZSBnaXZlbiBwcm9jZXNzIGlkZW50aWZpZXJcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IHBpZCAtIFRoZSB2YWxpZCBwcm9jZXNzIGlkZW50aWZpZXJcbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgZ2l2ZW4gUElEIGlzIGVpdGhlciBpbnZhbGlkIG9yIGlzIG5vdCBwcmVzZW50XG4gKiBpbiB0aGUgYWN0aXZlIHByb2Nlc3NlcyBsaXN0XG4gKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgcHJvY2VzcyBuYW1lXG4gKi9cbm1ldGhvZHMuZ2V0TmFtZUJ5UGlkID0gYXN5bmMgZnVuY3Rpb24gZ2V0TmFtZUJ5UGlkIChwaWQpIHtcbiAgaWYgKGlzTmFOKHBpZCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZSBQSUQgdmFsdWUgbXVzdCBiZSBhIHZhbGlkIG51bWJlci4gJyR7cGlkfScgaXMgZ2l2ZW4gaW5zdGVhZGApO1xuICB9XG4gIHBpZCA9IHBhcnNlSW50KHBpZCwgMTApO1xuXG4gIGNvbnN0IHN0ZG91dCA9IGF3YWl0IHRoaXMuc2hlbGwoWydwcyddKTtcbiAgY29uc3QgdGl0bGVNYXRjaCA9IFBTX1RJVExFX1BBVFRFUk4uZXhlYyhzdGRvdXQpO1xuICBpZiAoIXRpdGxlTWF0Y2gpIHtcbiAgICBsb2cuZGVidWcoc3Rkb3V0KTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBnZXQgdGhlIHByb2Nlc3MgbmFtZSBmb3IgUElEICcke3BpZH0nYCk7XG4gIH1cbiAgY29uc3QgYWxsVGl0bGVzID0gdGl0bGVNYXRjaFsxXS50cmltKCkuc3BsaXQoL1xccysvKTtcbiAgY29uc3QgcGlkSW5kZXggPSBhbGxUaXRsZXMuaW5kZXhPZihQSURfQ09MVU1OX1RJVExFKTtcbiAgLy8gaXQgbWlnaHQgbm90IGJlIHN0YWJsZSB0byB0YWtlIE5BTUUgYnkgaW5kZXgsIGJlY2F1c2UgZGVwZW5kaW5nIG9uIHRoZVxuICAvLyBhY3R1YWwgU0RLIHRoZSBwcyBvdXRwdXQgbWlnaHQgbm90IGNvbnRhaW4gYW4gYWJicmV2aWF0aW9uIGZvciB0aGUgUyBmbGFnOlxuICAvLyBVU0VSICAgICBQSUQgICBQUElEICBWU0laRSAgUlNTICAgICBXQ0hBTiAgICBQQyAgICAgICAgTkFNRVxuICAvLyBVU0VSICAgICBQSUQgICBQUElEICBWU0laRSAgUlNTICAgICBXQ0hBTiAgICBQQyAgIFMgICAgTkFNRVxuICBjb25zdCBuYW1lT2Zmc2V0ID0gYWxsVGl0bGVzLmluZGV4T2YoUFJPQ0VTU19OQU1FX0NPTFVNTl9USVRMRSkgLSBhbGxUaXRsZXMubGVuZ3RoO1xuICBjb25zdCBwaWRSZWdleCA9IG5ldyBSZWdFeHAoYF4oLipcXFxcYiR7cGlkfVxcXFxiLiopJGAsICdnbScpO1xuICBsZXQgbWF0Y2hlZExpbmU7XG4gIHdoaWxlICgobWF0Y2hlZExpbmUgPSBwaWRSZWdleC5leGVjKHN0ZG91dCkpKSB7XG4gICAgY29uc3QgaXRlbXMgPSBtYXRjaGVkTGluZVsxXS50cmltKCkuc3BsaXQoL1xccysvKTtcbiAgICBpZiAocGFyc2VJbnQoaXRlbXNbcGlkSW5kZXhdLCAxMCkgPT09IHBpZCAmJiBpdGVtc1tpdGVtcy5sZW5ndGggKyBuYW1lT2Zmc2V0XSkge1xuICAgICAgcmV0dXJuIGl0ZW1zW2l0ZW1zLmxlbmd0aCArIG5hbWVPZmZzZXRdO1xuICAgIH1cbiAgfVxuICBsb2cuZGVidWcoc3Rkb3V0KTtcbiAgdGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgZ2V0IHRoZSBwcm9jZXNzIG5hbWUgZm9yIFBJRCAnJHtwaWR9J2ApO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIGxpc3Qgb2YgcHJvY2VzcyBpZHMgZm9yIHRoZSBwYXJ0aWN1bGFyIHByb2Nlc3Mgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gVGhlIHBhcnQgb2YgcHJvY2VzcyBuYW1lLlxuICogQHJldHVybiB7QXJyYXkuPG51bWJlcj59IFRoZSBsaXN0IG9mIG1hdGNoZWQgcHJvY2VzcyBJRHMgb3IgYW4gZW1wdHkgbGlzdC5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGFzc2VkIHByb2Nlc3MgbmFtZSBpcyBub3QgYSB2YWxpZCBvbmVcbiAqL1xubWV0aG9kcy5nZXRQSURzQnlOYW1lID0gYXN5bmMgZnVuY3Rpb24gZ2V0UElEc0J5TmFtZSAobmFtZSkge1xuICBsb2cuZGVidWcoYEdldHRpbmcgSURzIG9mIGFsbCAnJHtuYW1lfScgcHJvY2Vzc2VzYCk7XG4gIGlmICghdGhpcy5pc1ZhbGlkQ2xhc3MobmFtZSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgcHJvY2VzcyBuYW1lOiAnJHtuYW1lfSdgKTtcbiAgfVxuICAvLyBodHRwczovL2dpdGh1Yi5jb20vYXBwaXVtL2FwcGl1bS9pc3N1ZXMvMTM1NjdcbiAgaWYgKGF3YWl0IHRoaXMuZ2V0QXBpTGV2ZWwoKSA+PSAyMykge1xuICAgIGlmICghXy5pc0Jvb2xlYW4odGhpcy5faXNQZ3JlcEF2YWlsYWJsZSkpIHtcbiAgICAgIC8vIHBncmVwIGlzIGluIHByaW9yaXR5LCBzaW5jZSBwaWRvZiBoYXMgYmVlbiByZXBvcnRlZCBvZiBoYXZpbmcgYnVncyBvbiBzb21lIHBsYXRmb3Jtc1xuICAgICAgY29uc3QgcGdyZXBPdXRwdXQgPSBfLnRyaW0oYXdhaXQgdGhpcy5zaGVsbChbJ3BncmVwIC0taGVscDsgZWNobyAkPyddKSk7XG4gICAgICB0aGlzLl9pc1BncmVwQXZhaWxhYmxlID0gcGFyc2VJbnQoXy5sYXN0KHBncmVwT3V0cHV0LnNwbGl0KC9cXHMrLykpLCAxMCkgPT09IDA7XG4gICAgICBpZiAodGhpcy5faXNQZ3JlcEF2YWlsYWJsZSkge1xuICAgICAgICB0aGlzLl9jYW5QZ3JlcFVzZUZ1bGxDbWRMaW5lU2VhcmNoID0gL14tZlxcYi9tLnRlc3QocGdyZXBPdXRwdXQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5faXNQaWRvZkF2YWlsYWJsZSA9IHBhcnNlSW50KGF3YWl0IHRoaXMuc2hlbGwoWydwaWRvZiAtLWhlbHAgPiAvZGV2L251bGw7IGVjaG8gJD8nXSksIDEwKSA9PT0gMDtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHRoaXMuX2lzUGdyZXBBdmFpbGFibGUgfHwgdGhpcy5faXNQaWRvZkF2YWlsYWJsZSkge1xuICAgICAgY29uc3Qgc2hlbGxDb21tYW5kID0gdGhpcy5faXNQZ3JlcEF2YWlsYWJsZVxuICAgICAgICA/ICh0aGlzLl9jYW5QZ3JlcFVzZUZ1bGxDbWRMaW5lU2VhcmNoXG4gICAgICAgICAgPyBbJ3BncmVwJywgJy1mJywgXy5lc2NhcGVSZWdFeHAobmFtZSldXG4gICAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2FwcGl1bS9hcHBpdW0vaXNzdWVzLzEzODcyXG4gICAgICAgICAgOiBbYHBncmVwIF4ke18uZXNjYXBlUmVnRXhwKG5hbWUuc2xpY2UoLU1BWF9QR1JFUF9QQVRURVJOX0xFTikpfSQgfHwgcGdyZXAgXiR7Xy5lc2NhcGVSZWdFeHAobmFtZS5zbGljZSgwLCBNQVhfUEdSRVBfUEFUVEVSTl9MRU4pKX0kYF0pXG4gICAgICAgIDogWydwaWRvZicsIG5hbWVdO1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIChhd2FpdCB0aGlzLnNoZWxsKHNoZWxsQ29tbWFuZCkpXG4gICAgICAgICAgLnNwbGl0KC9cXHMrLylcbiAgICAgICAgICAubWFwKCh4KSA9PiBwYXJzZUludCh4LCAxMCkpXG4gICAgICAgICAgLmZpbHRlcigoeCkgPT4gXy5pc0ludGVnZXIoeCkpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAvLyBlcnJvciBjb2RlIDEgaXMgcmV0dXJuZWQgaWYgdGhlIHV0aWxpdHkgZGlkIG5vdCBmaW5kIGFueSBwcm9jZXNzZXNcbiAgICAgICAgLy8gd2l0aCB0aGUgZ2l2ZW4gbmFtZVxuICAgICAgICBpZiAoZS5jb2RlID09PSAxKSB7XG4gICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IGV4dHJhY3QgcHJvY2VzcyBJRCBvZiAnJHtuYW1lfSc6ICR7ZS5tZXNzYWdlfWApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGxvZy5kZWJ1ZygnVXNpbmcgcHMtYmFzZWQgUElEIGRldGVjdGlvbicpO1xuICBjb25zdCBzdGRvdXQgPSBhd2FpdCB0aGlzLnNoZWxsKFsncHMnXSk7XG4gIGNvbnN0IHRpdGxlTWF0Y2ggPSBQU19USVRMRV9QQVRURVJOLmV4ZWMoc3Rkb3V0KTtcbiAgaWYgKCF0aXRsZU1hdGNoKSB7XG4gICAgbG9nLmRlYnVnKHN0ZG91dCk7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgZXh0cmFjdCBQSUQgb2YgJyR7bmFtZX0nIGZyb20gcHMgb3V0cHV0YCk7XG4gIH1cbiAgY29uc3QgYWxsVGl0bGVzID0gdGl0bGVNYXRjaFsxXS50cmltKCkuc3BsaXQoL1xccysvKTtcbiAgY29uc3QgcGlkSW5kZXggPSBhbGxUaXRsZXMuaW5kZXhPZihQSURfQ09MVU1OX1RJVExFKTtcbiAgY29uc3QgcGlkcyA9IFtdO1xuICBjb25zdCBwcm9jZXNzTmFtZVJlZ2V4ID0gbmV3IFJlZ0V4cChgXiguKlxcXFxiXFxcXGQrXFxcXGIuKlxcXFxiJHtfLmVzY2FwZVJlZ0V4cChuYW1lKX1cXFxcYi4qKSRgLCAnZ20nKTtcbiAgbGV0IG1hdGNoZWRMaW5lO1xuICB3aGlsZSAoKG1hdGNoZWRMaW5lID0gcHJvY2Vzc05hbWVSZWdleC5leGVjKHN0ZG91dCkpKSB7XG4gICAgY29uc3QgaXRlbXMgPSBtYXRjaGVkTGluZVsxXS50cmltKCkuc3BsaXQoL1xccysvKTtcbiAgICBpZiAocGlkSW5kZXggPj0gYWxsVGl0bGVzLmxlbmd0aCB8fCBpc05hTihpdGVtc1twaWRJbmRleF0pKSB7XG4gICAgICBsb2cuZGVidWcoc3Rkb3V0KTtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IGV4dHJhY3QgUElEIG9mICcke25hbWV9JyBmcm9tICcke21hdGNoZWRMaW5lWzFdLnRyaW0oKX0nYCk7XG4gICAgfVxuICAgIHBpZHMucHVzaChwYXJzZUludChpdGVtc1twaWRJbmRleF0sIDEwKSk7XG4gIH1cbiAgcmV0dXJuIHBpZHM7XG59O1xuXG4vKipcbiAqIEdldCB0aGUgbGlzdCBvZiBwcm9jZXNzIGlkcyBmb3IgdGhlIHBhcnRpY3VsYXIgcHJvY2VzcyBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBUaGUgcGFydCBvZiBwcm9jZXNzIG5hbWUuXG4gKiBAcmV0dXJuIHtBcnJheS48bnVtYmVyPn0gVGhlIGxpc3Qgb2YgbWF0Y2hlZCBwcm9jZXNzIElEcyBvciBhbiBlbXB0eSBsaXN0LlxuICovXG5tZXRob2RzLmtpbGxQcm9jZXNzZXNCeU5hbWUgPSBhc3luYyBmdW5jdGlvbiBraWxsUHJvY2Vzc2VzQnlOYW1lIChuYW1lKSB7XG4gIHRyeSB7XG4gICAgbG9nLmRlYnVnKGBBdHRlbXB0aW5nIHRvIGtpbGwgYWxsICR7bmFtZX0gcHJvY2Vzc2VzYCk7XG4gICAgbGV0IHBpZHMgPSBhd2FpdCB0aGlzLmdldFBJRHNCeU5hbWUobmFtZSk7XG4gICAgaWYgKF8uaXNFbXB0eShwaWRzKSkge1xuICAgICAgbG9nLmluZm8oYE5vICcke25hbWV9JyBwcm9jZXNzIGhhcyBiZWVuIGZvdW5kYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGZvciAobGV0IHBpZCBvZiBwaWRzKSB7XG4gICAgICBhd2FpdCB0aGlzLmtpbGxQcm9jZXNzQnlQSUQocGlkKTtcbiAgICB9XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBraWxsICR7bmFtZX0gcHJvY2Vzc2VzLiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gIH1cbn07XG5cbi8qKlxuICogS2lsbCB0aGUgcGFydGljdWxhciBwcm9jZXNzIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqIFRoZSBjdXJyZW50IHVzZXIgaXMgYXV0b21hdGljYWxseSBzd2l0Y2hlZCB0byByb290IGlmIG5lY2Vzc2FyeSBpbiBvcmRlclxuICogdG8gcHJvcGVybHkga2lsbCB0aGUgcHJvY2Vzcy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IHBpZCAtIFRoZSBJRCBvZiB0aGUgcHJvY2VzcyB0byBiZSBraWxsZWQuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IEtpbGwgY29tbWFuZCdzIHN0ZG91dCBvciBzdGRlcnIgaWYgdGhlcmUgd2FzIG5vIHN1Y2ggcHJvY2Vzcy5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcHJvY2VzcyBjYW5ub3QgYmUga2lsbGVkLlxuICovXG5tZXRob2RzLmtpbGxQcm9jZXNzQnlQSUQgPSBhc3luYyBmdW5jdGlvbiBraWxsUHJvY2Vzc0J5UElEIChwaWQpIHtcbiAgbG9nLmRlYnVnKGBBdHRlbXB0aW5nIHRvIGtpbGwgcHJvY2VzcyAke3BpZH1gKTtcbiAgbGV0IHdhc1Jvb3QgPSBmYWxzZTtcbiAgbGV0IGJlY2FtZVJvb3QgPSBmYWxzZTtcbiAgdHJ5IHtcbiAgICB0cnkge1xuICAgICAgLy8gQ2hlY2sgaWYgdGhlIHByb2Nlc3MgZXhpc3RzIGFuZCB0aHJvdyBhbiBleGNlcHRpb24gb3RoZXJ3aXNlXG4gICAgICBhd2FpdCB0aGlzLnNoZWxsKFsna2lsbCcsICctMCcsIHBpZF0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChfLmluY2x1ZGVzKGUuc3RkZXJyLCAnTm8gc3VjaCBwcm9jZXNzJykpIHtcbiAgICAgICAgcmV0dXJuIGUuc3RkZXJyO1xuICAgICAgfVxuICAgICAgaWYgKCFfLmluY2x1ZGVzKGUuc3RkZXJyLCAnT3BlcmF0aW9uIG5vdCBwZXJtaXR0ZWQnKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgICAgdHJ5IHtcbiAgICAgICAgd2FzUm9vdCA9IGF3YWl0IHRoaXMuaXNSb290KCk7XG4gICAgICB9IGNhdGNoIChpZ24pIHt9XG4gICAgICBpZiAod2FzUm9vdCkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgICAgbG9nLmluZm8oYENhbm5vdCBraWxsIFBJRCAke3BpZH0gZHVlIHRvIGluc3VmZmljaWVudCBwZXJtaXNzaW9ucy4gUmV0cnlpbmcgYXMgcm9vdGApO1xuICAgICAgKHtpc1N1Y2Nlc3NmdWw6IGJlY2FtZVJvb3R9ID0gYXdhaXQgdGhpcy5yb290KCkpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGhpcy5zaGVsbChbJ2tpbGwnLCAnLTAnLCBwaWRdKTtcbiAgICAgIH0gY2F0Y2ggKGUxKSB7XG4gICAgICAgIGlmIChfLmluY2x1ZGVzKGUxLnN0ZGVyciwgJ05vIHN1Y2ggcHJvY2VzcycpKSB7XG4gICAgICAgICAgcmV0dXJuIGUxLnN0ZGVycjtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlMTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgdGltZW91dE1zID0gMTAwMDtcbiAgICBsZXQgc3Rkb3V0O1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB3YWl0Rm9yQ29uZGl0aW9uKGFzeW5jICgpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBzdGRvdXQgPSBhd2FpdCB0aGlzLnNoZWxsKFsna2lsbCcsIHBpZF0pO1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIC8vIGtpbGwgcmV0dXJucyBub24temVybyBjb2RlIGlmIHRoZSBwcm9jZXNzIGlzIGFscmVhZHkga2lsbGVkXG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgIH0sIHt3YWl0TXM6IHRpbWVvdXRNcywgaW50ZXJ2YWxNczogMzAwfSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBsb2cud2FybihgQ2Fubm90IGtpbGwgcHJvY2VzcyAke3BpZH0gaW4gJHt0aW1lb3V0TXN9IG1zLiBUcnlpbmcgdG8gZm9yY2Uga2lsbC4uLmApO1xuICAgICAgc3Rkb3V0ID0gYXdhaXQgdGhpcy5zaGVsbChbJ2tpbGwnLCAnLTknLCBwaWRdKTtcbiAgICB9XG4gICAgcmV0dXJuIHN0ZG91dDtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAoYmVjYW1lUm9vdCkge1xuICAgICAgYXdhaXQgdGhpcy51bnJvb3QoKTtcbiAgICB9XG4gIH1cbn07XG5cbi8qKlxuICogQnJvYWRjYXN0IHByb2Nlc3Mga2lsbGluZyBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGludGVudCAtIFRoZSBuYW1lIG9mIHRoZSBpbnRlbnQgdG8gYnJvYWRjYXN0IHRvLlxuICogQHBhcmFtIHtzdHJpbmd9IHByb2Nlc3NOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGtpbGxlZCBwcm9jZXNzLlxuICogQHRocm93cyB7ZXJyb3J9IElmIHRoZSBwcm9jZXNzIHdhcyBub3Qga2lsbGVkLlxuICovXG5tZXRob2RzLmJyb2FkY2FzdFByb2Nlc3NFbmQgPSBhc3luYyBmdW5jdGlvbiBicm9hZGNhc3RQcm9jZXNzRW5kIChpbnRlbnQsIHByb2Nlc3NOYW1lKSB7XG4gIC8vIHN0YXJ0IHRoZSBicm9hZGNhc3Qgd2l0aG91dCB3YWl0aW5nIGZvciBpdCB0byBmaW5pc2guXG4gIHRoaXMuYnJvYWRjYXN0KGludGVudCk7XG4gIC8vIHdhaXQgZm9yIHRoZSBwcm9jZXNzIHRvIGVuZFxuICBsZXQgc3RhcnQgPSBEYXRlLm5vdygpO1xuICBsZXQgdGltZW91dE1zID0gNDAwMDA7XG4gIHRyeSB7XG4gICAgd2hpbGUgKChEYXRlLm5vdygpIC0gc3RhcnQpIDwgdGltZW91dE1zKSB7XG4gICAgICBpZiAoYXdhaXQgdGhpcy5wcm9jZXNzRXhpc3RzKHByb2Nlc3NOYW1lKSkge1xuICAgICAgICAvLyBjb29sIGRvd25cbiAgICAgICAgYXdhaXQgc2xlZXAoNDAwKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihgUHJvY2VzcyBuZXZlciBkaWVkIHdpdGhpbiAke3RpbWVvdXRNc30gbXNgKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIGJyb2FkY2FzdCBwcm9jZXNzIGVuZC4gT3JpZ2luYWwgZXJyb3I6ICR7ZS5tZXNzYWdlfWApO1xuICB9XG59O1xuXG4vKipcbiAqIEJyb2FkY2FzdCBhIG1lc3NhZ2UgdG8gdGhlIGdpdmVuIGludGVudC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaW50ZW50IC0gVGhlIG5hbWUgb2YgdGhlIGludGVudCB0byBicm9hZGNhc3QgdG8uXG4gKiBAdGhyb3dzIHtlcnJvcn0gSWYgaW50ZW50IG5hbWUgaXMgbm90IGEgdmFsaWQgY2xhc3MgbmFtZS5cbiAqL1xubWV0aG9kcy5icm9hZGNhc3QgPSBhc3luYyBmdW5jdGlvbiBicm9hZGNhc3QgKGludGVudCkge1xuICBpZiAoIXRoaXMuaXNWYWxpZENsYXNzKGludGVudCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgaW50ZW50ICR7aW50ZW50fWApO1xuICB9XG4gIGxvZy5kZWJ1ZyhgQnJvYWRjYXN0aW5nOiAke2ludGVudH1gKTtcbiAgYXdhaXQgdGhpcy5zaGVsbChbJ2FtJywgJ2Jyb2FkY2FzdCcsICctYScsIGludGVudF0pO1xufTtcblxuLyoqXG4gKiBLaWxsIEFuZHJvaWQgaW5zdHJ1bWVudHMgaWYgdGhleSBhcmUgY3VycmVudGx5IHJ1bm5pbmcuXG4gKi9cbm1ldGhvZHMuZW5kQW5kcm9pZENvdmVyYWdlID0gYXN5bmMgZnVuY3Rpb24gZW5kQW5kcm9pZENvdmVyYWdlICgpIHtcbiAgaWYgKHRoaXMuaW5zdHJ1bWVudFByb2MgJiYgdGhpcy5pbnN0cnVtZW50UHJvYy5pc1J1bm5pbmcpIHtcbiAgICBhd2FpdCB0aGlzLmluc3RydW1lbnRQcm9jLnN0b3AoKTtcbiAgfVxufTtcblxuLyoqXG4gKiBJbnN0cnVtZW50IHRoZSBwYXJ0aWN1bGFyIGFjdGl2aXR5LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwa2cgLSBUaGUgbmFtZSBvZiB0aGUgcGFja2FnZSB0byBiZSBpbnN0cnVtZW50ZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gYWN0aXZpdHkgLSBUaGUgbmFtZSBvZiB0aGUgbWFpbiBhY3Rpdml0eSBpbiB0aGlzIHBhY2thZ2UuXG4gKiBAcGFyYW0ge3N0cmluZ30gaW5zdHJ1bWVudFdpdGggLSBUaGUgbmFtZSBvZiB0aGUgcGFja2FnZSB0byBpbnN0cnVtZW50XG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGUgYWN0aXZpdHkgd2l0aC5cbiAqIEB0aHJvd3Mge2Vycm9yfSBJZiBhbnkgZXhjZXB0aW9uIGlzIHJlcG9ydGVkIGJ5IGFkYiBzaGVsbC5cbiAqL1xubWV0aG9kcy5pbnN0cnVtZW50ID0gYXN5bmMgZnVuY3Rpb24gaW5zdHJ1bWVudCAocGtnLCBhY3Rpdml0eSwgaW5zdHJ1bWVudFdpdGgpIHtcbiAgaWYgKGFjdGl2aXR5WzBdICE9PSAnLicpIHtcbiAgICBwa2cgPSAnJztcbiAgfVxuICBsZXQgcGtnQWN0aXZpdHkgPSAocGtnICsgYWN0aXZpdHkpLnJlcGxhY2UoL1xcLisvZywgJy4nKTsgLy8gRml4IHBrZy4uYWN0aXZpdHkgZXJyb3JcbiAgbGV0IHN0ZG91dCA9IGF3YWl0IHRoaXMuc2hlbGwoW1xuICAgICdhbScsICdpbnN0cnVtZW50JyxcbiAgICAnLWUnLCAnbWFpbl9hY3Rpdml0eScsXG4gICAgcGtnQWN0aXZpdHksXG4gICAgaW5zdHJ1bWVudFdpdGgsXG4gIF0pO1xuICBpZiAoc3Rkb3V0LmluZGV4T2YoJ0V4Y2VwdGlvbicpICE9PSAtMSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBleGNlcHRpb24gZHVyaW5nIGluc3RydW1lbnRhdGlvbi4gT3JpZ2luYWwgZXJyb3IgJHtzdGRvdXQuc3BsaXQoJ1xcbicpWzBdfWApO1xuICB9XG59O1xuXG4vKipcbiAqIENvbGxlY3QgQW5kcm9pZCBjb3ZlcmFnZSBieSBpbnN0cnVtZW50aW5nIHRoZSBwYXJ0aWN1bGFyIGFjdGl2aXR5LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBpbnN0cnVtZW50Q2xhc3MgLSBUaGUgbmFtZSBvZiB0aGUgaW5zdHJ1bWVudGF0aW9uIGNsYXNzLlxuICogQHBhcmFtIHtzdHJpbmd9IHdhaXRQa2cgLSBUaGUgbmFtZSBvZiB0aGUgcGFja2FnZSB0byBiZSBpbnN0cnVtZW50ZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gd2FpdEFjdGl2aXR5IC0gVGhlIG5hbWUgb2YgdGhlIG1haW4gYWN0aXZpdHkgaW4gdGhpcyBwYWNrYWdlLlxuICpcbiAqIEByZXR1cm4ge3Byb21pc2V9IFRoZSBwcm9taXNlIGlzIHN1Y2Nlc3NmdWxseSByZXNvbHZlZCBpZiB0aGUgaW5zdHJ1bWVudGF0aW9uIHN0YXJ0c1xuICogICAgICAgICAgICAgICAgICAgd2l0aG91dCBlcnJvcnMuXG4gKi9cbm1ldGhvZHMuYW5kcm9pZENvdmVyYWdlID0gYXN5bmMgZnVuY3Rpb24gYW5kcm9pZENvdmVyYWdlIChpbnN0cnVtZW50Q2xhc3MsIHdhaXRQa2csIHdhaXRBY3Rpdml0eSkge1xuICBpZiAoIXRoaXMuaXNWYWxpZENsYXNzKGluc3RydW1lbnRDbGFzcykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgY2xhc3MgJHtpbnN0cnVtZW50Q2xhc3N9YCk7XG4gIH1cbiAgcmV0dXJuIGF3YWl0IG5ldyBCKGFzeW5jIChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBsZXQgYXJncyA9IHRoaXMuZXhlY3V0YWJsZS5kZWZhdWx0QXJnc1xuICAgICAgLmNvbmNhdChbJ3NoZWxsJywgJ2FtJywgJ2luc3RydW1lbnQnLCAnLWUnLCAnY292ZXJhZ2UnLCAndHJ1ZScsICctdyddKVxuICAgICAgLmNvbmNhdChbaW5zdHJ1bWVudENsYXNzXSk7XG4gICAgbG9nLmRlYnVnKGBDb2xsZWN0aW5nIGNvdmVyYWdlIGRhdGEgd2l0aDogJHtbdGhpcy5leGVjdXRhYmxlLnBhdGhdLmNvbmNhdChhcmdzKS5qb2luKCcgJyl9YCk7XG4gICAgdHJ5IHtcbiAgICAgIC8vIGFtIGluc3RydW1lbnQgcnVucyBmb3IgdGhlIGxpZmUgb2YgdGhlIGFwcCBwcm9jZXNzLlxuICAgICAgdGhpcy5pbnN0cnVtZW50UHJvYyA9IG5ldyBTdWJQcm9jZXNzKHRoaXMuZXhlY3V0YWJsZS5wYXRoLCBhcmdzKTtcbiAgICAgIGF3YWl0IHRoaXMuaW5zdHJ1bWVudFByb2Muc3RhcnQoMCk7XG4gICAgICB0aGlzLmluc3RydW1lbnRQcm9jLm9uKCdvdXRwdXQnLCAoc3Rkb3V0LCBzdGRlcnIpID0+IHtcbiAgICAgICAgaWYgKHN0ZGVycikge1xuICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBydW4gaW5zdHJ1bWVudGF0aW9uLiBPcmlnaW5hbCBlcnJvcjogJHtzdGRlcnJ9YCkpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGF3YWl0IHRoaXMud2FpdEZvckFjdGl2aXR5KHdhaXRQa2csIHdhaXRBY3Rpdml0eSk7XG4gICAgICByZXNvbHZlKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmVqZWN0KG5ldyBFcnJvcihgQW5kcm9pZCBjb3ZlcmFnZSBmYWlsZWQuIE9yaWdpbmFsIGVycm9yOiAke2UubWVzc2FnZX1gKSk7XG4gICAgfVxuICB9KTtcbn07XG5cbi8qKlxuICogR2V0IHRoZSBwYXJ0aWN1bGFyIHByb3BlcnR5IG9mIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvcGVydHkgLSBUaGUgbmFtZSBvZiB0aGUgcHJvcGVydHkuIFRoaXMgbmFtZSBzaG91bGRcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlIGtub3duIHRvIF9hZGIgc2hlbGwgZ2V0cHJvcF8gdG9vbC5cbiAqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSB2YWx1ZSBvZiB0aGUgZ2l2ZW4gcHJvcGVydHkuXG4gKi9cbm1ldGhvZHMuZ2V0RGV2aWNlUHJvcGVydHkgPSBhc3luYyBmdW5jdGlvbiBnZXREZXZpY2VQcm9wZXJ0eSAocHJvcGVydHkpIHtcbiAgbGV0IHN0ZG91dCA9IGF3YWl0IHRoaXMuc2hlbGwoWydnZXRwcm9wJywgcHJvcGVydHldKTtcbiAgbGV0IHZhbCA9IHN0ZG91dC50cmltKCk7XG4gIGxvZy5kZWJ1ZyhgQ3VycmVudCBkZXZpY2UgcHJvcGVydHkgJyR7cHJvcGVydHl9JzogJHt2YWx9YCk7XG4gIHJldHVybiB2YWw7XG59O1xuXG4vKipcbiAqIEB0eXBlZGVmIHtvYmplY3R9IHNldFByb3BPcHRzXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IHByaXZpbGVnZWQgLSBEbyB3ZSBydW4gc2V0UHJvcCBhcyBhIHByaXZpbGVnZWQgY29tbWFuZD8gRGVmYXVsdCB0cnVlLlxuICovXG5cbi8qKlxuICogU2V0IHRoZSBwYXJ0aWN1bGFyIHByb3BlcnR5IG9mIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvcGVydHkgLSBUaGUgbmFtZSBvZiB0aGUgcHJvcGVydHkuIFRoaXMgbmFtZSBzaG91bGRcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlIGtub3duIHRvIF9hZGIgc2hlbGwgc2V0cHJvcF8gdG9vbC5cbiAqIEBwYXJhbSB7c3RyaW5nfSB2YWwgLSBUaGUgbmV3IHByb3BlcnR5IHZhbHVlLlxuICogQHBhcmFtIHtzZXRQcm9wT3B0c30gb3B0c1xuICpcbiAqIEB0aHJvd3Mge2Vycm9yfSBJZiBfc2V0cHJvcF8gdXRpbGl0eSBmYWlscyB0byBjaGFuZ2UgcHJvcGVydHkgdmFsdWUuXG4gKi9cbm1ldGhvZHMuc2V0RGV2aWNlUHJvcGVydHkgPSBhc3luYyBmdW5jdGlvbiBzZXREZXZpY2VQcm9wZXJ0eSAocHJvcCwgdmFsLCBvcHRzID0ge30pIHtcbiAgY29uc3Qge3ByaXZpbGVnZWQgPSB0cnVlfSA9IG9wdHM7XG4gIGxvZy5kZWJ1ZyhgU2V0dGluZyBkZXZpY2UgcHJvcGVydHkgJyR7cHJvcH0nIHRvICcke3ZhbH0nYCk7XG4gIGF3YWl0IHRoaXMuc2hlbGwoWydzZXRwcm9wJywgcHJvcCwgdmFsXSwge1xuICAgIHByaXZpbGVnZWQsXG4gIH0pO1xufTtcblxuLyoqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IEN1cnJlbnQgc3lzdGVtIGxhbmd1YWdlIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqL1xubWV0aG9kcy5nZXREZXZpY2VTeXNMYW5ndWFnZSA9IGFzeW5jIGZ1bmN0aW9uIGdldERldmljZVN5c0xhbmd1YWdlICgpIHtcbiAgcmV0dXJuIGF3YWl0IHRoaXMuZ2V0RGV2aWNlUHJvcGVydHkoJ3BlcnNpc3Quc3lzLmxhbmd1YWdlJyk7XG59O1xuXG4vKipcbiAqIEByZXR1cm4ge3N0cmluZ30gQ3VycmVudCBjb3VudHJ5IG5hbWUgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICovXG5tZXRob2RzLmdldERldmljZVN5c0NvdW50cnkgPSBhc3luYyBmdW5jdGlvbiBnZXREZXZpY2VTeXNDb3VudHJ5ICgpIHtcbiAgcmV0dXJuIGF3YWl0IHRoaXMuZ2V0RGV2aWNlUHJvcGVydHkoJ3BlcnNpc3Quc3lzLmNvdW50cnknKTtcbn07XG5cbi8qKlxuICogQHJldHVybiB7c3RyaW5nfSBDdXJyZW50IHN5c3RlbSBsb2NhbGUgbmFtZSBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKi9cbm1ldGhvZHMuZ2V0RGV2aWNlU3lzTG9jYWxlID0gYXN5bmMgZnVuY3Rpb24gZ2V0RGV2aWNlU3lzTG9jYWxlICgpIHtcbiAgcmV0dXJuIGF3YWl0IHRoaXMuZ2V0RGV2aWNlUHJvcGVydHkoJ3BlcnNpc3Quc3lzLmxvY2FsZScpO1xufTtcblxuLyoqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IEN1cnJlbnQgcHJvZHVjdCBsYW5ndWFnZSBuYW1lIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqL1xubWV0aG9kcy5nZXREZXZpY2VQcm9kdWN0TGFuZ3VhZ2UgPSBhc3luYyBmdW5jdGlvbiBnZXREZXZpY2VQcm9kdWN0TGFuZ3VhZ2UgKCkge1xuICByZXR1cm4gYXdhaXQgdGhpcy5nZXREZXZpY2VQcm9wZXJ0eSgncm8ucHJvZHVjdC5sb2NhbGUubGFuZ3VhZ2UnKTtcbn07XG5cbi8qKlxuICogQHJldHVybiB7c3RyaW5nfSBDdXJyZW50IHByb2R1Y3QgY291bnRyeSBuYW1lIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqL1xubWV0aG9kcy5nZXREZXZpY2VQcm9kdWN0Q291bnRyeSA9IGFzeW5jIGZ1bmN0aW9uIGdldERldmljZVByb2R1Y3RDb3VudHJ5ICgpIHtcbiAgcmV0dXJuIGF3YWl0IHRoaXMuZ2V0RGV2aWNlUHJvcGVydHkoJ3JvLnByb2R1Y3QubG9jYWxlLnJlZ2lvbicpO1xufTtcblxuLyoqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IEN1cnJlbnQgcHJvZHVjdCBsb2NhbGUgbmFtZSBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKi9cbm1ldGhvZHMuZ2V0RGV2aWNlUHJvZHVjdExvY2FsZSA9IGFzeW5jIGZ1bmN0aW9uIGdldERldmljZVByb2R1Y3RMb2NhbGUgKCkge1xuICByZXR1cm4gYXdhaXQgdGhpcy5nZXREZXZpY2VQcm9wZXJ0eSgncm8ucHJvZHVjdC5sb2NhbGUnKTtcbn07XG5cbi8qKlxuICogQHJldHVybiB7c3RyaW5nfSBUaGUgbW9kZWwgbmFtZSBvZiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKi9cbm1ldGhvZHMuZ2V0TW9kZWwgPSBhc3luYyBmdW5jdGlvbiBnZXRNb2RlbCAoKSB7XG4gIHJldHVybiBhd2FpdCB0aGlzLmdldERldmljZVByb3BlcnR5KCdyby5wcm9kdWN0Lm1vZGVsJyk7XG59O1xuXG4vKipcbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIG1hbnVmYWN0dXJlciBuYW1lIG9mIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqL1xubWV0aG9kcy5nZXRNYW51ZmFjdHVyZXIgPSBhc3luYyBmdW5jdGlvbiBnZXRNYW51ZmFjdHVyZXIgKCkge1xuICByZXR1cm4gYXdhaXQgdGhpcy5nZXREZXZpY2VQcm9wZXJ0eSgncm8ucHJvZHVjdC5tYW51ZmFjdHVyZXInKTtcbn07XG5cbi8qKlxuICogR2V0IHRoZSBjdXJyZW50IHNjcmVlbiBzaXplLlxuICpcbiAqIEByZXR1cm4ge3N0cmluZ30gRGV2aWNlIHNjcmVlbiBzaXplIGFzIHN0cmluZyBpbiBmb3JtYXQgJ1d4SCcgb3JcbiAqICAgICAgICAgICAgICAgICAgX251bGxfIGlmIGl0IGNhbm5vdCBiZSBkZXRlcm1pbmVkLlxuICovXG5tZXRob2RzLmdldFNjcmVlblNpemUgPSBhc3luYyBmdW5jdGlvbiBnZXRTY3JlZW5TaXplICgpIHtcbiAgbGV0IHN0ZG91dCA9IGF3YWl0IHRoaXMuc2hlbGwoWyd3bScsICdzaXplJ10pO1xuICBsZXQgc2l6ZSA9IG5ldyBSZWdFeHAoL1BoeXNpY2FsIHNpemU6IChbXlxccj9cXG5dKykqL2cpLmV4ZWMoc3Rkb3V0KTtcbiAgaWYgKHNpemUgJiYgc2l6ZS5sZW5ndGggPj0gMikge1xuICAgIHJldHVybiBzaXplWzFdLnRyaW0oKTtcbiAgfVxuICByZXR1cm4gbnVsbDtcbn07XG5cbi8qKlxuICogR2V0IHRoZSBjdXJyZW50IHNjcmVlbiBkZW5zaXR5IGluIGRwaVxuICpcbiAqIEByZXR1cm4gez9udW1iZXJ9IERldmljZSBzY3JlZW4gZGVuc2l0eSBhcyBhIG51bWJlciBvciBfbnVsbF8gaWYgaXRcbiAqICAgICAgICAgICAgICAgICAgY2Fubm90IGJlIGRldGVybWluZWRcbiAqL1xubWV0aG9kcy5nZXRTY3JlZW5EZW5zaXR5ID0gYXN5bmMgZnVuY3Rpb24gZ2V0U2NyZWVuRGVuc2l0eSAoKSB7XG4gIGxldCBzdGRvdXQgPSBhd2FpdCB0aGlzLnNoZWxsKFsnd20nLCAnZGVuc2l0eSddKTtcbiAgbGV0IGRlbnNpdHkgPSBuZXcgUmVnRXhwKC9QaHlzaWNhbCBkZW5zaXR5OiAoW15cXHI/XFxuXSspKi9nKS5leGVjKHN0ZG91dCk7XG4gIGlmIChkZW5zaXR5ICYmIGRlbnNpdHkubGVuZ3RoID49IDIpIHtcbiAgICBsZXQgZGVuc2l0eU51bWJlciA9IHBhcnNlSW50KGRlbnNpdHlbMV0udHJpbSgpLCAxMCk7XG4gICAgcmV0dXJuIGlzTmFOKGRlbnNpdHlOdW1iZXIpID8gbnVsbCA6IGRlbnNpdHlOdW1iZXI7XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59O1xuXG4vKipcbiAqIFNldHVwIEhUVFAgcHJveHkgaW4gZGV2aWNlIGdsb2JhbCBzZXR0aW5ncy5cbiAqIFJlYWQgaHR0cHM6Ly9hbmRyb2lkLmdvb2dsZXNvdXJjZS5jb20vcGxhdGZvcm0vZnJhbWV3b3Jrcy9iYXNlLysvYW5kcm9pZC05LjAuMF9yMjEvY29yZS9qYXZhL2FuZHJvaWQvcHJvdmlkZXIvU2V0dGluZ3MuamF2YSBmb3IgZWFjaCBwcm9wZXJ0eVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm94eUhvc3QgLSBUaGUgaG9zdCBuYW1lIG9mIHRoZSBwcm94eS5cbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gcHJveHlQb3J0IC0gVGhlIHBvcnQgbnVtYmVyIHRvIGJlIHNldC5cbiAqL1xubWV0aG9kcy5zZXRIdHRwUHJveHkgPSBhc3luYyBmdW5jdGlvbiBzZXRIdHRwUHJveHkgKHByb3h5SG9zdCwgcHJveHlQb3J0KSB7XG4gIGxldCBwcm94eSA9IGAke3Byb3h5SG9zdH06JHtwcm94eVBvcnR9YDtcbiAgaWYgKF8uaXNVbmRlZmluZWQocHJveHlIb3N0KSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgQ2FsbCB0byBzZXRIdHRwUHJveHkgbWV0aG9kIHdpdGggdW5kZWZpbmVkIHByb3h5X2hvc3Q6ICR7cHJveHl9YCk7XG4gIH1cbiAgaWYgKF8uaXNVbmRlZmluZWQocHJveHlQb3J0KSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgQ2FsbCB0byBzZXRIdHRwUHJveHkgbWV0aG9kIHdpdGggdW5kZWZpbmVkIHByb3h5X3BvcnQgJHtwcm94eX1gKTtcbiAgfVxuXG4gIGNvbnN0IGh0dHBQcm94eVNldHRpbnMgPSBbXG4gICAgWydodHRwX3Byb3h5JywgcHJveHldLFxuICAgIFsnZ2xvYmFsX2h0dHBfcHJveHlfaG9zdCcsIHByb3h5SG9zdF0sXG4gICAgWydnbG9iYWxfaHR0cF9wcm94eV9wb3J0JywgcHJveHlQb3J0XVxuICBdO1xuICBmb3IgKGNvbnN0IFtzZXR0aW5nS2V5LCBzZXR0aW5nVmFsdWVdIG9mIGh0dHBQcm94eVNldHRpbnMpIHtcbiAgICBhd2FpdCB0aGlzLnNldFNldHRpbmcoJ2dsb2JhbCcsIHNldHRpbmdLZXksIHNldHRpbmdWYWx1ZSk7XG4gIH1cbn07XG5cbi8qKlxuICogRGVsZXRlIEhUVFAgcHJveHkgaW4gZGV2aWNlIGdsb2JhbCBzZXR0aW5ncy5cbiAqIFJlYm9vdGluZyB0aGUgdGVzdCBkZXZpY2UgaXMgbmVjZXNzYXJ5IHRvIGFwcGx5IHRoZSBjaGFuZ2UuXG4gKi9cbm1ldGhvZHMuZGVsZXRlSHR0cFByb3h5ID0gYXN5bmMgZnVuY3Rpb24gZGVsZXRlSHR0cFByb3h5ICgpIHtcbiAgY29uc3QgaHR0cFByb3h5U2V0dGlucyA9IFtcbiAgICAnaHR0cF9wcm94eScsXG4gICAgJ2dsb2JhbF9odHRwX3Byb3h5X2hvc3QnLFxuICAgICdnbG9iYWxfaHR0cF9wcm94eV9wb3J0JyxcbiAgICAnZ2xvYmFsX2h0dHBfcHJveHlfZXhjbHVzaW9uX2xpc3QnIC8vIGBnbG9iYWxfaHR0cF9wcm94eV9leGNsdXNpb25fbGlzdD1gIHdhcyBnZW5lcmF0ZWQgYnkgYHNldHRpbmdzIGdsb2JhbCBodHRvX3Byb3h5IHh4eHhgXG4gIF07XG4gIGZvciAoY29uc3Qgc2V0dGluZyBvZiBodHRwUHJveHlTZXR0aW5zKSB7XG4gICAgYXdhaXQgdGhpcy5zaGVsbChbJ3NldHRpbmdzJywgJ2RlbGV0ZScsICdnbG9iYWwnLCBzZXR0aW5nXSk7XG4gIH1cbn07XG5cbi8qKlxuICogU2V0IGRldmljZSBwcm9wZXJ0eS5cbiAqIFthbmRyb2lkLnByb3ZpZGVyLlNldHRpbmdzXXtAbGluayBodHRwczovL2RldmVsb3Blci5hbmRyb2lkLmNvbS9yZWZlcmVuY2UvYW5kcm9pZC9wcm92aWRlci9TZXR0aW5ncy5odG1sfVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lc3BhY2UgLSBvbmUgb2Yge3N5c3RlbSwgc2VjdXJlLCBnbG9iYWx9LCBjYXNlLWluc2Vuc2l0aXZlLlxuICogQHBhcmFtIHtzdHJpbmd9IHNldHRpbmcgLSBwcm9wZXJ0eSBuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSB2YWx1ZSAtIHByb3BlcnR5IHZhbHVlLlxuICogQHJldHVybiB7c3RyaW5nfSBjb21tYW5kIG91dHB1dC5cbiAqL1xubWV0aG9kcy5zZXRTZXR0aW5nID0gYXN5bmMgZnVuY3Rpb24gc2V0U2V0dGluZyAobmFtZXNwYWNlLCBzZXR0aW5nLCB2YWx1ZSkge1xuICByZXR1cm4gYXdhaXQgdGhpcy5zaGVsbChbJ3NldHRpbmdzJywgJ3B1dCcsIG5hbWVzcGFjZSwgc2V0dGluZywgdmFsdWVdKTtcbn07XG5cbi8qKlxuICogR2V0IGRldmljZSBwcm9wZXJ0eS5cbiAqIFthbmRyb2lkLnByb3ZpZGVyLlNldHRpbmdzXXtAbGluayBodHRwczovL2RldmVsb3Blci5hbmRyb2lkLmNvbS9yZWZlcmVuY2UvYW5kcm9pZC9wcm92aWRlci9TZXR0aW5ncy5odG1sfVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lc3BhY2UgLSBvbmUgb2Yge3N5c3RlbSwgc2VjdXJlLCBnbG9iYWx9LCBjYXNlLWluc2Vuc2l0aXZlLlxuICogQHBhcmFtIHtzdHJpbmd9IHNldHRpbmcgLSBwcm9wZXJ0eSBuYW1lLlxuICogQHJldHVybiB7c3RyaW5nfSBwcm9wZXJ0eSB2YWx1ZS5cbiAqL1xubWV0aG9kcy5nZXRTZXR0aW5nID0gYXN5bmMgZnVuY3Rpb24gZ2V0U2V0dGluZyAobmFtZXNwYWNlLCBzZXR0aW5nKSB7XG4gIHJldHVybiBhd2FpdCB0aGlzLnNoZWxsKFsnc2V0dGluZ3MnLCAnZ2V0JywgbmFtZXNwYWNlLCBzZXR0aW5nXSk7XG59O1xuXG4vKipcbiAqIFJldHJpZXZlIHRoZSBgYWRiIGJ1Z3JlcG9ydGAgY29tbWFuZCBvdXRwdXQuIFRoaXNcbiAqIG9wZXJhdGlvbiBtYXkgdGFrZSB1cCB0byBzZXZlcmFsIG1pbnV0ZXMuXG4gKlxuICogQHBhcmFtIHs/bnVtYmVyfSB0aW1lb3V0IFsxMjAwMDBdIC0gQ29tbWFuZCB0aW1lb3V0IGluIG1pbGxpc2Vjb25kc1xuICogQHJldHVybnMge3N0cmluZ30gQ29tbWFuZCBzdGRvdXRcbiAqL1xubWV0aG9kcy5idWdyZXBvcnQgPSBhc3luYyBmdW5jdGlvbiBidWdyZXBvcnQgKHRpbWVvdXQgPSAxMjAwMDApIHtcbiAgcmV0dXJuIGF3YWl0IHRoaXMuYWRiRXhlYyhbJ2J1Z3JlcG9ydCddLCB7dGltZW91dH0pO1xufTtcblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBTY3JlZW5yZWNvcmRPcHRpb25zXG4gKiBAcHJvcGVydHkgez9zdHJpbmd9IHZpZGVvU2l6ZSAtIFRoZSBmb3JtYXQgaXMgd2lkdGh4aGVpZ2h0LlxuICogICAgICAgICAgICAgICAgICBUaGUgZGVmYXVsdCB2YWx1ZSBpcyB0aGUgZGV2aWNlJ3MgbmF0aXZlIGRpc3BsYXkgcmVzb2x1dGlvbiAoaWYgc3VwcG9ydGVkKSxcbiAqICAgICAgICAgICAgICAgICAgMTI4MHg3MjAgaWYgbm90LiBGb3IgYmVzdCByZXN1bHRzLFxuICogICAgICAgICAgICAgICAgICB1c2UgYSBzaXplIHN1cHBvcnRlZCBieSB5b3VyIGRldmljZSdzIEFkdmFuY2VkIFZpZGVvIENvZGluZyAoQVZDKSBlbmNvZGVyLlxuICogICAgICAgICAgICAgICAgICBGb3IgZXhhbXBsZSwgXCIxMjgweDcyMFwiXG4gKiBAcHJvcGVydHkgez9ib29sZWFufSBidWdSZXBvcnQgLSBTZXQgaXQgdG8gYHRydWVgIGluIG9yZGVyIHRvIGRpc3BsYXkgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiBvbiB0aGUgdmlkZW8gb3ZlcmxheSxcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2ggYXMgYSB0aW1lc3RhbXAsIHRoYXQgaXMgaGVscGZ1bCBpbiB2aWRlb3MgY2FwdHVyZWQgdG8gaWxsdXN0cmF0ZSBidWdzLlxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVGhpcyBvcHRpb24gaXMgb25seSBzdXBwb3J0ZWQgc2luY2UgQVBJIGxldmVsIDI3IChBbmRyb2lkIFApLlxuICogQHByb3BlcnR5IHs/c3RyaW5nfG51bWJlcn0gdGltZUxpbWl0IC0gVGhlIG1heGltdW0gcmVjb3JkaW5nIHRpbWUsIGluIHNlY29uZHMuXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUaGUgZGVmYXVsdCAoYW5kIG1heGltdW0pIHZhbHVlIGlzIDE4MCAoMyBtaW51dGVzKS5cbiAqIEBwcm9wZXJ0eSB7P3N0cmluZ3xudW1iZXJ9IGJpdFJhdGUgLSBUaGUgdmlkZW8gYml0IHJhdGUgZm9yIHRoZSB2aWRlbywgaW4gbWVnYWJpdHMgcGVyIHNlY29uZC5cbiAqICAgICAgICAgICAgICAgIFRoZSBkZWZhdWx0IHZhbHVlIGlzIDQuIFlvdSBjYW4gaW5jcmVhc2UgdGhlIGJpdCByYXRlIHRvIGltcHJvdmUgdmlkZW8gcXVhbGl0eSxcbiAqICAgICAgICAgICAgICAgIGJ1dCBkb2luZyBzbyByZXN1bHRzIGluIGxhcmdlciBtb3ZpZSBmaWxlcy5cbiAqL1xuXG4vKipcbiAqIEluaXRpYXRlIHNjcmVlbnJlY29yZCB1dGlsaXR5IG9uIHRoZSBkZXZpY2VcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gZGVzdGluYXRpb24gLSBGdWxsIHBhdGggdG8gdGhlIHdyaXRhYmxlIG1lZGlhIGZpbGUgZGVzdGluYXRpb25cbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uIHRoZSBkZXZpY2UgZmlsZSBzeXN0ZW0uXG4gKiBAcGFyYW0gez9TY3JlZW5yZWNvcmRPcHRpb25zfSBvcHRpb25zIFt7fV1cbiAqIEByZXR1cm5zIHtTdWJQcm9jZXNzfSBzY3JlZW5yZWNvcmQgcHJvY2Vzcywgd2hpY2ggY2FuIGJlIHRoZW4gY29udHJvbGxlZCBieSB0aGUgY2xpZW50IGNvZGVcbiAqL1xubWV0aG9kcy5zY3JlZW5yZWNvcmQgPSBmdW5jdGlvbiBzY3JlZW5yZWNvcmQgKGRlc3RpbmF0aW9uLCBvcHRpb25zID0ge30pIHtcbiAgY29uc3QgY21kID0gWydzY3JlZW5yZWNvcmQnXTtcbiAgY29uc3Qge1xuICAgIHZpZGVvU2l6ZSxcbiAgICBiaXRSYXRlLFxuICAgIHRpbWVMaW1pdCxcbiAgICBidWdSZXBvcnQsXG4gIH0gPSBvcHRpb25zO1xuICBpZiAodXRpbC5oYXNWYWx1ZSh2aWRlb1NpemUpKSB7XG4gICAgY21kLnB1c2goJy0tc2l6ZScsIHZpZGVvU2l6ZSk7XG4gIH1cbiAgaWYgKHV0aWwuaGFzVmFsdWUodGltZUxpbWl0KSkge1xuICAgIGNtZC5wdXNoKCctLXRpbWUtbGltaXQnLCB0aW1lTGltaXQpO1xuICB9XG4gIGlmICh1dGlsLmhhc1ZhbHVlKGJpdFJhdGUpKSB7XG4gICAgY21kLnB1c2goJy0tYml0LXJhdGUnLCBiaXRSYXRlKTtcbiAgfVxuICBpZiAoYnVnUmVwb3J0KSB7XG4gICAgY21kLnB1c2goJy0tYnVncmVwb3J0Jyk7XG4gIH1cbiAgY21kLnB1c2goZGVzdGluYXRpb24pO1xuXG4gIGNvbnN0IGZ1bGxDbWQgPSBbXG4gICAgLi4udGhpcy5leGVjdXRhYmxlLmRlZmF1bHRBcmdzLFxuICAgICdzaGVsbCcsXG4gICAgLi4uY21kXG4gIF07XG4gIGxvZy5kZWJ1ZyhgQnVpbGRpbmcgc2NyZWVucmVjb3JkIHByb2Nlc3Mgd2l0aCB0aGUgY29tbWFuZCBsaW5lOiBhZGIgJHt1dGlsLnF1b3RlKGZ1bGxDbWQpfWApO1xuICByZXR1cm4gbmV3IFN1YlByb2Nlc3ModGhpcy5leGVjdXRhYmxlLnBhdGgsIGZ1bGxDbWQpO1xufTtcblxuLyoqXG4gKiBFeGVjdXRlcyB0aGUgZ2l2ZW4gZnVuY3Rpb24gd2l0aCB0aGUgZ2l2ZW4gaW5wdXQgbWV0aG9kIGNvbnRleHRcbiAqIGFuZCB0aGVuIHJlc3RvcmVzIHRoZSBJTUUgdG8gdGhlIG9yaWdpbmFsIHZhbHVlXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGltZSAtIFZhbGlkIElNRSBpZGVudGlmaWVyXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiAtIEZ1bmN0aW9uIHRvIGV4ZWN1dGVcbiAqIEByZXR1cm5zIHsqfSBUaGUgcmVzdWx0IG9mIHRoZSBnaXZlbiBmdW5jdGlvblxuICovXG5tZXRob2RzLnJ1bkluSW1lQ29udGV4dCA9IGFzeW5jIGZ1bmN0aW9uIHJ1bkluSW1lQ29udGV4dCAoaW1lLCBmbikge1xuICBjb25zdCBvcmlnaW5hbEltZSA9IGF3YWl0IHRoaXMuZGVmYXVsdElNRSgpO1xuICBpZiAob3JpZ2luYWxJbWUgPT09IGltZSkge1xuICAgIGxvZy5kZWJ1ZyhgVGhlIG9yaWdpbmFsIElNRSBpcyB0aGUgc2FtZSBhcyAnJHtpbWV9Jy4gVGhlcmUgaXMgbm8gbmVlZCB0byByZXNldCBpdGApO1xuICB9IGVsc2Uge1xuICAgIGF3YWl0IHRoaXMuc2V0SU1FKGltZSk7XG4gIH1cbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgZm4oKTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAob3JpZ2luYWxJbWUgIT09IGltZSkge1xuICAgICAgYXdhaXQgdGhpcy5zZXRJTUUob3JpZ2luYWxJbWUpO1xuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBHZXQgdHogZGF0YWJhc2UgdGltZSB6b25lIGZvcm1hdHRlZCB0aW1lem9uZVxuICpcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFRaIGRhdGFiYXNlIFRpbWUgWm9uZXMgZm9ybWF0XG4gKlxuICogQHRocm93cyB7ZXJyb3J9IElmIGFueSBleGNlcHRpb24gaXMgcmVwb3J0ZWQgYnkgYWRiIHNoZWxsLlxuICovXG5tZXRob2RzLmdldFRpbWVab25lID0gYXN5bmMgZnVuY3Rpb24gZ2V0VGltZVpvbmUgKCkge1xuICBsb2cuZGVidWcoJ0dldHRpbmcgY3VycmVudCB0aW1lem9uZScpO1xuICB0cnkge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLmdldERldmljZVByb3BlcnR5KCdwZXJzaXN0LnN5cy50aW1lem9uZScpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciBnZXR0aW5nIHRpbWV6b25lLiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gIH1cbn07XG5cbi8qKlxuICogUmV0cmlldmVzIHRoZSBsaXN0IG9mIGZlYXR1cmVzIHN1cHBvcnRlZCBieSB0aGUgZGV2aWNlIHVuZGVyIHRlc3RcbiAqXG4gKiBAcmV0dXJucyB7QXJyYXk8c3RyaW5nPn0gdGhlIGxpc3Qgb2Ygc3VwcG9ydGVkIGZlYXR1cmUgbmFtZXMgb3IgYW4gZW1wdHkgbGlzdC5cbiAqIEFuIGV4YW1wbGUgYWRiIGNvbW1hbmQgb3V0cHV0OlxuICogYGBgXG4gKiBjbWRcbiAqIGxzX3YyXG4gKiBmaXhlZF9wdXNoX21rZGlyXG4gKiBzaGVsbF92MlxuICogYWJiXG4gKiBzdGF0X3YyXG4gKiBhcGV4XG4gKiBhYmJfZXhlY1xuICogcmVtb3VudF9zaGVsbFxuICogZml4ZWRfcHVzaF9zeW1saW5rX3RpbWVzdGFtcFxuICogYGBgXG4gKiBAdGhyb3dzIHtFcnJvcn0gaWYgdGhlcmUgd2FzIGFuIGVycm9yIHdoaWxlIHJldHJpZXZpbmcgdGhlIGxpc3RcbiAqL1xubWV0aG9kcy5saXN0RmVhdHVyZXMgPSBhc3luYyBmdW5jdGlvbiBsaXN0RmVhdHVyZXMgKCkge1xuICB0aGlzLl9tZW1vaXplZEZlYXR1cmVzID0gdGhpcy5fbWVtb2l6ZWRGZWF0dXJlc1xuICAgIHx8IF8ubWVtb2l6ZShhc3luYyAoKSA9PiBhd2FpdCB0aGlzLmFkYkV4ZWMoWydmZWF0dXJlcyddKSwgKCkgPT4gdGhpcy5jdXJEZXZpY2VJZCk7XG4gIHRyeSB7XG4gICAgcmV0dXJuIChhd2FpdCB0aGlzLl9tZW1vaXplZEZlYXR1cmVzKCkpXG4gICAgICAuc3BsaXQoL1xccysvKVxuICAgICAgLm1hcCgoeCkgPT4geC50cmltKCkpXG4gICAgICAuZmlsdGVyKEJvb2xlYW4pO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKF8uaW5jbHVkZXMoZS5zdGRlcnIsICd1bmtub3duIGNvbW1hbmQnKSkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICB0aHJvdyBlO1xuICB9XG59O1xuXG4vKipcbiAqIENoZWNrcyB0aGUgc3RhdGUgb2Ygc3RyZWFtZWQgaW5zdGFsbCBmZWF0dXJlLlxuICogVGhpcyBmZWF0dXJlIGFsbG93cyB0byBzcGVlZCB1cCBhcGsgaW5zdGFsbGF0aW9uXG4gKiBzaW5jZSBpdCBkb2VzIG5vdCByZXF1aXJlIHRoZSBvcmlnaW5hbCBhcGsgdG8gYmUgcHVzaGVkIHRvXG4gKiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QgZmlyc3QsIHdoaWNoIGFsc28gc2F2ZXMgc3BhY2UuXG4gKiBBbHRob3VnaCwgaXQgaXMgcmVxdWlyZWQgdGhhdCBib3RoIHRoZSBkZXZpY2UgdW5kZXIgdGVzdFxuICogYW5kIHRoZSBhZGIgc2VydmVyIGhhdmUgdGhlIG1lbnRpb25lZCBmdW5jdGlvbmFsaXR5LlxuICogU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9hb3NwLW1pcnJvci9wbGF0Zm9ybV9zeXN0ZW1fY29yZS9ibG9iL21hc3Rlci9hZGIvY2xpZW50L2FkYl9pbnN0YWxsLmNwcFxuICogZm9yIG1vcmUgZGV0YWlsc1xuICpcbiAqIEByZXR1cm5zIHtib29sZWFufSBgdHJ1ZWAgaWYgdGhlIGZlYXR1cmUgaXMgc3VwcG9ydGVkIGJ5IGJvdGggYWRiIGFuZCB0aGVcbiAqIGRldmljZSB1bmRlciB0ZXN0XG4gKi9cbm1ldGhvZHMuaXNTdHJlYW1lZEluc3RhbGxTdXBwb3J0ZWQgPSBhc3luYyBmdW5jdGlvbiBpc1N0cmVhbWVkSW5zdGFsbFN1cHBvcnRlZCAoKSB7XG4gIGNvbnN0IHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHRoaXMpO1xuICBwcm90by5faGVscE91dHB1dCA9IHByb3RvLl9oZWxwT3V0cHV0IHx8IGF3YWl0IHRoaXMuYWRiRXhlYyhbJ2hlbHAnXSk7XG4gIHJldHVybiBwcm90by5faGVscE91dHB1dC5pbmNsdWRlcygnLS1zdHJlYW1pbmcnKSAmJiAoYXdhaXQgdGhpcy5saXN0RmVhdHVyZXMoKSkuaW5jbHVkZXMoJ2NtZCcpO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgbWV0aG9kcztcbiJdLCJmaWxlIjoibGliL3Rvb2xzL2FkYi1jb21tYW5kcy5qcyIsInNvdXJjZVJvb3QiOiIuLi8uLi8uLiJ9