appium-uiautomator2-driver 2.29.11 → 2.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/build/index.d.ts +4 -0
  3. package/build/index.d.ts.map +1 -0
  4. package/build/index.js +8 -15
  5. package/build/index.js.map +1 -0
  6. package/build/lib/commands/actions.d.ts +2 -0
  7. package/build/lib/commands/actions.d.ts.map +1 -0
  8. package/build/lib/commands/actions.js +67 -62
  9. package/build/lib/commands/actions.js.map +1 -1
  10. package/build/lib/commands/alert.d.ts +2 -0
  11. package/build/lib/commands/alert.d.ts.map +1 -0
  12. package/build/lib/commands/alert.js +28 -26
  13. package/build/lib/commands/alert.js.map +1 -1
  14. package/build/lib/commands/app-strings.d.ts +3 -0
  15. package/build/lib/commands/app-strings.d.ts.map +1 -0
  16. package/build/lib/commands/app-strings.js +86 -57
  17. package/build/lib/commands/app-strings.js.map +1 -1
  18. package/build/lib/commands/battery.d.ts +2 -0
  19. package/build/lib/commands/battery.d.ts.map +1 -0
  20. package/build/lib/commands/battery.js +26 -16
  21. package/build/lib/commands/battery.js.map +1 -1
  22. package/build/lib/commands/element.d.ts +2 -0
  23. package/build/lib/commands/element.d.ts.map +1 -0
  24. package/build/lib/commands/element.js +140 -159
  25. package/build/lib/commands/element.js.map +1 -1
  26. package/build/lib/commands/find.d.ts +2 -0
  27. package/build/lib/commands/find.d.ts.map +1 -0
  28. package/build/lib/commands/find.js +39 -25
  29. package/build/lib/commands/find.js.map +1 -1
  30. package/build/lib/commands/general.d.ts +4 -0
  31. package/build/lib/commands/general.d.ts.map +1 -0
  32. package/build/lib/commands/general.js +209 -215
  33. package/build/lib/commands/general.js.map +1 -1
  34. package/build/lib/commands/gestures.d.ts +2 -0
  35. package/build/lib/commands/gestures.d.ts.map +1 -0
  36. package/build/lib/commands/gestures.js +206 -193
  37. package/build/lib/commands/gestures.js.map +1 -1
  38. package/build/lib/commands/index.d.ts +2 -0
  39. package/build/lib/commands/index.d.ts.map +1 -0
  40. package/build/lib/commands/index.js +13 -22
  41. package/build/lib/commands/index.js.map +1 -1
  42. package/build/lib/commands/mixins.d.ts +87 -0
  43. package/build/lib/commands/mixins.d.ts.map +1 -0
  44. package/build/lib/commands/mixins.js +26 -0
  45. package/build/lib/commands/mixins.js.map +1 -0
  46. package/build/lib/commands/screenshot.d.ts +2 -0
  47. package/build/lib/commands/screenshot.d.ts.map +1 -0
  48. package/build/lib/commands/screenshot.js +77 -62
  49. package/build/lib/commands/screenshot.js.map +1 -1
  50. package/build/lib/commands/touch.d.ts +2 -0
  51. package/build/lib/commands/touch.d.ts.map +1 -0
  52. package/build/lib/commands/touch.js +48 -38
  53. package/build/lib/commands/touch.js.map +1 -1
  54. package/build/lib/commands/types.d.ts +452 -0
  55. package/build/lib/commands/types.d.ts.map +1 -0
  56. package/build/lib/commands/types.js +3 -0
  57. package/build/lib/commands/types.js.map +1 -0
  58. package/build/lib/commands/viewport.d.ts +2 -0
  59. package/build/lib/commands/viewport.d.ts.map +1 -0
  60. package/build/lib/commands/viewport.js +37 -35
  61. package/build/lib/commands/viewport.js.map +1 -1
  62. package/build/lib/constraints.d.ts +325 -0
  63. package/build/lib/constraints.d.ts.map +1 -0
  64. package/build/lib/constraints.js +51 -0
  65. package/build/lib/constraints.js.map +1 -0
  66. package/build/lib/css-converter.d.ts +45 -0
  67. package/build/lib/css-converter.d.ts.map +1 -0
  68. package/build/lib/css-converter.js +272 -175
  69. package/build/lib/css-converter.js.map +1 -1
  70. package/build/lib/driver.d.ts +904 -0
  71. package/build/lib/driver.d.ts.map +1 -0
  72. package/build/lib/driver.js +726 -485
  73. package/build/lib/driver.js.map +1 -1
  74. package/build/lib/execute-method-map.d.ts +477 -0
  75. package/build/lib/execute-method-map.d.ts.map +1 -0
  76. package/build/lib/execute-method-map.js +542 -0
  77. package/build/lib/execute-method-map.js.map +1 -0
  78. package/build/lib/extensions.d.ts +3 -0
  79. package/build/lib/extensions.d.ts.map +1 -0
  80. package/build/lib/extensions.js +7 -9
  81. package/build/lib/extensions.js.map +1 -1
  82. package/build/lib/helpers.d.ts +7 -0
  83. package/build/lib/helpers.d.ts.map +1 -0
  84. package/build/lib/helpers.js +36 -29
  85. package/build/lib/helpers.js.map +1 -1
  86. package/build/lib/logger.d.ts +3 -0
  87. package/build/lib/logger.d.ts.map +1 -0
  88. package/build/lib/logger.js +5 -10
  89. package/build/lib/logger.js.map +1 -1
  90. package/build/lib/method-map.d.ts +389 -0
  91. package/build/lib/method-map.d.ts.map +1 -0
  92. package/build/lib/method-map.js +11 -17
  93. package/build/lib/method-map.js.map +1 -1
  94. package/build/lib/types.d.ts +44 -0
  95. package/build/lib/types.d.ts.map +1 -0
  96. package/build/lib/types.js +3 -0
  97. package/build/lib/types.js.map +1 -0
  98. package/build/lib/uiautomator2.d.ts +45 -0
  99. package/build/lib/uiautomator2.d.ts.map +1 -0
  100. package/build/lib/uiautomator2.js +340 -299
  101. package/build/lib/uiautomator2.js.map +1 -1
  102. package/build/lib/utils.d.ts +10 -0
  103. package/build/lib/utils.d.ts.map +1 -0
  104. package/build/lib/utils.js +23 -16
  105. package/build/lib/utils.js.map +1 -1
  106. package/build/tsconfig.tsbuildinfo +1 -0
  107. package/index.js +5 -3
  108. package/lib/commands/actions.js +115 -101
  109. package/lib/commands/alert.js +36 -44
  110. package/lib/commands/app-strings.js +79 -58
  111. package/lib/commands/battery.js +27 -28
  112. package/lib/commands/element.js +231 -134
  113. package/lib/commands/find.js +40 -21
  114. package/lib/commands/general.js +262 -336
  115. package/lib/commands/gestures.js +252 -366
  116. package/lib/commands/index.js +11 -31
  117. package/lib/commands/mixins.ts +169 -0
  118. package/lib/commands/screenshot.js +80 -76
  119. package/lib/commands/touch.js +64 -31
  120. package/lib/commands/types.ts +473 -0
  121. package/lib/commands/viewport.js +43 -31
  122. package/lib/constraints.ts +53 -0
  123. package/lib/css-converter.js +9 -1
  124. package/lib/{driver.js → driver.ts} +374 -239
  125. package/lib/execute-method-map.ts +573 -0
  126. package/lib/method-map.ts +11 -0
  127. package/lib/types.ts +57 -0
  128. package/lib/uiautomator2.js +21 -2
  129. package/lib/utils.js +2 -2
  130. package/npm-shrinkwrap.json +395 -528
  131. package/package.json +96 -70
  132. package/build/lib/desired-caps.js +0 -71
  133. package/build/lib/desired-caps.js.map +0 -1
  134. package/lib/desired-caps.js +0 -70
  135. package/lib/method-map.js +0 -11
@@ -1,520 +1,761 @@
1
1
  "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
- Object.defineProperty(exports, "__esModule", {
5
- value: true
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
6
17
  });
7
- exports.default = exports.AndroidUiautomator2Driver = void 0;
8
- require("source-map-support/register");
9
- var _lodash = _interopRequireDefault(require("lodash"));
10
- var _driver = require("appium/driver");
11
- var _uiautomator = require("./uiautomator2");
12
- var _methodMap = require("./method-map");
13
- var _support = require("appium/support");
14
- var _asyncbox = require("asyncbox");
15
- var _bluebird = _interopRequireDefault(require("bluebird"));
16
- var _index = _interopRequireDefault(require("./commands/index"));
17
- var _appiumAdb = require("appium-adb");
18
- var _helpers = _interopRequireDefault(require("./helpers"));
19
- var _appiumAndroidDriver = require("appium-android-driver");
20
- var _desiredCaps = _interopRequireDefault(require("./desired-caps"));
21
- var _portscanner = require("portscanner");
22
- var _os = _interopRequireDefault(require("os"));
23
- var _path = _interopRequireDefault(require("path"));
24
- var _extensions = require("./extensions");
25
- const helpers = Object.assign({}, _helpers.default, _appiumAndroidDriver.androidHelpers);
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.AndroidUiautomator2Driver = void 0;
30
+ const appium_adb_1 = require("appium-adb");
31
+ const appium_android_driver_1 = __importStar(require("appium-android-driver"));
32
+ const driver_1 = require("appium/driver");
33
+ const support_1 = require("appium/support");
34
+ const asyncbox_1 = require("asyncbox");
35
+ const bluebird_1 = __importDefault(require("bluebird"));
36
+ const lodash_1 = __importDefault(require("lodash"));
37
+ const node_os_1 = __importDefault(require("node:os"));
38
+ const node_path_1 = __importDefault(require("node:path"));
39
+ const portscanner_1 = require("portscanner");
40
+ const constraints_1 = __importDefault(require("./constraints"));
41
+ const execute_method_map_1 = require("./execute-method-map");
42
+ const extensions_1 = require("./extensions");
43
+ const helpers_1 = __importDefault(require("./helpers"));
44
+ const method_map_1 = require("./method-map");
45
+ const uiautomator2_1 = require("./uiautomator2");
46
+ const helpers = { ...helpers_1.default, ...appium_android_driver_1.androidHelpers };
47
+ // The range of ports we can use on the system for communicating to the
48
+ // UiAutomator2 HTTP server on the device
26
49
  const DEVICE_PORT_RANGE = [8200, 8299];
27
- const DEVICE_PORT_ALLOCATION_GUARD = _support.util.getLockFileGuard(_path.default.resolve(_os.default.tmpdir(), 'uia2_device_port_guard'), {
28
- timeout: 25,
29
- tryRecovery: true
30
- });
50
+ // The guard is needed to avoid dynamic system port allocation conflicts for
51
+ // parallel driver sessions
52
+ const DEVICE_PORT_ALLOCATION_GUARD = support_1.util.getLockFileGuard(node_path_1.default.resolve(node_os_1.default.tmpdir(), 'uia2_device_port_guard'), { timeout: 25, tryRecovery: true });
53
+ // This is the port that UiAutomator2 listens to on the device. We will forward
54
+ // one of the ports above on the system to this port on the device.
31
55
  const DEVICE_PORT = 6790;
56
+ // This is the port that the UiAutomator2 MJPEG server listens to on the device.
57
+ // We will forward one of the ports above on the system to this port on the
58
+ // device.
32
59
  const MJPEG_SERVER_DEVICE_PORT = 7810;
33
60
  const LOCALHOST_IP4 = '127.0.0.1';
34
- const NO_PROXY = [['DELETE', new RegExp('^/session/[^/]+/actions')], ['GET', new RegExp('^/session/(?!.*/)')], ['GET', new RegExp('^/session/[^/]+/alert_[^/]+')], ['GET', new RegExp('^/session/[^/]+/alert/[^/]+')], ['GET', new RegExp('^/session/[^/]+/appium/[^/]+/current_activity')], ['GET', new RegExp('^/session/[^/]+/appium/[^/]+/current_package')], ['GET', new RegExp('^/session/[^/]+/appium/app/[^/]+')], ['GET', new RegExp('^/session/[^/]+/appium/device/[^/]+')], ['GET', new RegExp('^/session/[^/]+/appium/settings')], ['GET', new RegExp('^/session/[^/]+/context')], ['GET', new RegExp('^/session/[^/]+/contexts')], ['GET', new RegExp('^/session/[^/]+/element/[^/]+/attribute')], ['GET', new RegExp('^/session/[^/]+/element/[^/]+/displayed')], ['GET', new RegExp('^/session/[^/]+/element/[^/]+/enabled')], ['GET', new RegExp('^/session/[^/]+/element/[^/]+/location_in_view')], ['GET', new RegExp('^/session/[^/]+/element/[^/]+/name')], ['GET', new RegExp('^/session/[^/]+/element/[^/]+/screenshot')], ['GET', new RegExp('^/session/[^/]+/element/[^/]+/selected')], ['GET', new RegExp('^/session/[^/]+/ime/[^/]+')], ['GET', new RegExp('^/session/[^/]+/location')], ['GET', new RegExp('^/session/[^/]+/network_connection')], ['GET', new RegExp('^/session/[^/]+/screenshot')], ['GET', new RegExp('^/session/[^/]+/timeouts')], ['GET', new RegExp('^/session/[^/]+/url')], ['POST', new RegExp('^/session/[^/]+/[^/]+_alert$')], ['POST', new RegExp('^/session/[^/]+/actions')], ['POST', new RegExp('^/session/[^/]+/alert/[^/]+')], ['POST', new RegExp('^/session/[^/]+/app/[^/]')], ['POST', new RegExp('^/session/[^/]+/appium/[^/]+/start_activity')], ['POST', new RegExp('^/session/[^/]+/appium/app/[^/]+')], ['POST', new RegExp('^/session/[^/]+/appium/compare_images')], ['POST', new RegExp('^/session/[^/]+/appium/device/(?!set_clipboard)[^/]+')], ['POST', new RegExp('^/session/[^/]+/appium/element/[^/]+/replace_value')], ['POST', new RegExp('^/session/[^/]+/appium/element/[^/]+/value')], ['POST', new RegExp('^/session/[^/]+/appium/getPerformanceData')], ['POST', new RegExp('^/session/[^/]+/appium/performanceData/types')], ['POST', new RegExp('^/session/[^/]+/appium/settings')], ['POST', new RegExp('^/session/[^/]+/appium/execute_driver')], ['POST', new RegExp('^/session/[^/]+/appium/start_recording_screen')], ['POST', new RegExp('^/session/[^/]+/appium/stop_recording_screen')], ['POST', new RegExp('^/session/[^/]+/appium/.*event')], ['POST', new RegExp('^/session/[^/]+/context')], ['POST', new RegExp('^/session/[^/]+/element')], ['POST', new RegExp('^/session/[^/]+/ime/[^/]+')], ['POST', new RegExp('^/session/[^/]+/keys')], ['POST', new RegExp('^/session/[^/]+/location')], ['POST', new RegExp('^/session/[^/]+/network_connection')], ['POST', new RegExp('^/session/[^/]+/timeouts')], ['POST', new RegExp('^/session/[^/]+/touch/multi/perform')], ['POST', new RegExp('^/session/[^/]+/touch/perform')], ['POST', new RegExp('^/session/[^/]+/url')], ['GET', new RegExp('^/session/[^/]+/log/types')], ['POST', new RegExp('^/session/[^/]+/execute')], ['POST', new RegExp('^/session/[^/]+/execute_async')], ['POST', new RegExp('^/session/[^/]+/log')], ['GET', new RegExp('^/session/[^/]+/se/log/types')], ['GET', new RegExp('^/session/[^/]+/window/rect')], ['POST', new RegExp('^/session/[^/]+/execute/async')], ['POST', new RegExp('^/session/[^/]+/execute/sync')], ['POST', new RegExp('^/session/[^/]+/se/log')]];
35
- const CHROME_NO_PROXY = [['GET', new RegExp('^/session/[^/]+/appium')], ['GET', new RegExp('^/session/[^/]+/context')], ['GET', new RegExp('^/session/[^/]+/element/[^/]+/rect')], ['GET', new RegExp('^/session/[^/]+/orientation')], ['POST', new RegExp('^/session/[^/]+/appium')], ['POST', new RegExp('^/session/[^/]+/context')], ['POST', new RegExp('^/session/[^/]+/orientation')], ['POST', new RegExp('^/session/[^/]+/touch/multi/perform')], ['POST', new RegExp('^/session/[^/]+/touch/perform')], ['POST', new RegExp('^/session/[^/]+/execute$')], ['POST', new RegExp('^/session/[^/]+/execute/sync')], ['GET', new RegExp('^/session/[^/]+/log/types$')], ['POST', new RegExp('^/session/[^/]+/log$')], ['GET', new RegExp('^/session/[^/]+/se/log/types$')], ['POST', new RegExp('^/session/[^/]+/se/log$')]];
61
+ // NO_PROXY contains the paths that we never want to proxy to UiAutomator2 server.
62
+ // TODO: Add the list of paths that we never want to proxy to UiAutomator2 server.
63
+ // TODO: Need to segregate the paths better way using regular expressions wherever applicable.
64
+ // (Not segregating right away because more paths to be added in the NO_PROXY list)
65
+ const NO_PROXY = [
66
+ ['DELETE', new RegExp('^/session/[^/]+/actions')],
67
+ ['GET', new RegExp('^/session/(?!.*/)')],
68
+ ['GET', new RegExp('^/session/[^/]+/alert_[^/]+')],
69
+ ['GET', new RegExp('^/session/[^/]+/alert/[^/]+')],
70
+ ['GET', new RegExp('^/session/[^/]+/appium/[^/]+/current_activity')],
71
+ ['GET', new RegExp('^/session/[^/]+/appium/[^/]+/current_package')],
72
+ ['GET', new RegExp('^/session/[^/]+/appium/app/[^/]+')],
73
+ ['GET', new RegExp('^/session/[^/]+/appium/device/[^/]+')],
74
+ ['GET', new RegExp('^/session/[^/]+/appium/settings')],
75
+ ['GET', new RegExp('^/session/[^/]+/context')],
76
+ ['GET', new RegExp('^/session/[^/]+/contexts')],
77
+ ['GET', new RegExp('^/session/[^/]+/element/[^/]+/attribute')],
78
+ ['GET', new RegExp('^/session/[^/]+/element/[^/]+/displayed')],
79
+ ['GET', new RegExp('^/session/[^/]+/element/[^/]+/enabled')],
80
+ ['GET', new RegExp('^/session/[^/]+/element/[^/]+/location_in_view')],
81
+ ['GET', new RegExp('^/session/[^/]+/element/[^/]+/name')],
82
+ ['GET', new RegExp('^/session/[^/]+/element/[^/]+/screenshot')],
83
+ ['GET', new RegExp('^/session/[^/]+/element/[^/]+/selected')],
84
+ ['GET', new RegExp('^/session/[^/]+/ime/[^/]+')],
85
+ ['GET', new RegExp('^/session/[^/]+/location')],
86
+ ['GET', new RegExp('^/session/[^/]+/network_connection')],
87
+ ['GET', new RegExp('^/session/[^/]+/screenshot')],
88
+ ['GET', new RegExp('^/session/[^/]+/timeouts')],
89
+ ['GET', new RegExp('^/session/[^/]+/url')],
90
+ ['POST', new RegExp('^/session/[^/]+/[^/]+_alert$')],
91
+ ['POST', new RegExp('^/session/[^/]+/actions')],
92
+ ['POST', new RegExp('^/session/[^/]+/alert/[^/]+')],
93
+ ['POST', new RegExp('^/session/[^/]+/app/[^/]')],
94
+ ['POST', new RegExp('^/session/[^/]+/appium/[^/]+/start_activity')],
95
+ ['POST', new RegExp('^/session/[^/]+/appium/app/[^/]+')],
96
+ ['POST', new RegExp('^/session/[^/]+/appium/compare_images')],
97
+ ['POST', new RegExp('^/session/[^/]+/appium/device/(?!set_clipboard)[^/]+')],
98
+ ['POST', new RegExp('^/session/[^/]+/appium/element/[^/]+/replace_value')],
99
+ ['POST', new RegExp('^/session/[^/]+/appium/element/[^/]+/value')],
100
+ ['POST', new RegExp('^/session/[^/]+/appium/getPerformanceData')],
101
+ ['POST', new RegExp('^/session/[^/]+/appium/performanceData/types')],
102
+ ['POST', new RegExp('^/session/[^/]+/appium/settings')],
103
+ ['POST', new RegExp('^/session/[^/]+/appium/execute_driver')],
104
+ ['POST', new RegExp('^/session/[^/]+/appium/start_recording_screen')],
105
+ ['POST', new RegExp('^/session/[^/]+/appium/stop_recording_screen')],
106
+ ['POST', new RegExp('^/session/[^/]+/appium/.*event')],
107
+ ['POST', new RegExp('^/session/[^/]+/context')],
108
+ ['POST', new RegExp('^/session/[^/]+/element')],
109
+ ['POST', new RegExp('^/session/[^/]+/ime/[^/]+')],
110
+ ['POST', new RegExp('^/session/[^/]+/keys')],
111
+ ['POST', new RegExp('^/session/[^/]+/location')],
112
+ ['POST', new RegExp('^/session/[^/]+/network_connection')],
113
+ ['POST', new RegExp('^/session/[^/]+/timeouts')],
114
+ ['POST', new RegExp('^/session/[^/]+/touch/multi/perform')],
115
+ ['POST', new RegExp('^/session/[^/]+/touch/perform')],
116
+ ['POST', new RegExp('^/session/[^/]+/url')],
117
+ // MJSONWP commands
118
+ ['GET', new RegExp('^/session/[^/]+/log/types')],
119
+ ['POST', new RegExp('^/session/[^/]+/execute')],
120
+ ['POST', new RegExp('^/session/[^/]+/execute_async')],
121
+ ['POST', new RegExp('^/session/[^/]+/log')],
122
+ // W3C commands
123
+ // For Selenium v4 (W3C does not have this route)
124
+ ['GET', new RegExp('^/session/[^/]+/se/log/types')],
125
+ ['GET', new RegExp('^/session/[^/]+/window/rect')],
126
+ ['POST', new RegExp('^/session/[^/]+/execute/async')],
127
+ ['POST', new RegExp('^/session/[^/]+/execute/sync')],
128
+ // For Selenium v4 (W3C does not have this route)
129
+ ['POST', new RegExp('^/session/[^/]+/se/log')],
130
+ ];
131
+ // This is a set of methods and paths that we never want to proxy to Chromedriver.
132
+ const CHROME_NO_PROXY = [
133
+ ['GET', new RegExp('^/session/[^/]+/appium')],
134
+ ['GET', new RegExp('^/session/[^/]+/context')],
135
+ ['GET', new RegExp('^/session/[^/]+/element/[^/]+/rect')],
136
+ ['GET', new RegExp('^/session/[^/]+/orientation')],
137
+ ['POST', new RegExp('^/session/[^/]+/appium')],
138
+ ['POST', new RegExp('^/session/[^/]+/context')],
139
+ ['POST', new RegExp('^/session/[^/]+/orientation')],
140
+ ['POST', new RegExp('^/session/[^/]+/touch/multi/perform')],
141
+ ['POST', new RegExp('^/session/[^/]+/touch/perform')],
142
+ // this is needed to make the mobile: commands working in web context
143
+ ['POST', new RegExp('^/session/[^/]+/execute$')],
144
+ ['POST', new RegExp('^/session/[^/]+/execute/sync')],
145
+ // MJSONWP commands
146
+ ['GET', new RegExp('^/session/[^/]+/log/types$')],
147
+ ['POST', new RegExp('^/session/[^/]+/log$')],
148
+ // W3C commands
149
+ // For Selenium v4 (W3C does not have this route)
150
+ ['GET', new RegExp('^/session/[^/]+/se/log/types$')],
151
+ // For Selenium v4 (W3C does not have this route)
152
+ ['POST', new RegExp('^/session/[^/]+/se/log$')],
153
+ ];
36
154
  const MEMOIZED_FUNCTIONS = ['getStatusBarHeight', 'getDevicePixelRatio'];
37
- class AndroidUiautomator2Driver extends _driver.BaseDriver {
38
- static newMethodMap = _methodMap.newMethodMap;
39
- constructor(opts = {}, shouldValidateCaps = true) {
40
- delete opts.shell;
41
- super(opts, shouldValidateCaps);
42
- this.locatorStrategies = ['xpath', 'id', 'class name', 'accessibility id', 'css selector', '-android uiautomator'];
43
- this.desiredCapConstraints = _desiredCaps.default;
44
- this.uiautomator2 = null;
45
- this.jwpProxyActive = false;
46
- this.jwpProxyAvoid = NO_PROXY;
47
- this.apkStrings = {};
48
- this.settings = new _driver.DeviceSettings({
49
- ignoreUnimportantViews: false,
50
- allowInvisibleElements: false
51
- }, this.onSettingsUpdate.bind(this));
52
- this.chromedriver = null;
53
- this.sessionChromedrivers = {};
54
- for (const fn of MEMOIZED_FUNCTIONS) {
55
- this[fn] = _lodash.default.memoize(this[fn]);
56
- }
57
- }
58
- validateDesiredCaps(caps) {
59
- return super.validateDesiredCaps(caps) && _appiumAndroidDriver.androidHelpers.validateDesiredCaps(caps);
60
- }
61
- async createSession(...args) {
62
- try {
63
- let [sessionId, caps] = await super.createSession(...args);
64
- let serverDetails = {
65
- platform: 'LINUX',
66
- webStorageEnabled: false,
67
- takesScreenshot: true,
68
- javascriptEnabled: true,
69
- databaseEnabled: false,
70
- networkConnectionEnabled: true,
71
- locationContextEnabled: false,
72
- warnings: {},
73
- desired: this.caps
74
- };
75
- this.caps = Object.assign(serverDetails, this.caps);
76
- this.curContext = this.defaultContextName();
77
- let defaultOpts = {
78
- fullReset: false,
79
- autoLaunch: true,
80
- adbPort: _appiumAdb.DEFAULT_ADB_PORT,
81
- androidInstallTimeout: 90000
82
- };
83
- _lodash.default.defaults(this.opts, defaultOpts);
84
- if (this.isChromeSession) {
85
- this.log.info("We're going to run a Chrome-based session");
86
- let {
87
- pkg,
88
- activity
89
- } = helpers.getChromePkg(this.opts.browserName);
90
- this.opts.appPackage = this.caps.appPackage = pkg;
91
- this.opts.appActivity = this.caps.appActivity = activity;
92
- this.log.info(`Chrome-type package and activity are ${pkg} and ${activity}`);
93
- }
94
- if (this.opts.reboot) {
95
- this.setAvdFromCapabilities(caps);
96
- }
97
- if (this.opts.app) {
98
- this.opts.app = await this.helpers.configureApp(this.opts.app, [_extensions.APK_EXTENSION, _extensions.APKS_EXTENSION]);
99
- await this.checkAppPresent();
100
- } else if (this.opts.appPackage) {
101
- this.log.info(`Starting '${this.opts.appPackage}' directly on the device`);
102
- } else {
103
- this.log.info(`Neither 'app' nor 'appPackage' was set. Starting UiAutomator2 ` + 'without the target application');
104
- }
105
- this.opts.adbPort = this.opts.adbPort || _appiumAdb.DEFAULT_ADB_PORT;
106
- await this.startUiAutomator2Session();
107
- await this.fillDeviceDetails();
108
- if (this.opts.mjpegScreenshotUrl) {
109
- this.log.info(`Starting MJPEG stream reading URL: '${this.opts.mjpegScreenshotUrl}'`);
110
- this.mjpegStream = new _support.mjpeg.MJpegStream(this.opts.mjpegScreenshotUrl);
111
- await this.mjpegStream.start();
112
- }
113
- return [sessionId, this.caps];
114
- } catch (e) {
115
- await this.deleteSession();
116
- throw e;
117
- }
118
- }
119
- async fillDeviceDetails() {
120
- this.caps.pixelRatio = await this.getDevicePixelRatio();
121
- this.caps.statBarHeight = await this.getStatusBarHeight();
122
- this.caps.viewportRect = await this.getViewPortRect();
123
- }
124
- get driverData() {
125
- return {};
126
- }
127
- async getSession() {
128
- let sessionData = await super.getSession();
129
- this.log.debug('Getting session details from server to mix in');
130
- let uia2Data = await this.uiautomator2.jwproxy.command('/', 'GET', {});
131
- return Object.assign({}, sessionData, uia2Data);
132
- }
133
- isEmulator() {
134
- return helpers.isEmulator(this.adb, this.opts);
135
- }
136
- setAvdFromCapabilities(caps) {
137
- if (this.opts.avd) {
138
- this.log.info('avd name defined, ignoring device name and platform version');
139
- } else {
140
- if (!caps.deviceName) {
141
- this.log.errorAndThrow('avd or deviceName should be specified when reboot option is enables');
142
- }
143
- if (!caps.platformVersion) {
144
- this.log.errorAndThrow('avd or platformVersion should be specified when reboot option is enabled');
145
- }
146
- let avdDevice = caps.deviceName.replace(/[^a-zA-Z0-9_.]/g, '-');
147
- this.opts.avd = `${avdDevice}__${caps.platformVersion}`;
155
+ class AndroidUiautomator2Driver extends appium_android_driver_1.default {
156
+ constructor(opts = {}, shouldValidateCaps = true) {
157
+ // `shell` overwrites adb.shell, so remove
158
+ // @ts-expect-error FIXME: what is this?
159
+ delete opts.shell;
160
+ super(opts, shouldValidateCaps);
161
+ this.locatorStrategies = [
162
+ 'xpath',
163
+ 'id',
164
+ 'class name',
165
+ 'accessibility id',
166
+ 'css selector',
167
+ '-android uiautomator',
168
+ ];
169
+ this.desiredCapConstraints = lodash_1.default.cloneDeep(constraints_1.default);
170
+ this.jwpProxyActive = false;
171
+ this.jwpProxyAvoid = NO_PROXY;
172
+ this.apkStrings = {}; // map of language -> strings obj
173
+ this.settings = new driver_1.DeviceSettings({ ignoreUnimportantViews: false, allowInvisibleElements: false }, this.onSettingsUpdate.bind(this));
174
+ // handle webview mechanics from AndroidDriver
175
+ this.sessionChromedrivers = {};
176
+ this.caps = {};
177
+ this.opts = opts;
178
+ // memoize functions here, so that they are done on a per-instance basis
179
+ for (const fn of MEMOIZED_FUNCTIONS) {
180
+ this[fn] = lodash_1.default.memoize(this[fn]);
181
+ }
148
182
  }
149
- }
150
- async allocateSystemPort() {
151
- const forwardPort = async localPort => {
152
- this.log.debug(`Forwarding UiAutomator2 Server port ${DEVICE_PORT} to local port ${localPort}`);
153
- if ((await (0, _portscanner.checkPortStatus)(localPort, LOCALHOST_IP4)) === 'open') {
154
- this.log.errorAndThrow(`UiAutomator2 Server cannot start because the local port #${localPort} is busy. ` + `Make sure the port you provide via 'systemPort' capability is not occupied. ` + `This situation might often be a result of an inaccurate sessions management, e.g. ` + `old automation sessions on the same device must always be closed before starting new ones.`);
155
- }
156
- await this.adb.forwardPort(localPort, DEVICE_PORT);
157
- };
158
- if (this.opts.systemPort) {
159
- this._hasSystemPortInCaps = true;
160
- return await forwardPort(this.opts.systemPort);
183
+ validateDesiredCaps(caps) {
184
+ return (driver_1.BaseDriver.prototype.validateDesiredCaps.call(this, caps) &&
185
+ appium_android_driver_1.androidHelpers.validateDesiredCaps(caps));
161
186
  }
162
- await DEVICE_PORT_ALLOCATION_GUARD(async () => {
163
- const [startPort, endPort] = DEVICE_PORT_RANGE;
164
- try {
165
- this.opts.systemPort = await (0, _portscanner.findAPortNotInUse)(startPort, endPort);
166
- } catch (e) {
167
- this.log.errorAndThrow(`Cannot find any free port in range ${startPort}..${endPort}}. ` + `Please set the available port number by providing the systemPort capability or ` + `double check the processes that are locking ports within this range and terminate ` + `these which are not needed anymore`);
168
- }
169
- await forwardPort(this.opts.systemPort);
170
- });
171
- }
172
- async releaseSystemPort() {
173
- if (!this.opts.systemPort || !this.adb) {
174
- return;
187
+ async createSession(w3cCaps1, w3cCaps2, w3cCaps3, driverData) {
188
+ try {
189
+ // TODO handle otherSessionData for multiple sessions
190
+ const [sessionId, caps] = (await driver_1.BaseDriver.prototype.createSession.call(this, w3cCaps1, w3cCaps2, w3cCaps3, driverData));
191
+ const startSessionOpts = {
192
+ ...caps,
193
+ platform: 'LINUX',
194
+ webStorageEnabled: false,
195
+ takesScreenshot: true,
196
+ javascriptEnabled: true,
197
+ databaseEnabled: false,
198
+ networkConnectionEnabled: true,
199
+ locationContextEnabled: false,
200
+ warnings: {},
201
+ desired: caps,
202
+ };
203
+ const defaultOpts = {
204
+ fullReset: false,
205
+ autoLaunch: true,
206
+ adbPort: appium_adb_1.DEFAULT_ADB_PORT,
207
+ androidInstallTimeout: 90000,
208
+ };
209
+ lodash_1.default.defaults(this.opts, defaultOpts);
210
+ if (this.isChromeSession) {
211
+ this.log.info("We're going to run a Chrome-based session");
212
+ const { pkg, activity } = helpers.getChromePkg(this.opts.browserName);
213
+ this.opts.appPackage = this.caps.appPackage = pkg;
214
+ this.opts.appActivity = this.caps.appActivity = activity;
215
+ this.log.info(`Chrome-type package and activity are ${pkg} and ${activity}`);
216
+ }
217
+ // @ts-expect-error FIXME: missing CLI option?
218
+ if (this.opts.reboot) {
219
+ this.setAvdFromCapabilities(startSessionOpts);
220
+ }
221
+ if (this.opts.app) {
222
+ // find and copy, or download and unzip an app url or path
223
+ this.opts.app = await this.helpers.configureApp(this.opts.app, [
224
+ extensions_1.APK_EXTENSION,
225
+ extensions_1.APKS_EXTENSION,
226
+ ]);
227
+ await this.checkAppPresent();
228
+ }
229
+ else if (this.opts.appPackage) {
230
+ // the app isn't an actual app file but rather something we want to
231
+ // assume is on the device and just launch via the appPackage
232
+ this.log.info(`Starting '${this.opts.appPackage}' directly on the device`);
233
+ }
234
+ else {
235
+ this.log.info(`Neither 'app' nor 'appPackage' was set. Starting UiAutomator2 ` +
236
+ 'without the target application');
237
+ }
238
+ this.opts.adbPort = this.opts.adbPort || appium_adb_1.DEFAULT_ADB_PORT;
239
+ const result = await this.startUiAutomator2Session(startSessionOpts);
240
+ if (this.opts.mjpegScreenshotUrl) {
241
+ this.log.info(`Starting MJPEG stream reading URL: '${this.opts.mjpegScreenshotUrl}'`);
242
+ this.mjpegStream = new support_1.mjpeg.MJpegStream(this.opts.mjpegScreenshotUrl);
243
+ await this.mjpegStream.start();
244
+ }
245
+ return [sessionId, result];
246
+ }
247
+ catch (e) {
248
+ await this.deleteSession();
249
+ throw e;
250
+ }
175
251
  }
176
- if (this._hasSystemPortInCaps) {
177
- await this.adb.removePortForward(this.opts.systemPort);
178
- } else {
179
- await DEVICE_PORT_ALLOCATION_GUARD(async () => await this.adb.removePortForward(this.opts.systemPort));
252
+ async getDeviceDetails() {
253
+ const [pixelRatio, statBarHeight, viewportRect] = await bluebird_1.default.all([
254
+ this.getDevicePixelRatio(),
255
+ this.getStatusBarHeight(),
256
+ this.getViewPortRect(),
257
+ ]);
258
+ return { pixelRatio, statBarHeight, viewportRect };
180
259
  }
181
- }
182
- async allocateMjpegServerPort() {
183
- if (this.opts.mjpegServerPort) {
184
- this.log.debug(`MJPEG broadcasting requested, forwarding MJPEG server port ${MJPEG_SERVER_DEVICE_PORT} ` + `to local port ${this.opts.mjpegServerPort}`);
185
- await this.adb.forwardPort(this.opts.mjpegServerPort, MJPEG_SERVER_DEVICE_PORT);
260
+ get driverData() {
261
+ // TODO fill out resource info here
262
+ return {};
186
263
  }
187
- }
188
- async releaseMjpegServerPort() {
189
- if (this.opts.mjpegServerPort) {
190
- await this.adb.removePortForward(this.opts.mjpegServerPort);
264
+ async getSession() {
265
+ const sessionData = await driver_1.BaseDriver.prototype.getSession.call(this);
266
+ this.log.debug('Getting session details from server to mix in');
267
+ const uia2Data = (await this.uiautomator2.jwproxy.command('/', 'GET', {}));
268
+ return { ...sessionData, ...uia2Data };
191
269
  }
192
- }
193
- async startUiAutomator2Session() {
194
- let {
195
- udid,
196
- emPort
197
- } = await helpers.getDeviceInfoFromCaps(this.opts);
198
- this.opts.udid = udid;
199
- this.opts.emPort = emPort;
200
- this.adb = await _appiumAndroidDriver.androidHelpers.createADB(this.opts);
201
- const apiLevel = await this.adb.getApiLevel();
202
- if (apiLevel < 21) {
203
- this.log.errorAndThrow('UIAutomator2 is only supported since Android 5.0 (Lollipop). ' + 'You could still use other supported backends in order to automate older Android versions.');
270
+ setAvdFromCapabilities(caps) {
271
+ if (this.opts.avd) {
272
+ this.log.info('avd name defined, ignoring device name and platform version');
273
+ }
274
+ else {
275
+ if (!caps.deviceName) {
276
+ this.log.errorAndThrow('avd or deviceName should be specified when reboot option is enables');
277
+ throw new Error(); // unreachable
278
+ }
279
+ if (!caps.platformVersion) {
280
+ this.log.errorAndThrow('avd or platformVersion should be specified when reboot option is enabled');
281
+ throw new Error(); // unreachable
282
+ }
283
+ const avdDevice = caps.deviceName.replace(/[^a-zA-Z0-9_.]/g, '-');
284
+ this.opts.avd = `${avdDevice}__${caps.platformVersion}`;
285
+ }
204
286
  }
205
- if (apiLevel >= 28) {
206
- this.log.info('Relaxing hidden api policy');
207
- await this.adb.setHiddenApiPolicy('1', !!this.opts.ignoreHiddenApiPolicyError);
287
+ async allocateSystemPort() {
288
+ const forwardPort = async (localPort) => {
289
+ this.log.debug(`Forwarding UiAutomator2 Server port ${DEVICE_PORT} to local port ${localPort}`);
290
+ if ((await (0, portscanner_1.checkPortStatus)(localPort, LOCALHOST_IP4)) === 'open') {
291
+ this.log.errorAndThrow(`UiAutomator2 Server cannot start because the local port #${localPort} is busy. ` +
292
+ `Make sure the port you provide via 'systemPort' capability is not occupied. ` +
293
+ `This situation might often be a result of an inaccurate sessions management, e.g. ` +
294
+ `old automation sessions on the same device must always be closed before starting new ones.`);
295
+ }
296
+ await this.adb.forwardPort(localPort, DEVICE_PORT);
297
+ };
298
+ if (this.systemPort) {
299
+ this._hasSystemPortInCaps = true;
300
+ return await forwardPort(this.systemPort);
301
+ }
302
+ await DEVICE_PORT_ALLOCATION_GUARD(async () => {
303
+ const [startPort, endPort] = DEVICE_PORT_RANGE;
304
+ try {
305
+ this.systemPort = await (0, portscanner_1.findAPortNotInUse)(startPort, endPort);
306
+ }
307
+ catch (e) {
308
+ this.log.errorAndThrow(`Cannot find any free port in range ${startPort}..${endPort}}. ` +
309
+ `Please set the available port number by providing the systemPort capability or ` +
310
+ `double check the processes that are locking ports within this range and terminate ` +
311
+ `these which are not needed anymore`);
312
+ throw new Error(); // unreachable
313
+ }
314
+ await forwardPort(this.systemPort);
315
+ });
208
316
  }
209
- if (_support.util.hasValue(this.opts.gpsEnabled)) {
210
- if (this.isEmulator()) {
211
- this.log.info(`Trying to ${this.opts.gpsEnabled ? 'enable' : 'disable'} gps location provider`);
212
- await this.adb.toggleGPSLocationProvider(this.opts.gpsEnabled);
213
- } else {
214
- this.log.warn(`Sorry! 'gpsEnabled' capability is only available for emulators`);
215
- }
317
+ async releaseSystemPort() {
318
+ if (!this.systemPort || !this.adb) {
319
+ return;
320
+ }
321
+ if (this._hasSystemPortInCaps) {
322
+ await this.adb.removePortForward(this.systemPort);
323
+ }
324
+ else {
325
+ await DEVICE_PORT_ALLOCATION_GUARD(async () => await this.adb.removePortForward(this.systemPort));
326
+ }
216
327
  }
217
- const appInfo = await helpers.getLaunchInfo(this.adb, this.opts);
218
- Object.assign(this.opts, appInfo || {});
219
- this.caps.deviceName = this.adb.curDeviceId;
220
- this.caps.deviceUDID = this.opts.udid;
221
- await helpers.initDevice(this.adb, this.opts);
222
- await this.allocateSystemPort();
223
- await this.allocateMjpegServerPort();
224
- await this.initUiAutomator2Server();
225
- if (this.opts.disableWindowAnimation && (await this.adb.getApiLevel()) < 26) {
226
- if (await this.adb.isAnimationOn()) {
227
- this.log.info('Disabling animation via io.appium.settings');
228
- await this.adb.setAnimationState(false);
229
- this._wasWindowAnimationDisabled = true;
230
- } else {
231
- this.log.info('Window animation is already disabled');
232
- }
328
+ async allocateMjpegServerPort() {
329
+ if (this.opts.mjpegServerPort) {
330
+ this.log.debug(`MJPEG broadcasting requested, forwarding MJPEG server port ${MJPEG_SERVER_DEVICE_PORT} ` +
331
+ `to local port ${this.opts.mjpegServerPort}`);
332
+ await this.adb.forwardPort(this.opts.mjpegServerPort, MJPEG_SERVER_DEVICE_PORT);
333
+ }
233
334
  }
234
- await this.initAUT();
235
- if (!this.caps.appPackage && appInfo) {
236
- this.caps.appPackage = appInfo.appPackage;
335
+ async releaseMjpegServerPort() {
336
+ if (this.opts.mjpegServerPort) {
337
+ await this.adb.removePortForward(this.opts.mjpegServerPort);
338
+ }
237
339
  }
238
- await this.uiautomator2.startSession(this.caps);
239
- await this.addDeviceInfoToCaps();
240
- if (!this.opts.skipUnlock) {
241
- await helpers.unlock(this, this.adb, this.caps);
242
- } else {
243
- this.log.debug(`'skipUnlock' capability set, so skipping device unlock`);
340
+ async startUiAutomator2Session(caps) {
341
+ // get device udid for this session
342
+ const { udid, emPort } = await helpers.getDeviceInfoFromCaps(this.opts);
343
+ this.opts.udid = udid;
344
+ // @ts-expect-error do not put random stuff on opts
345
+ this.opts.emPort = emPort;
346
+ // now that we know our java version and device info, we can create our
347
+ // ADB instance
348
+ this.adb = await appium_android_driver_1.androidHelpers.createADB(this.opts);
349
+ const apiLevel = await this.adb.getApiLevel();
350
+ if (apiLevel < 21) {
351
+ this.log.errorAndThrow('UIAutomator2 is only supported since Android 5.0 (Lollipop). ' +
352
+ 'You could still use other supported backends in order to automate older Android versions.');
353
+ }
354
+ if (apiLevel >= 28) {
355
+ // Android P
356
+ this.log.info('Relaxing hidden api policy');
357
+ await this.adb.setHiddenApiPolicy('1', !!this.opts.ignoreHiddenApiPolicyError);
358
+ }
359
+ // check if we have to enable/disable gps before running the application
360
+ if (support_1.util.hasValue(this.opts.gpsEnabled)) {
361
+ if (this.isEmulator()) {
362
+ this.log.info(`Trying to ${this.opts.gpsEnabled ? 'enable' : 'disable'} gps location provider`);
363
+ await this.adb.toggleGPSLocationProvider(this.opts.gpsEnabled);
364
+ }
365
+ else {
366
+ this.log.warn(`Sorry! 'gpsEnabled' capability is only available for emulators`);
367
+ }
368
+ }
369
+ // get appPackage et al from manifest if necessary
370
+ const appInfo = await helpers.getLaunchInfo(this.adb, this.opts);
371
+ // and get it onto our 'opts' object so we use it from now on
372
+ this.opts = { ...this.opts, ...(appInfo ?? {}) };
373
+ // set actual device name, udid, platform version, screen size, screen density, model and manufacturer details
374
+ const sessionInfo = {
375
+ deviceName: this.adb.curDeviceId,
376
+ deviceUDID: this.opts.udid,
377
+ };
378
+ const capsWithSessionInfo = {
379
+ ...caps,
380
+ ...sessionInfo,
381
+ };
382
+ // start an avd, set the language/locale, pick an emulator, etc...
383
+ // TODO with multiple devices we'll need to parameterize this
384
+ await helpers.initDevice(this.adb, this.opts);
385
+ // Prepare the device by forwarding the UiAutomator2 port
386
+ // This call mutates this.systemPort if it is not set explicitly
387
+ await this.allocateSystemPort();
388
+ // Prepare the device by forwarding the UiAutomator2 MJPEG server port (if
389
+ // applicable)
390
+ await this.allocateMjpegServerPort();
391
+ // set up the modified UiAutomator2 server etc
392
+ const uiautomator2 = await this.initUiAutomator2Server();
393
+ // Should be after installing io.appium.settings in helpers.initDevice
394
+ if (this.opts.disableWindowAnimation && (await this.adb.getApiLevel()) < 26) {
395
+ // API level 26 is Android 8.0.
396
+ // Granting android.permission.SET_ANIMATION_SCALE is necessary to handle animations under API level 26
397
+ // Read https://github.com/appium/appium/pull/11640#issuecomment-438260477
398
+ // `--no-window-animation` works over Android 8 to disable all of animations
399
+ if (await this.adb.isAnimationOn()) {
400
+ this.log.info('Disabling animation via io.appium.settings');
401
+ await this.adb.setAnimationState(false);
402
+ this._wasWindowAnimationDisabled = true;
403
+ }
404
+ else {
405
+ this.log.info('Window animation is already disabled');
406
+ }
407
+ }
408
+ // set up app under test
409
+ // prepare our actual AUT, get it on the device, etc...
410
+ await this.initAUT();
411
+ // Adding AUT package name in the capabilities if package name not exist in caps
412
+ if (!capsWithSessionInfo.appPackage && appInfo) {
413
+ capsWithSessionInfo.appPackage = appInfo.appPackage;
414
+ }
415
+ // launch UiAutomator2 and wait till its online and we have a session
416
+ await uiautomator2.startSession(capsWithSessionInfo);
417
+ const capsWithSessionAndDeviceInfo = {
418
+ ...capsWithSessionInfo,
419
+ ...(await this.getDeviceInfoFromUia2()),
420
+ };
421
+ // Unlock the device after the session is started.
422
+ if (!this.opts.skipUnlock) {
423
+ // unlock the device to prepare it for testing
424
+ await helpers.unlock(this, this.adb, this.caps);
425
+ }
426
+ else {
427
+ this.log.debug(`'skipUnlock' capability set, so skipping device unlock`);
428
+ }
429
+ if (this.isChromeSession) {
430
+ // start a chromedriver session
431
+ await this.startChromeSession();
432
+ }
433
+ else if (this.opts.autoLaunch && this.opts.appPackage) {
434
+ await this.ensureAppStarts();
435
+ }
436
+ // if the initial orientation is requested, set it
437
+ if (support_1.util.hasValue(this.opts.orientation)) {
438
+ this.log.debug(`Setting initial orientation to '${this.opts.orientation}'`);
439
+ await this.setOrientation(this.opts.orientation);
440
+ }
441
+ // if we want to immediately get into a webview, set our context
442
+ // appropriately
443
+ if (this.opts.autoWebview) {
444
+ const viewName = this.defaultWebviewName();
445
+ const timeout = this.opts.autoWebviewTimeout || 2000;
446
+ this.log.info(`Setting auto webview to context '${viewName}' with timeout ${timeout}ms`);
447
+ await (0, asyncbox_1.retryInterval)(timeout / 500, 500, this.setContext.bind(this), viewName);
448
+ }
449
+ // now that everything has started successfully, turn on proxying so all
450
+ // subsequent session requests go straight to/from uiautomator2
451
+ this.jwpProxyActive = true;
452
+ return { ...capsWithSessionAndDeviceInfo, ...(await this.getDeviceDetails()) };
244
453
  }
245
- if (this.isChromeSession) {
246
- await this.startChromeSession(this);
247
- } else if (this.opts.autoLaunch && this.opts.appPackage) {
248
- await this.ensureAppStarts();
454
+ async getDeviceInfoFromUia2() {
455
+ const { apiVersion, platformVersion, manufacturer, model, realDisplaySize, displayDensity } = await this.mobileGetDeviceInfo();
456
+ return {
457
+ deviceApiLevel: lodash_1.default.parseInt(apiVersion),
458
+ platformVersion,
459
+ deviceManufacturer: manufacturer,
460
+ deviceModel: model,
461
+ deviceScreenSize: realDisplaySize,
462
+ deviceScreenDensity: displayDensity,
463
+ };
249
464
  }
250
- if (_support.util.hasValue(this.opts.orientation)) {
251
- this.log.debug(`Setting initial orientation to '${this.opts.orientation}'`);
252
- await this.setOrientation(this.opts.orientation);
465
+ async initUiAutomator2Server() {
466
+ // broken out for readability
467
+ const uiautomator2Opts = {
468
+ // @ts-expect-error FIXME: maybe `address` instead of `host`?
469
+ host: this.opts.remoteAdbHost || this.opts.host || LOCALHOST_IP4,
470
+ systemPort: this.systemPort,
471
+ devicePort: DEVICE_PORT,
472
+ adb: this.adb,
473
+ apk: this.opts.app,
474
+ tmpDir: this.opts.tmpDir,
475
+ appPackage: this.opts.appPackage,
476
+ appActivity: this.opts.appActivity,
477
+ disableWindowAnimation: !!this.opts.disableWindowAnimation,
478
+ disableSuppressAccessibilityService: this.opts.disableSuppressAccessibilityService,
479
+ readTimeout: this.opts.uiautomator2ServerReadTimeout,
480
+ };
481
+ // now that we have package and activity, we can create an instance of
482
+ // uiautomator2 with the appropriate options
483
+ this.uiautomator2 = new uiautomator2_1.UiAutomator2Server(this.log, uiautomator2Opts);
484
+ this.proxyReqRes = this.uiautomator2.proxyReqRes.bind(this.uiautomator2);
485
+ this.proxyCommand = this.uiautomator2.proxyCommand.bind(this.uiautomator2);
486
+ if (this.opts.skipServerInstallation) {
487
+ this.log.info(`'skipServerInstallation' is set. Skipping UIAutomator2 server installation.`);
488
+ }
489
+ else {
490
+ await this.uiautomator2.installServerApk(this.opts.uiautomator2ServerInstallTimeout);
491
+ try {
492
+ await this.adb.addToDeviceIdleWhitelist(appium_android_driver_1.SETTINGS_HELPER_PKG_ID, uiautomator2_1.SERVER_PACKAGE_ID, uiautomator2_1.SERVER_TEST_PACKAGE_ID);
493
+ }
494
+ catch (e) {
495
+ const err = e;
496
+ this.log.warn(`Cannot add server packages to the Doze whitelist. Original error: ` +
497
+ (err.stderr || err.message));
498
+ }
499
+ }
500
+ return this.uiautomator2;
253
501
  }
254
- if (this.opts.autoWebview) {
255
- const viewName = this.defaultWebviewName();
256
- const timeout = this.opts.autoWebviewTimeout || 2000;
257
- this.log.info(`Setting auto webview to context '${viewName}' with timeout ${timeout}ms`);
258
- await (0, _asyncbox.retryInterval)(timeout / 500, 500, this.setContext.bind(this), viewName);
502
+ async initAUT() {
503
+ // Uninstall any uninstallOtherPackages which were specified in caps
504
+ if (this.opts.uninstallOtherPackages) {
505
+ await helpers.uninstallOtherPackages(this.adb, helpers.parseArray(this.opts.uninstallOtherPackages), [appium_android_driver_1.SETTINGS_HELPER_PKG_ID, uiautomator2_1.SERVER_PACKAGE_ID, uiautomator2_1.SERVER_TEST_PACKAGE_ID]);
506
+ }
507
+ // Install any "otherApps" that were specified in caps
508
+ if (this.opts.otherApps) {
509
+ let otherApps;
510
+ try {
511
+ otherApps = helpers.parseArray(this.opts.otherApps);
512
+ }
513
+ catch (e) {
514
+ this.log.errorAndThrow(`Could not parse "otherApps" capability: ${e.message}`);
515
+ throw new Error(); // unrechable
516
+ }
517
+ otherApps = await bluebird_1.default.all(otherApps.map((app) => this.helpers.configureApp(app, [extensions_1.APK_EXTENSION, extensions_1.APKS_EXTENSION])));
518
+ await helpers.installOtherApks(otherApps, this.adb, this.opts);
519
+ }
520
+ if (this.opts.app) {
521
+ if ((this.opts.noReset && !(await this.adb.isAppInstalled(this.opts.appPackage))) ||
522
+ !this.opts.noReset) {
523
+ if (!this.opts.noSign &&
524
+ !(await this.adb.checkApkCert(this.opts.app, this.opts.appPackage, {
525
+ requireDefaultCert: false,
526
+ }))) {
527
+ await helpers.signApp(this.adb, this.opts.app);
528
+ }
529
+ if (!this.opts.skipUninstall) {
530
+ await this.adb.uninstallApk(this.opts.appPackage);
531
+ }
532
+ await helpers.installApk(this.adb, this.opts);
533
+ }
534
+ else {
535
+ this.log.debug('noReset has been requested and the app is already installed. Doing nothing');
536
+ }
537
+ }
538
+ else {
539
+ if (this.opts.fullReset) {
540
+ this.log.errorAndThrow('Full reset requires an app capability, use fastReset if app is not provided');
541
+ }
542
+ this.log.debug('No app capability. Assuming it is already on the device');
543
+ if (this.opts.fastReset && this.opts.appPackage) {
544
+ await helpers.resetApp(this.adb, this.opts);
545
+ }
546
+ }
259
547
  }
260
- this.jwpProxyActive = true;
261
- }
262
- async addDeviceInfoToCaps() {
263
- const {
264
- apiVersion,
265
- platformVersion,
266
- manufacturer,
267
- model,
268
- realDisplaySize,
269
- displayDensity
270
- } = await this.mobileGetDeviceInfo();
271
- this.caps.deviceApiLevel = parseInt(apiVersion, 10);
272
- this.caps.platformVersion = platformVersion;
273
- this.caps.deviceScreenSize = realDisplaySize;
274
- this.caps.deviceScreenDensity = displayDensity;
275
- this.caps.deviceModel = model;
276
- this.caps.deviceManufacturer = manufacturer;
277
- }
278
- async initUiAutomator2Server() {
279
- const uiautomator2Opts = {
280
- host: this.opts.remoteAdbHost || this.opts.host || LOCALHOST_IP4,
281
- systemPort: this.opts.systemPort,
282
- devicePort: DEVICE_PORT,
283
- adb: this.adb,
284
- apk: this.opts.app,
285
- tmpDir: this.opts.tmpDir,
286
- appPackage: this.opts.appPackage,
287
- appActivity: this.opts.appActivity,
288
- disableWindowAnimation: !!this.opts.disableWindowAnimation,
289
- disableSuppressAccessibilityService: this.opts.disableSuppressAccessibilityService,
290
- readTimeout: this.opts.uiautomator2ServerReadTimeout
291
- };
292
- this.uiautomator2 = new _uiautomator.UiAutomator2Server(this.log, uiautomator2Opts);
293
- this.proxyReqRes = this.uiautomator2.proxyReqRes.bind(this.uiautomator2);
294
- this.proxyCommand = this.uiautomator2.proxyCommand.bind(this.uiautomator2);
295
- if (this.opts.skipServerInstallation) {
296
- this.log.info(`'skipServerInstallation' is set. Skipping UIAutomator2 server installation.`);
297
- } else {
298
- await this.uiautomator2.installServerApk(this.opts.uiautomator2ServerInstallTimeout);
299
- try {
300
- await this.adb.addToDeviceIdleWhitelist(_appiumAndroidDriver.SETTINGS_HELPER_PKG_ID, _uiautomator.SERVER_PACKAGE_ID, _uiautomator.SERVER_TEST_PACKAGE_ID);
301
- } catch (e) {
302
- this.log.warn(`Cannot add server packages to the Doze whitelist. Original error: ` + (e.stderr || e.message));
303
- }
548
+ async ensureAppStarts() {
549
+ // make sure we have an activity and package to wait for
550
+ const appWaitPackage = this.opts.appWaitPackage || this.opts.appPackage;
551
+ const appWaitActivity = this.opts.appWaitActivity || this.opts.appActivity;
552
+ this.log.info(`Starting '${this.opts.appPackage}/${this.opts.appActivity} ` +
553
+ `and waiting for '${appWaitPackage}/${appWaitActivity}'`);
554
+ if (this.caps.androidCoverage) {
555
+ this.log.info(`androidCoverage is configured. ` +
556
+ ` Starting instrumentation of '${this.caps.androidCoverage}'...`);
557
+ await this.adb.androidCoverage(this.caps.androidCoverage, appWaitPackage, appWaitActivity);
558
+ return;
559
+ }
560
+ if (this.opts.noReset &&
561
+ !this.opts.forceAppLaunch &&
562
+ (await this.adb.processExists(this.opts.appPackage))) {
563
+ this.log.info(`'${this.opts.appPackage}' is already running and noReset is enabled. ` +
564
+ `Set forceAppLaunch capability to true if the app must be forcefully restarted on session startup.`);
565
+ return;
566
+ }
567
+ await this.adb.startApp({
568
+ pkg: this.opts.appPackage,
569
+ activity: this.opts.appActivity,
570
+ action: this.opts.intentAction || 'android.intent.action.MAIN',
571
+ category: this.opts.intentCategory || 'android.intent.category.LAUNCHER',
572
+ flags: this.opts.intentFlags || '0x10200000',
573
+ waitPkg: this.opts.appWaitPackage,
574
+ waitActivity: this.opts.appWaitActivity,
575
+ waitForLaunch: this.opts.appWaitForLaunch,
576
+ waitDuration: this.opts.appWaitDuration,
577
+ optionalIntentArguments: this.opts.optionalIntentArguments,
578
+ stopApp: this.opts.forceAppLaunch || !this.opts.dontStopAppOnReset,
579
+ retry: true,
580
+ user: this.opts.userProfile,
581
+ });
304
582
  }
305
- }
306
- async initAUT() {
307
- if (this.opts.uninstallOtherPackages) {
308
- await helpers.uninstallOtherPackages(this.adb, helpers.parseArray(this.opts.uninstallOtherPackages), [_appiumAndroidDriver.SETTINGS_HELPER_PKG_ID, _uiautomator.SERVER_PACKAGE_ID, _uiautomator.SERVER_TEST_PACKAGE_ID]);
583
+ async deleteSession() {
584
+ this.log.debug('Deleting UiAutomator2 session');
585
+ const screenRecordingStopTasks = [
586
+ async () => {
587
+ if (!lodash_1.default.isEmpty(this._screenRecordingProperties)) {
588
+ await this.stopRecordingScreen();
589
+ }
590
+ },
591
+ async () => {
592
+ if (await this.mobileIsMediaProjectionRecordingRunning()) {
593
+ await this.mobileStopMediaProjectionRecording();
594
+ }
595
+ },
596
+ async () => {
597
+ if (!lodash_1.default.isEmpty(this._screenStreamingProps)) {
598
+ await this.mobileStopScreenStreaming();
599
+ }
600
+ },
601
+ ];
602
+ await appium_android_driver_1.androidHelpers.removeAllSessionWebSocketHandlers(this.server, this.sessionId);
603
+ if (this.uiautomator2) {
604
+ try {
605
+ await this.stopChromedriverProxies();
606
+ }
607
+ catch (err) {
608
+ this.log.warn(`Unable to stop ChromeDriver proxies: ${err.message}`);
609
+ }
610
+ if (this.jwpProxyActive) {
611
+ try {
612
+ await this.uiautomator2.deleteSession();
613
+ }
614
+ catch (err) {
615
+ this.log.warn(`Unable to proxy deleteSession to UiAutomator2: ${err.message}`);
616
+ }
617
+ }
618
+ this.uiautomator2 = undefined;
619
+ }
620
+ this.jwpProxyActive = false;
621
+ if (this.adb) {
622
+ await bluebird_1.default.all(screenRecordingStopTasks.map((task) => {
623
+ (async () => {
624
+ try {
625
+ await task();
626
+ }
627
+ catch (ign) { }
628
+ })();
629
+ }));
630
+ if (this.caps.androidCoverage) {
631
+ this.log.info('Shutting down the adb process of instrumentation...');
632
+ await this.adb.endAndroidCoverage();
633
+ // Use this broadcast intent to notify it's time to dump coverage to file
634
+ if (this.caps.androidCoverageEndIntent) {
635
+ this.log.info(`Sending intent broadcast '${this.caps.androidCoverageEndIntent}' at the end of instrumenting.`);
636
+ await this.adb.broadcast(this.caps.androidCoverageEndIntent);
637
+ }
638
+ else {
639
+ this.log.warn('No androidCoverageEndIntent is configured in caps. Possibly you cannot get coverage file.');
640
+ }
641
+ }
642
+ if (this.opts.appPackage) {
643
+ if (!this.isChromeSession &&
644
+ ((!this.opts.dontStopAppOnReset && !this.opts.noReset) ||
645
+ (this.opts.noReset && this.opts.shouldTerminateApp))) {
646
+ try {
647
+ await this.adb.forceStop(this.opts.appPackage);
648
+ }
649
+ catch (err) {
650
+ this.log.warn(`Unable to force stop app: ${err.message}`);
651
+ }
652
+ }
653
+ if (this.opts.fullReset && !this.opts.skipUninstall) {
654
+ this.log.debug(`Capability 'fullReset' set to 'true', Uninstalling '${this.opts.appPackage}'`);
655
+ try {
656
+ await this.adb.uninstallApk(this.opts.appPackage);
657
+ }
658
+ catch (err) {
659
+ this.log.warn(`Unable to uninstall app: ${err.message}`);
660
+ }
661
+ }
662
+ }
663
+ // This value can be true if test target device is <= 26
664
+ if (this._wasWindowAnimationDisabled) {
665
+ this.log.info('Restoring window animation state');
666
+ await this.adb.setAnimationState(true);
667
+ }
668
+ await this.adb.stopLogcat();
669
+ try {
670
+ await this.releaseSystemPort();
671
+ }
672
+ catch (error) {
673
+ this.log.warn(`Unable to remove system port forward: ${error.message}`);
674
+ // Ignore, this block will also be called when we fall in catch block
675
+ // and before even port forward.
676
+ }
677
+ try {
678
+ await this.releaseMjpegServerPort();
679
+ }
680
+ catch (error) {
681
+ this.log.warn(`Unable to remove MJPEG server port forward: ${error.message}`);
682
+ // Ignore, this block will also be called when we fall in catch block
683
+ // and before even port forward.
684
+ }
685
+ if ((await this.adb.getApiLevel()) >= 28) {
686
+ // Android P
687
+ this.log.info('Restoring hidden api policy to the device default configuration');
688
+ await this.adb.setDefaultHiddenApiPolicy(!!this.opts.ignoreHiddenApiPolicyError);
689
+ }
690
+ // @ts-expect-error unknown option
691
+ if (this.opts.reboot) {
692
+ const avdName = this.opts.avd.replace('@', '');
693
+ this.log.debug(`Closing emulator '${avdName}'`);
694
+ try {
695
+ await this.adb.killEmulator(avdName);
696
+ }
697
+ catch (err) {
698
+ this.log.warn(`Unable to close emulator: ${err.message}`);
699
+ }
700
+ }
701
+ }
702
+ if (this.mjpegStream) {
703
+ this.log.info('Closing MJPEG stream');
704
+ this.mjpegStream.stop();
705
+ }
706
+ await driver_1.BaseDriver.prototype.deleteSession.call(this);
309
707
  }
310
- if (this.opts.otherApps) {
311
- let otherApps;
312
- try {
313
- otherApps = helpers.parseArray(this.opts.otherApps);
314
- } catch (e) {
315
- this.log.errorAndThrow(`Could not parse "otherApps" capability: ${e.message}`);
316
- }
317
- otherApps = await _bluebird.default.all(otherApps.map(app => this.helpers.configureApp(app, [_extensions.APK_EXTENSION, _extensions.APKS_EXTENSION])));
318
- await helpers.installOtherApks(otherApps, this.adb, this.opts);
708
+ async checkAppPresent() {
709
+ this.log.debug('Checking whether app is actually present');
710
+ if (!(await support_1.fs.exists(this.opts.app))) {
711
+ this.log.errorAndThrow(`Could not find app apk at '${this.opts.app}'`);
712
+ throw new Error(); // unreachable
713
+ }
319
714
  }
320
- if (this.opts.app) {
321
- if (this.opts.noReset && !(await this.adb.isAppInstalled(this.opts.appPackage)) || !this.opts.noReset) {
322
- if (!this.opts.noSign && !(await this.adb.checkApkCert(this.opts.app, this.opts.appPackage, {
323
- requireDefaultCert: false
324
- }))) {
325
- await helpers.signApp(this.adb, this.opts.app);
326
- }
327
- if (!this.opts.skipUninstall) {
328
- await this.adb.uninstallApk(this.opts.appPackage);
329
- }
330
- await helpers.installApk(this.adb, this.opts);
331
- } else {
332
- this.log.debug('noReset has been requested and the app is already installed. Doing nothing');
333
- }
334
- } else {
335
- if (this.opts.fullReset) {
336
- this.log.errorAndThrow('Full reset requires an app capability, use fastReset if app is not provided');
337
- }
338
- this.log.debug('No app capability. Assuming it is already on the device');
339
- if (this.opts.fastReset && this.opts.appPackage) {
340
- await helpers.resetApp(this.adb, this.opts);
341
- }
715
+ async onSettingsUpdate() {
716
+ // intentionally do nothing here, since commands.updateSettings proxies
717
+ // settings to the uiauto2 server already
342
718
  }
343
- }
344
- async ensureAppStarts() {
345
- const appWaitPackage = this.opts.appWaitPackage || this.opts.appPackage;
346
- const appWaitActivity = this.opts.appWaitActivity || this.opts.appActivity;
347
- this.log.info(`Starting '${this.opts.appPackage}/${this.opts.appActivity} ` + `and waiting for '${appWaitPackage}/${appWaitActivity}'`);
348
- if (this.caps.androidCoverage) {
349
- this.log.info(`androidCoverage is configured. ` + ` Starting instrumentation of '${this.caps.androidCoverage}'...`);
350
- await this.adb.androidCoverage(this.caps.androidCoverage, appWaitPackage, appWaitActivity);
351
- return;
719
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
720
+ proxyActive(sessionId) {
721
+ // we always have an active proxy to the UiAutomator2 server
722
+ return true;
352
723
  }
353
- if (this.opts.noReset && !this.opts.forceAppLaunch && (await this.adb.processExists(this.opts.appPackage))) {
354
- this.log.info(`'${this.opts.appPackage}' is already running and noReset is enabled. ` + `Set forceAppLaunch capability to true if the app must be forcefully restarted on session startup.`);
355
- return;
724
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
725
+ canProxy(sessionId) {
726
+ // we can always proxy to the uiautomator2 server
727
+ return true;
356
728
  }
357
- await this.adb.startApp({
358
- pkg: this.opts.appPackage,
359
- activity: this.opts.appActivity,
360
- action: this.opts.intentAction || 'android.intent.action.MAIN',
361
- category: this.opts.intentCategory || 'android.intent.category.LAUNCHER',
362
- flags: this.opts.intentFlags || '0x10200000',
363
- waitPkg: this.opts.appWaitPackage,
364
- waitActivity: this.opts.appWaitActivity,
365
- waitForLaunch: this.opts.appWaitForLaunch,
366
- waitDuration: this.opts.appWaitDuration,
367
- optionalIntentArguments: this.opts.optionalIntentArguments,
368
- stopApp: this.opts.forceAppLaunch || !this.opts.dontStopAppOnReset,
369
- retry: true,
370
- user: this.opts.userProfile
371
- });
372
- }
373
- async deleteSession() {
374
- this.log.debug('Deleting UiAutomator2 session');
375
- const screenRecordingStopTasks = [async () => {
376
- if (!_lodash.default.isEmpty(this._screenRecordingProperties)) {
377
- await this.stopRecordingScreen();
378
- }
379
- }, async () => {
380
- if (await this.mobileIsMediaProjectionRecordingRunning()) {
381
- await this.mobileStopMediaProjectionRecording();
382
- }
383
- }, async () => {
384
- if (!_lodash.default.isEmpty(this._screenStreamingProps)) {
385
- await this.mobileStopScreenStreaming();
386
- }
387
- }];
388
- await _appiumAndroidDriver.androidHelpers.removeAllSessionWebSocketHandlers(this.server, this.sessionId);
389
- if (this.uiautomator2) {
390
- try {
391
- await this.stopChromedriverProxies();
392
- } catch (err) {
393
- this.log.warn(`Unable to stop ChromeDriver proxies: ${err.message}`);
394
- }
395
- if (this.jwpProxyActive) {
396
- try {
397
- await this.uiautomator2.deleteSession();
398
- } catch (err) {
399
- this.log.warn(`Unable to proxy deleteSession to UiAutomator2: ${err.message}`);
729
+ getProxyAvoidList() {
730
+ // we are maintaining two sets of NO_PROXY lists, one for chromedriver(CHROME_NO_PROXY)
731
+ // and one for uiautomator2(NO_PROXY), based on current context will return related NO_PROXY list
732
+ if (support_1.util.hasValue(this.chromedriver)) {
733
+ // if the current context is webview(chromedriver), then return CHROME_NO_PROXY list
734
+ this.jwpProxyAvoid = CHROME_NO_PROXY;
400
735
  }
401
- }
402
- this.uiautomator2 = null;
403
- }
404
- this.jwpProxyActive = false;
405
- if (this.adb) {
406
- await _bluebird.default.all(screenRecordingStopTasks.map(task => {
407
- (async () => {
408
- try {
409
- await task();
410
- } catch (ign) {}
411
- })();
412
- }));
413
- if (this.caps.androidCoverage) {
414
- this.log.info('Shutting down the adb process of instrumentation...');
415
- await this.adb.endAndroidCoverage();
416
- if (this.caps.androidCoverageEndIntent) {
417
- this.log.info(`Sending intent broadcast '${this.caps.androidCoverageEndIntent}' at the end of instrumenting.`);
418
- await this.adb.broadcast(this.caps.androidCoverageEndIntent);
419
- } else {
420
- this.log.warn('No androidCoverageEndIntent is configured in caps. Possibly you cannot get coverage file.');
421
- }
422
- }
423
- if (this.opts.appPackage) {
424
- if (!this.isChromeSession && (!this.opts.dontStopAppOnReset && !this.opts.noReset || this.opts.noReset && this.opts.shouldTerminateApp)) {
425
- try {
426
- await this.adb.forceStop(this.opts.appPackage);
427
- } catch (err) {
428
- this.log.warn(`Unable to force stop app: ${err.message}`);
429
- }
430
- }
431
- if (this.opts.fullReset && !this.opts.skipUninstall) {
432
- this.log.debug(`Capability 'fullReset' set to 'true', Uninstalling '${this.opts.appPackage}'`);
433
- try {
434
- await this.adb.uninstallApk(this.opts.appPackage);
435
- } catch (err) {
436
- this.log.warn(`Unable to uninstall app: ${err.message}`);
437
- }
438
- }
439
- }
440
- if (this._wasWindowAnimationDisabled) {
441
- this.log.info('Restoring window animation state');
442
- await this.adb.setAnimationState(true);
443
- }
444
- await this.adb.stopLogcat();
445
- try {
446
- await this.releaseSystemPort();
447
- } catch (error) {
448
- this.log.warn(`Unable to remove system port forward: ${error.message}`);
449
- }
450
- try {
451
- await this.releaseMjpegServerPort();
452
- } catch (error) {
453
- this.log.warn(`Unable to remove MJPEG server port forward: ${error.message}`);
454
- }
455
- if ((await this.adb.getApiLevel()) >= 28) {
456
- this.log.info('Restoring hidden api policy to the device default configuration');
457
- await this.adb.setDefaultHiddenApiPolicy(!!this.opts.ignoreHiddenApiPolicyError);
458
- }
459
- if (this.opts.reboot) {
460
- let avdName = this.opts.avd.replace('@', '');
461
- this.log.debug(`Closing emulator '${avdName}'`);
462
- try {
463
- await this.adb.killEmulator(avdName);
464
- } catch (err) {
465
- this.log.warn(`Unable to close emulator: ${err.message}`);
736
+ else {
737
+ this.jwpProxyAvoid = NO_PROXY;
466
738
  }
467
- }
468
- }
469
- if (this.mjpegStream) {
470
- this.log.info('Closing MJPEG stream');
471
- this.mjpegStream.stop();
472
- }
473
- await super.deleteSession();
474
- }
475
- async checkAppPresent() {
476
- this.log.debug('Checking whether app is actually present');
477
- if (!(await _support.fs.exists(this.opts.app))) {
478
- this.log.errorAndThrow(`Could not find app apk at '${this.opts.app}'`);
739
+ if (this.opts.nativeWebScreenshot) {
740
+ this.jwpProxyAvoid = [
741
+ ...this.jwpProxyAvoid,
742
+ ['GET', new RegExp('^/session/[^/]+/screenshot')],
743
+ ];
744
+ }
745
+ return this.jwpProxyAvoid;
479
746
  }
480
- }
481
- async onSettingsUpdate() {}
482
- async wrapBootstrapDisconnect(wrapped) {
483
- await wrapped();
484
- await this.adb.restart();
485
- await this.allocateSystemPort();
486
- await this.allocateMjpegServerPort();
487
- }
488
- proxyActive(sessionId) {
489
- super.proxyActive(sessionId);
490
- return true;
491
- }
492
- canProxy(sessionId) {
493
- super.canProxy(sessionId);
494
- return true;
495
- }
496
- getProxyAvoidList(sessionId) {
497
- super.getProxyAvoidList(sessionId);
498
- if (_support.util.hasValue(this.chromedriver)) {
499
- this.jwpProxyAvoid = CHROME_NO_PROXY;
500
- } else {
501
- this.jwpProxyAvoid = NO_PROXY;
747
+ async updateSettings(settings) {
748
+ await this.settings.update(settings);
749
+ await this.uiautomator2.jwproxy.command('/appium/settings', 'POST', { settings });
502
750
  }
503
- if (this.opts.nativeWebScreenshot) {
504
- this.jwpProxyAvoid = [...this.jwpProxyAvoid, ['GET', new RegExp('^/session/[^/]+/screenshot')]];
751
+ async getSettings() {
752
+ const driverSettings = this.settings.getSettings();
753
+ const serverSettings = (await this.uiautomator2.jwproxy.command('/appium/settings', 'GET'));
754
+ return { ...driverSettings, ...serverSettings };
505
755
  }
506
- return this.jwpProxyAvoid;
507
- }
508
- get isChromeSession() {
509
- return helpers.isChromeBrowser(this.opts.browserName);
510
- }
511
756
  }
512
757
  exports.AndroidUiautomator2Driver = AndroidUiautomator2Driver;
513
- for (let [cmd, fn] of _lodash.default.toPairs(_appiumAndroidDriver.androidCommands)) {
514
- AndroidUiautomator2Driver.prototype[cmd] = fn;
515
- }
516
- for (let [cmd, fn] of _lodash.default.toPairs(_index.default)) {
517
- AndroidUiautomator2Driver.prototype[cmd] = fn;
518
- }
519
- var _default = exports.default = AndroidUiautomator2Driver;
520
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbG9kYXNoIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfZHJpdmVyIiwiX3VpYXV0b21hdG9yIiwiX21ldGhvZE1hcCIsIl9zdXBwb3J0IiwiX2FzeW5jYm94IiwiX2JsdWViaXJkIiwiX2luZGV4IiwiX2FwcGl1bUFkYiIsIl9oZWxwZXJzIiwiX2FwcGl1bUFuZHJvaWREcml2ZXIiLCJfZGVzaXJlZENhcHMiLCJfcG9ydHNjYW5uZXIiLCJfb3MiLCJfcGF0aCIsIl9leHRlbnNpb25zIiwiaGVscGVycyIsIk9iamVjdCIsImFzc2lnbiIsInVpYXV0b21hdG9yMkhlbHBlcnMiLCJhbmRyb2lkSGVscGVycyIsIkRFVklDRV9QT1JUX1JBTkdFIiwiREVWSUNFX1BPUlRfQUxMT0NBVElPTl9HVUFSRCIsInV0aWwiLCJnZXRMb2NrRmlsZUd1YXJkIiwicGF0aCIsInJlc29sdmUiLCJvcyIsInRtcGRpciIsInRpbWVvdXQiLCJ0cnlSZWNvdmVyeSIsIkRFVklDRV9QT1JUIiwiTUpQRUdfU0VSVkVSX0RFVklDRV9QT1JUIiwiTE9DQUxIT1NUX0lQNCIsIk5PX1BST1hZIiwiUmVnRXhwIiwiQ0hST01FX05PX1BST1hZIiwiTUVNT0laRURfRlVOQ1RJT05TIiwiQW5kcm9pZFVpYXV0b21hdG9yMkRyaXZlciIsIkJhc2VEcml2ZXIiLCJuZXdNZXRob2RNYXAiLCJjb25zdHJ1Y3RvciIsIm9wdHMiLCJzaG91bGRWYWxpZGF0ZUNhcHMiLCJzaGVsbCIsImxvY2F0b3JTdHJhdGVnaWVzIiwiZGVzaXJlZENhcENvbnN0cmFpbnRzIiwidWlhdXRvbWF0b3IyIiwiandwUHJveHlBY3RpdmUiLCJqd3BQcm94eUF2b2lkIiwiYXBrU3RyaW5ncyIsInNldHRpbmdzIiwiRGV2aWNlU2V0dGluZ3MiLCJpZ25vcmVVbmltcG9ydGFudFZpZXdzIiwiYWxsb3dJbnZpc2libGVFbGVtZW50cyIsIm9uU2V0dGluZ3NVcGRhdGUiLCJiaW5kIiwiY2hyb21lZHJpdmVyIiwic2Vzc2lvbkNocm9tZWRyaXZlcnMiLCJmbiIsIl8iLCJtZW1vaXplIiwidmFsaWRhdGVEZXNpcmVkQ2FwcyIsImNhcHMiLCJjcmVhdGVTZXNzaW9uIiwiYXJncyIsInNlc3Npb25JZCIsInNlcnZlckRldGFpbHMiLCJwbGF0Zm9ybSIsIndlYlN0b3JhZ2VFbmFibGVkIiwidGFrZXNTY3JlZW5zaG90IiwiamF2YXNjcmlwdEVuYWJsZWQiLCJkYXRhYmFzZUVuYWJsZWQiLCJuZXR3b3JrQ29ubmVjdGlvbkVuYWJsZWQiLCJsb2NhdGlvbkNvbnRleHRFbmFibGVkIiwid2FybmluZ3MiLCJkZXNpcmVkIiwiY3VyQ29udGV4dCIsImRlZmF1bHRDb250ZXh0TmFtZSIsImRlZmF1bHRPcHRzIiwiZnVsbFJlc2V0IiwiYXV0b0xhdW5jaCIsImFkYlBvcnQiLCJERUZBVUxUX0FEQl9QT1JUIiwiYW5kcm9pZEluc3RhbGxUaW1lb3V0IiwiZGVmYXVsdHMiLCJpc0Nocm9tZVNlc3Npb24iLCJsb2ciLCJpbmZvIiwicGtnIiwiYWN0aXZpdHkiLCJnZXRDaHJvbWVQa2ciLCJicm93c2VyTmFtZSIsImFwcFBhY2thZ2UiLCJhcHBBY3Rpdml0eSIsInJlYm9vdCIsInNldEF2ZEZyb21DYXBhYmlsaXRpZXMiLCJhcHAiLCJjb25maWd1cmVBcHAiLCJBUEtfRVhURU5TSU9OIiwiQVBLU19FWFRFTlNJT04iLCJjaGVja0FwcFByZXNlbnQiLCJzdGFydFVpQXV0b21hdG9yMlNlc3Npb24iLCJmaWxsRGV2aWNlRGV0YWlscyIsIm1qcGVnU2NyZWVuc2hvdFVybCIsIm1qcGVnU3RyZWFtIiwibWpwZWciLCJNSnBlZ1N0cmVhbSIsInN0YXJ0IiwiZSIsImRlbGV0ZVNlc3Npb24iLCJwaXhlbFJhdGlvIiwiZ2V0RGV2aWNlUGl4ZWxSYXRpbyIsInN0YXRCYXJIZWlnaHQiLCJnZXRTdGF0dXNCYXJIZWlnaHQiLCJ2aWV3cG9ydFJlY3QiLCJnZXRWaWV3UG9ydFJlY3QiLCJkcml2ZXJEYXRhIiwiZ2V0U2Vzc2lvbiIsInNlc3Npb25EYXRhIiwiZGVidWciLCJ1aWEyRGF0YSIsImp3cHJveHkiLCJjb21tYW5kIiwiaXNFbXVsYXRvciIsImFkYiIsImF2ZCIsImRldmljZU5hbWUiLCJlcnJvckFuZFRocm93IiwicGxhdGZvcm1WZXJzaW9uIiwiYXZkRGV2aWNlIiwicmVwbGFjZSIsImFsbG9jYXRlU3lzdGVtUG9ydCIsImZvcndhcmRQb3J0IiwibG9jYWxQb3J0IiwiY2hlY2tQb3J0U3RhdHVzIiwic3lzdGVtUG9ydCIsIl9oYXNTeXN0ZW1Qb3J0SW5DYXBzIiwic3RhcnRQb3J0IiwiZW5kUG9ydCIsImZpbmRBUG9ydE5vdEluVXNlIiwicmVsZWFzZVN5c3RlbVBvcnQiLCJyZW1vdmVQb3J0Rm9yd2FyZCIsImFsbG9jYXRlTWpwZWdTZXJ2ZXJQb3J0IiwibWpwZWdTZXJ2ZXJQb3J0IiwicmVsZWFzZU1qcGVnU2VydmVyUG9ydCIsInVkaWQiLCJlbVBvcnQiLCJnZXREZXZpY2VJbmZvRnJvbUNhcHMiLCJjcmVhdGVBREIiLCJhcGlMZXZlbCIsImdldEFwaUxldmVsIiwic2V0SGlkZGVuQXBpUG9saWN5IiwiaWdub3JlSGlkZGVuQXBpUG9saWN5RXJyb3IiLCJoYXNWYWx1ZSIsImdwc0VuYWJsZWQiLCJ0b2dnbGVHUFNMb2NhdGlvblByb3ZpZGVyIiwid2FybiIsImFwcEluZm8iLCJnZXRMYXVuY2hJbmZvIiwiY3VyRGV2aWNlSWQiLCJkZXZpY2VVRElEIiwiaW5pdERldmljZSIsImluaXRVaUF1dG9tYXRvcjJTZXJ2ZXIiLCJkaXNhYmxlV2luZG93QW5pbWF0aW9uIiwiaXNBbmltYXRpb25PbiIsInNldEFuaW1hdGlvblN0YXRlIiwiX3dhc1dpbmRvd0FuaW1hdGlvbkRpc2FibGVkIiwiaW5pdEFVVCIsInN0YXJ0U2Vzc2lvbiIsImFkZERldmljZUluZm9Ub0NhcHMiLCJza2lwVW5sb2NrIiwidW5sb2NrIiwic3RhcnRDaHJvbWVTZXNzaW9uIiwiZW5zdXJlQXBwU3RhcnRzIiwib3JpZW50YXRpb24iLCJzZXRPcmllbnRhdGlvbiIsImF1dG9XZWJ2aWV3Iiwidmlld05hbWUiLCJkZWZhdWx0V2Vidmlld05hbWUiLCJhdXRvV2Vidmlld1RpbWVvdXQiLCJyZXRyeUludGVydmFsIiwic2V0Q29udGV4dCIsImFwaVZlcnNpb24iLCJtYW51ZmFjdHVyZXIiLCJtb2RlbCIsInJlYWxEaXNwbGF5U2l6ZSIsImRpc3BsYXlEZW5zaXR5IiwibW9iaWxlR2V0RGV2aWNlSW5mbyIsImRldmljZUFwaUxldmVsIiwicGFyc2VJbnQiLCJkZXZpY2VTY3JlZW5TaXplIiwiZGV2aWNlU2NyZWVuRGVuc2l0eSIsImRldmljZU1vZGVsIiwiZGV2aWNlTWFudWZhY3R1cmVyIiwidWlhdXRvbWF0b3IyT3B0cyIsImhvc3QiLCJyZW1vdGVBZGJIb3N0IiwiZGV2aWNlUG9ydCIsImFwayIsInRtcERpciIsImRpc2FibGVTdXBwcmVzc0FjY2Vzc2liaWxpdHlTZXJ2aWNlIiwicmVhZFRpbWVvdXQiLCJ1aWF1dG9tYXRvcjJTZXJ2ZXJSZWFkVGltZW91dCIsIlVpQXV0b21hdG9yMlNlcnZlciIsInByb3h5UmVxUmVzIiwicHJveHlDb21tYW5kIiwic2tpcFNlcnZlckluc3RhbGxhdGlvbiIsImluc3RhbGxTZXJ2ZXJBcGsiLCJ1aWF1dG9tYXRvcjJTZXJ2ZXJJbnN0YWxsVGltZW91dCIsImFkZFRvRGV2aWNlSWRsZVdoaXRlbGlzdCIsIlNFVFRJTkdTX0hFTFBFUl9QS0dfSUQiLCJTRVJWRVJfUEFDS0FHRV9JRCIsIlNFUlZFUl9URVNUX1BBQ0tBR0VfSUQiLCJzdGRlcnIiLCJtZXNzYWdlIiwidW5pbnN0YWxsT3RoZXJQYWNrYWdlcyIsInBhcnNlQXJyYXkiLCJvdGhlckFwcHMiLCJCIiwiYWxsIiwibWFwIiwiaW5zdGFsbE90aGVyQXBrcyIsIm5vUmVzZXQiLCJpc0FwcEluc3RhbGxlZCIsIm5vU2lnbiIsImNoZWNrQXBrQ2VydCIsInJlcXVpcmVEZWZhdWx0Q2VydCIsInNpZ25BcHAiLCJza2lwVW5pbnN0YWxsIiwidW5pbnN0YWxsQXBrIiwiaW5zdGFsbEFwayIsImZhc3RSZXNldCIsInJlc2V0QXBwIiwiYXBwV2FpdFBhY2thZ2UiLCJhcHBXYWl0QWN0aXZpdHkiLCJhbmRyb2lkQ292ZXJhZ2UiLCJmb3JjZUFwcExhdW5jaCIsInByb2Nlc3NFeGlzdHMiLCJzdGFydEFwcCIsImFjdGlvbiIsImludGVudEFjdGlvbiIsImNhdGVnb3J5IiwiaW50ZW50Q2F0ZWdvcnkiLCJmbGFncyIsImludGVudEZsYWdzIiwid2FpdFBrZyIsIndhaXRBY3Rpdml0eSIsIndhaXRGb3JMYXVuY2giLCJhcHBXYWl0Rm9yTGF1bmNoIiwid2FpdER1cmF0aW9uIiwiYXBwV2FpdER1cmF0aW9uIiwib3B0aW9uYWxJbnRlbnRBcmd1bWVudHMiLCJzdG9wQXBwIiwiZG9udFN0b3BBcHBPblJlc2V0IiwicmV0cnkiLCJ1c2VyIiwidXNlclByb2ZpbGUiLCJzY3JlZW5SZWNvcmRpbmdTdG9wVGFza3MiLCJpc0VtcHR5IiwiX3NjcmVlblJlY29yZGluZ1Byb3BlcnRpZXMiLCJzdG9wUmVjb3JkaW5nU2NyZWVuIiwibW9iaWxlSXNNZWRpYVByb2plY3Rpb25SZWNvcmRpbmdSdW5uaW5nIiwibW9iaWxlU3RvcE1lZGlhUHJvamVjdGlvblJlY29yZGluZyIsIl9zY3JlZW5TdHJlYW1pbmdQcm9wcyIsIm1vYmlsZVN0b3BTY3JlZW5TdHJlYW1pbmciLCJyZW1vdmVBbGxTZXNzaW9uV2ViU29ja2V0SGFuZGxlcnMiLCJzZXJ2ZXIiLCJzdG9wQ2hyb21lZHJpdmVyUHJveGllcyIsImVyciIsInRhc2siLCJpZ24iLCJlbmRBbmRyb2lkQ292ZXJhZ2UiLCJhbmRyb2lkQ292ZXJhZ2VFbmRJbnRlbnQiLCJicm9hZGNhc3QiLCJzaG91bGRUZXJtaW5hdGVBcHAiLCJmb3JjZVN0b3AiLCJzdG9wTG9nY2F0IiwiZXJyb3IiLCJzZXREZWZhdWx0SGlkZGVuQXBpUG9saWN5IiwiYXZkTmFtZSIsImtpbGxFbXVsYXRvciIsInN0b3AiLCJmcyIsImV4aXN0cyIsIndyYXBCb290c3RyYXBEaXNjb25uZWN0Iiwid3JhcHBlZCIsInJlc3RhcnQiLCJwcm94eUFjdGl2ZSIsImNhblByb3h5IiwiZ2V0UHJveHlBdm9pZExpc3QiLCJuYXRpdmVXZWJTY3JlZW5zaG90IiwiaXNDaHJvbWVCcm93c2VyIiwiZXhwb3J0cyIsImNtZCIsInRvUGFpcnMiLCJhbmRyb2lkQ29tbWFuZHMiLCJwcm90b3R5cGUiLCJjb21tYW5kcyIsIl9kZWZhdWx0IiwiZGVmYXVsdCJdLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi9kcml2ZXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IEJhc2VEcml2ZXIsIERldmljZVNldHRpbmdzIH0gZnJvbSAnYXBwaXVtL2RyaXZlcic7XG5pbXBvcnQge1xuICBVaUF1dG9tYXRvcjJTZXJ2ZXIsIFNFUlZFUl9QQUNLQUdFX0lELCBTRVJWRVJfVEVTVF9QQUNLQUdFX0lEXG59IGZyb20gJy4vdWlhdXRvbWF0b3IyJztcbmltcG9ydCB7IG5ld01ldGhvZE1hcCB9IGZyb20gJy4vbWV0aG9kLW1hcCc7XG5pbXBvcnQgeyBmcywgdXRpbCwgbWpwZWcgfSBmcm9tICdhcHBpdW0vc3VwcG9ydCc7XG5pbXBvcnQgeyByZXRyeUludGVydmFsIH0gZnJvbSAnYXN5bmNib3gnO1xuaW1wb3J0IEIgZnJvbSAnYmx1ZWJpcmQnO1xuaW1wb3J0IGNvbW1hbmRzIGZyb20gJy4vY29tbWFuZHMvaW5kZXgnO1xuaW1wb3J0IHsgREVGQVVMVF9BREJfUE9SVCB9IGZyb20gJ2FwcGl1bS1hZGInO1xuaW1wb3J0IHVpYXV0b21hdG9yMkhlbHBlcnMgZnJvbSAnLi9oZWxwZXJzJztcbmltcG9ydCB7IGFuZHJvaWRIZWxwZXJzLCBhbmRyb2lkQ29tbWFuZHMsIFNFVFRJTkdTX0hFTFBFUl9QS0dfSUQsIH0gZnJvbSAnYXBwaXVtLWFuZHJvaWQtZHJpdmVyJztcbmltcG9ydCBkZXNpcmVkQ2FwQ29uc3RyYWludHMgZnJvbSAnLi9kZXNpcmVkLWNhcHMnO1xuaW1wb3J0IHsgZmluZEFQb3J0Tm90SW5Vc2UsIGNoZWNrUG9ydFN0YXR1cyB9IGZyb20gJ3BvcnRzY2FubmVyJztcbmltcG9ydCBvcyBmcm9tICdvcyc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IEFQS19FWFRFTlNJT04sIEFQS1NfRVhURU5TSU9OIH0gZnJvbSAnLi9leHRlbnNpb25zJztcblxuXG5jb25zdCBoZWxwZXJzID0gT2JqZWN0LmFzc2lnbih7fSwgdWlhdXRvbWF0b3IySGVscGVycywgYW5kcm9pZEhlbHBlcnMpO1xuXG4vLyBUaGUgcmFuZ2Ugb2YgcG9ydHMgd2UgY2FuIHVzZSBvbiB0aGUgc3lzdGVtIGZvciBjb21tdW5pY2F0aW5nIHRvIHRoZVxuLy8gVWlBdXRvbWF0b3IyIEhUVFAgc2VydmVyIG9uIHRoZSBkZXZpY2VcbmNvbnN0IERFVklDRV9QT1JUX1JBTkdFID0gWzgyMDAsIDgyOTldO1xuXG4vLyBUaGUgZ3VhcmQgaXMgbmVlZGVkIHRvIGF2b2lkIGR5bmFtaWMgc3lzdGVtIHBvcnQgYWxsb2NhdGlvbiBjb25mbGljdHMgZm9yXG4vLyBwYXJhbGxlbCBkcml2ZXIgc2Vzc2lvbnNcbmNvbnN0IERFVklDRV9QT1JUX0FMTE9DQVRJT05fR1VBUkQgPSB1dGlsLmdldExvY2tGaWxlR3VhcmQoXG4gIHBhdGgucmVzb2x2ZShvcy50bXBkaXIoKSwgJ3VpYTJfZGV2aWNlX3BvcnRfZ3VhcmQnKSxcbiAge3RpbWVvdXQ6IDI1LCB0cnlSZWNvdmVyeTogdHJ1ZX1cbik7XG5cbi8vIFRoaXMgaXMgdGhlIHBvcnQgdGhhdCBVaUF1dG9tYXRvcjIgbGlzdGVucyB0byBvbiB0aGUgZGV2aWNlLiBXZSB3aWxsIGZvcndhcmRcbi8vIG9uZSBvZiB0aGUgcG9ydHMgYWJvdmUgb24gdGhlIHN5c3RlbSB0byB0aGlzIHBvcnQgb24gdGhlIGRldmljZS5cbmNvbnN0IERFVklDRV9QT1JUID0gNjc5MDtcbi8vIFRoaXMgaXMgdGhlIHBvcnQgdGhhdCB0aGUgVWlBdXRvbWF0b3IyIE1KUEVHIHNlcnZlciBsaXN0ZW5zIHRvIG9uIHRoZSBkZXZpY2UuXG4vLyBXZSB3aWxsIGZvcndhcmQgb25lIG9mIHRoZSBwb3J0cyBhYm92ZSBvbiB0aGUgc3lzdGVtIHRvIHRoaXMgcG9ydCBvbiB0aGVcbi8vIGRldmljZS5cbmNvbnN0IE1KUEVHX1NFUlZFUl9ERVZJQ0VfUE9SVCA9IDc4MTA7XG5cbmNvbnN0IExPQ0FMSE9TVF9JUDQgPSAnMTI3LjAuMC4xJztcblxuLy8gTk9fUFJPWFkgY29udGFpbnMgdGhlIHBhdGhzIHRoYXQgd2UgbmV2ZXIgd2FudCB0byBwcm94eSB0byBVaUF1dG9tYXRvcjIgc2VydmVyLlxuLy8gVE9ETzogIEFkZCB0aGUgbGlzdCBvZiBwYXRocyB0aGF0IHdlIG5ldmVyIHdhbnQgdG8gcHJveHkgdG8gVWlBdXRvbWF0b3IyIHNlcnZlci5cbi8vIFRPRE86IE5lZWQgdG8gc2VncmVnYXRlIHRoZSBwYXRocyBiZXR0ZXIgd2F5IHVzaW5nIHJlZ3VsYXIgZXhwcmVzc2lvbnMgd2hlcmV2ZXIgYXBwbGljYWJsZS5cbi8vIChOb3Qgc2VncmVnYXRpbmcgcmlnaHQgYXdheSBiZWNhdXNlIG1vcmUgcGF0aHMgdG8gYmUgYWRkZWQgaW4gdGhlIE5PX1BST1hZIGxpc3QpXG5jb25zdCBOT19QUk9YWSA9IFtcbiAgWydERUxFVEUnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvYWN0aW9ucycpXSxcbiAgWydHRVQnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vKD8hLiovKScpXSxcbiAgWydHRVQnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvYWxlcnRfW14vXSsnKV0sXG4gIFsnR0VUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL2FsZXJ0L1teL10rJyldLFxuICBbJ0dFVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9hcHBpdW0vW14vXSsvY3VycmVudF9hY3Rpdml0eScpXSxcbiAgWydHRVQnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvYXBwaXVtL1teL10rL2N1cnJlbnRfcGFja2FnZScpXSxcbiAgWydHRVQnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvYXBwaXVtL2FwcC9bXi9dKycpXSxcbiAgWydHRVQnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvYXBwaXVtL2RldmljZS9bXi9dKycpXSxcbiAgWydHRVQnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvYXBwaXVtL3NldHRpbmdzJyldLFxuICBbJ0dFVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9jb250ZXh0JyldLFxuICBbJ0dFVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9jb250ZXh0cycpXSxcbiAgWydHRVQnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvZWxlbWVudC9bXi9dKy9hdHRyaWJ1dGUnKV0sXG4gIFsnR0VUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL2VsZW1lbnQvW14vXSsvZGlzcGxheWVkJyldLFxuICBbJ0dFVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9lbGVtZW50L1teL10rL2VuYWJsZWQnKV0sXG4gIFsnR0VUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL2VsZW1lbnQvW14vXSsvbG9jYXRpb25faW5fdmlldycpXSxcbiAgWydHRVQnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvZWxlbWVudC9bXi9dKy9uYW1lJyldLFxuICBbJ0dFVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9lbGVtZW50L1teL10rL3NjcmVlbnNob3QnKV0sXG4gIFsnR0VUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL2VsZW1lbnQvW14vXSsvc2VsZWN0ZWQnKV0sXG4gIFsnR0VUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL2ltZS9bXi9dKycpXSxcbiAgWydHRVQnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvbG9jYXRpb24nKV0sXG4gIFsnR0VUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL25ldHdvcmtfY29ubmVjdGlvbicpXSxcbiAgWydHRVQnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvc2NyZWVuc2hvdCcpXSxcbiAgWydHRVQnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvdGltZW91dHMnKV0sXG4gIFsnR0VUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL3VybCcpXSxcbiAgWydQT1NUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL1teL10rX2FsZXJ0JCcpXSxcbiAgWydQT1NUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL2FjdGlvbnMnKV0sXG4gIFsnUE9TVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9hbGVydC9bXi9dKycpXSxcbiAgWydQT1NUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL2FwcC9bXi9dJyldLFxuICBbJ1BPU1QnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvYXBwaXVtL1teL10rL3N0YXJ0X2FjdGl2aXR5JyldLFxuICBbJ1BPU1QnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvYXBwaXVtL2FwcC9bXi9dKycpXSxcbiAgWydQT1NUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL2FwcGl1bS9jb21wYXJlX2ltYWdlcycpXSxcbiAgWydQT1NUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL2FwcGl1bS9kZXZpY2UvKD8hc2V0X2NsaXBib2FyZClbXi9dKycpXSxcbiAgWydQT1NUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL2FwcGl1bS9lbGVtZW50L1teL10rL3JlcGxhY2VfdmFsdWUnKV0sXG4gIFsnUE9TVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9hcHBpdW0vZWxlbWVudC9bXi9dKy92YWx1ZScpXSxcbiAgWydQT1NUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL2FwcGl1bS9nZXRQZXJmb3JtYW5jZURhdGEnKV0sXG4gIFsnUE9TVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9hcHBpdW0vcGVyZm9ybWFuY2VEYXRhL3R5cGVzJyldLFxuICBbJ1BPU1QnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvYXBwaXVtL3NldHRpbmdzJyldLFxuICBbJ1BPU1QnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvYXBwaXVtL2V4ZWN1dGVfZHJpdmVyJyldLFxuICBbJ1BPU1QnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvYXBwaXVtL3N0YXJ0X3JlY29yZGluZ19zY3JlZW4nKV0sXG4gIFsnUE9TVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9hcHBpdW0vc3RvcF9yZWNvcmRpbmdfc2NyZWVuJyldLFxuICBbJ1BPU1QnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvYXBwaXVtLy4qZXZlbnQnKV0sXG4gIFsnUE9TVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9jb250ZXh0JyldLFxuICBbJ1BPU1QnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvZWxlbWVudCcpXSxcbiAgWydQT1NUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL2ltZS9bXi9dKycpXSxcbiAgWydQT1NUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL2tleXMnKV0sXG4gIFsnUE9TVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9sb2NhdGlvbicpXSxcbiAgWydQT1NUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL25ldHdvcmtfY29ubmVjdGlvbicpXSxcbiAgWydQT1NUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL3RpbWVvdXRzJyldLFxuICBbJ1BPU1QnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvdG91Y2gvbXVsdGkvcGVyZm9ybScpXSxcbiAgWydQT1NUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL3RvdWNoL3BlcmZvcm0nKV0sXG4gIFsnUE9TVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy91cmwnKV0sXG5cbiAgLy8gTUpTT05XUCBjb21tYW5kc1xuICBbJ0dFVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9sb2cvdHlwZXMnKV0sXG4gIFsnUE9TVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9leGVjdXRlJyldLFxuICBbJ1BPU1QnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvZXhlY3V0ZV9hc3luYycpXSxcbiAgWydQT1NUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL2xvZycpXSxcbiAgLy8gVzNDIGNvbW1hbmRzXG4gIC8vIEZvciBTZWxlbml1bSB2NCAoVzNDIGRvZXMgbm90IGhhdmUgdGhpcyByb3V0ZSlcbiAgWydHRVQnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvc2UvbG9nL3R5cGVzJyldLFxuICBbJ0dFVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy93aW5kb3cvcmVjdCcpXSxcbiAgWydQT1NUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL2V4ZWN1dGUvYXN5bmMnKV0sXG4gIFsnUE9TVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9leGVjdXRlL3N5bmMnKV0sXG4gIC8vIEZvciBTZWxlbml1bSB2NCAoVzNDIGRvZXMgbm90IGhhdmUgdGhpcyByb3V0ZSlcbiAgWydQT1NUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL3NlL2xvZycpXSxcbl07XG5cbi8vIFRoaXMgaXMgYSBzZXQgb2YgbWV0aG9kcyBhbmQgcGF0aHMgdGhhdCB3ZSBuZXZlciB3YW50IHRvIHByb3h5IHRvIENocm9tZWRyaXZlci5cbmNvbnN0IENIUk9NRV9OT19QUk9YWSA9IFtcbiAgWydHRVQnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvYXBwaXVtJyldLFxuICBbJ0dFVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9jb250ZXh0JyldLFxuICBbJ0dFVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9lbGVtZW50L1teL10rL3JlY3QnKV0sXG4gIFsnR0VUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL29yaWVudGF0aW9uJyldLFxuICBbJ1BPU1QnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvYXBwaXVtJyldLFxuICBbJ1BPU1QnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvY29udGV4dCcpXSxcbiAgWydQT1NUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL29yaWVudGF0aW9uJyldLFxuICBbJ1BPU1QnLCBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vW14vXSsvdG91Y2gvbXVsdGkvcGVyZm9ybScpXSxcbiAgWydQT1NUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL3RvdWNoL3BlcmZvcm0nKV0sXG5cbiAgLy8gdGhpcyBpcyBuZWVkZWQgdG8gbWFrZSB0aGUgbW9iaWxlOiBjb21tYW5kcyB3b3JraW5nIGluIHdlYiBjb250ZXh0XG4gIFsnUE9TVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9leGVjdXRlJCcpXSxcbiAgWydQT1NUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL2V4ZWN1dGUvc3luYycpXSxcblxuICAvLyBNSlNPTldQIGNvbW1hbmRzXG4gIFsnR0VUJywgbmV3IFJlZ0V4cCgnXi9zZXNzaW9uL1teL10rL2xvZy90eXBlcyQnKV0sXG4gIFsnUE9TVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9sb2ckJyldLFxuICAvLyBXM0MgY29tbWFuZHNcbiAgLy8gRm9yIFNlbGVuaXVtIHY0IChXM0MgZG9lcyBub3QgaGF2ZSB0aGlzIHJvdXRlKVxuICBbJ0dFVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9zZS9sb2cvdHlwZXMkJyldLFxuICAvLyBGb3IgU2VsZW5pdW0gdjQgKFczQyBkb2VzIG5vdCBoYXZlIHRoaXMgcm91dGUpXG4gIFsnUE9TVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9zZS9sb2ckJyldLFxuXTtcblxuY29uc3QgTUVNT0laRURfRlVOQ1RJT05TID0gW1xuICAnZ2V0U3RhdHVzQmFySGVpZ2h0JyxcbiAgJ2dldERldmljZVBpeGVsUmF0aW8nLFxuXTtcblxuY2xhc3MgQW5kcm9pZFVpYXV0b21hdG9yMkRyaXZlciBleHRlbmRzIEJhc2VEcml2ZXIge1xuXG4gIHN0YXRpYyBuZXdNZXRob2RNYXAgPSBuZXdNZXRob2RNYXA7XG5cbiAgY29uc3RydWN0b3IgKG9wdHMgPSB7fSwgc2hvdWxkVmFsaWRhdGVDYXBzID0gdHJ1ZSkge1xuICAgIC8vIGBzaGVsbGAgb3ZlcndyaXRlcyBhZGIuc2hlbGwsIHNvIHJlbW92ZVxuICAgIGRlbGV0ZSBvcHRzLnNoZWxsO1xuXG4gICAgc3VwZXIob3B0cywgc2hvdWxkVmFsaWRhdGVDYXBzKTtcbiAgICB0aGlzLmxvY2F0b3JTdHJhdGVnaWVzID0gW1xuICAgICAgJ3hwYXRoJyxcbiAgICAgICdpZCcsXG4gICAgICAnY2xhc3MgbmFtZScsXG4gICAgICAnYWNjZXNzaWJpbGl0eSBpZCcsXG4gICAgICAnY3NzIHNlbGVjdG9yJyxcbiAgICAgICctYW5kcm9pZCB1aWF1dG9tYXRvcidcbiAgICBdO1xuICAgIHRoaXMuZGVzaXJlZENhcENvbnN0cmFpbnRzID0gZGVzaXJlZENhcENvbnN0cmFpbnRzO1xuICAgIHRoaXMudWlhdXRvbWF0b3IyID0gbnVsbDtcbiAgICB0aGlzLmp3cFByb3h5QWN0aXZlID0gZmFsc2U7XG4gICAgdGhpcy5qd3BQcm94eUF2b2lkID0gTk9fUFJPWFk7XG4gICAgdGhpcy5hcGtTdHJpbmdzID0ge307IC8vIG1hcCBvZiBsYW5ndWFnZSAtPiBzdHJpbmdzIG9ialxuXG4gICAgdGhpcy5zZXR0aW5ncyA9IG5ldyBEZXZpY2VTZXR0aW5ncyh7aWdub3JlVW5pbXBvcnRhbnRWaWV3czogZmFsc2UsIGFsbG93SW52aXNpYmxlRWxlbWVudHM6IGZhbHNlfSxcbiAgICAgICAgdGhpcy5vblNldHRpbmdzVXBkYXRlLmJpbmQodGhpcykpO1xuICAgIC8vIGhhbmRsZSB3ZWJ2aWV3IG1lY2hhbmljcyBmcm9tIEFuZHJvaWREcml2ZXJcbiAgICB0aGlzLmNocm9tZWRyaXZlciA9IG51bGw7XG4gICAgdGhpcy5zZXNzaW9uQ2hyb21lZHJpdmVycyA9IHt9O1xuXG4gICAgLy8gbWVtb2l6ZSBmdW5jdGlvbnMgaGVyZSwgc28gdGhhdCB0aGV5IGFyZSBkb25lIG9uIGEgcGVyLWluc3RhbmNlIGJhc2lzXG4gICAgZm9yIChjb25zdCBmbiBvZiBNRU1PSVpFRF9GVU5DVElPTlMpIHtcbiAgICAgIHRoaXNbZm5dID0gXy5tZW1vaXplKHRoaXNbZm5dKTtcbiAgICB9XG4gIH1cblxuICB2YWxpZGF0ZURlc2lyZWRDYXBzIChjYXBzKSB7XG4gICAgcmV0dXJuIHN1cGVyLnZhbGlkYXRlRGVzaXJlZENhcHMoY2FwcykgJiYgYW5kcm9pZEhlbHBlcnMudmFsaWRhdGVEZXNpcmVkQ2FwcyhjYXBzKTtcbiAgfVxuXG4gIGFzeW5jIGNyZWF0ZVNlc3Npb24gKC4uLmFyZ3MpIHtcbiAgICB0cnkge1xuICAgICAgLy8gVE9ETyBoYW5kbGUgb3RoZXJTZXNzaW9uRGF0YSBmb3IgbXVsdGlwbGUgc2Vzc2lvbnNcbiAgICAgIGxldCBbc2Vzc2lvbklkLCBjYXBzXSA9IGF3YWl0IHN1cGVyLmNyZWF0ZVNlc3Npb24oLi4uYXJncyk7XG5cbiAgICAgIGxldCBzZXJ2ZXJEZXRhaWxzID0ge1xuICAgICAgICBwbGF0Zm9ybTogJ0xJTlVYJyxcbiAgICAgICAgd2ViU3RvcmFnZUVuYWJsZWQ6IGZhbHNlLFxuICAgICAgICB0YWtlc1NjcmVlbnNob3Q6IHRydWUsXG4gICAgICAgIGphdmFzY3JpcHRFbmFibGVkOiB0cnVlLFxuICAgICAgICBkYXRhYmFzZUVuYWJsZWQ6IGZhbHNlLFxuICAgICAgICBuZXR3b3JrQ29ubmVjdGlvbkVuYWJsZWQ6IHRydWUsXG4gICAgICAgIGxvY2F0aW9uQ29udGV4dEVuYWJsZWQ6IGZhbHNlLFxuICAgICAgICB3YXJuaW5nczoge30sXG4gICAgICAgIGRlc2lyZWQ6IHRoaXMuY2FwcyxcbiAgICAgIH07XG5cbiAgICAgIHRoaXMuY2FwcyA9IE9iamVjdC5hc3NpZ24oc2VydmVyRGV0YWlscywgdGhpcy5jYXBzKTtcblxuICAgICAgdGhpcy5jdXJDb250ZXh0ID0gdGhpcy5kZWZhdWx0Q29udGV4dE5hbWUoKTtcblxuICAgICAgbGV0IGRlZmF1bHRPcHRzID0ge1xuICAgICAgICBmdWxsUmVzZXQ6IGZhbHNlLFxuICAgICAgICBhdXRvTGF1bmNoOiB0cnVlLFxuICAgICAgICBhZGJQb3J0OiBERUZBVUxUX0FEQl9QT1JULFxuICAgICAgICBhbmRyb2lkSW5zdGFsbFRpbWVvdXQ6IDkwMDAwXG4gICAgICB9O1xuICAgICAgXy5kZWZhdWx0cyh0aGlzLm9wdHMsIGRlZmF1bHRPcHRzKTtcblxuICAgICAgaWYgKHRoaXMuaXNDaHJvbWVTZXNzaW9uKSB7XG4gICAgICAgIHRoaXMubG9nLmluZm8oXCJXZSdyZSBnb2luZyB0byBydW4gYSBDaHJvbWUtYmFzZWQgc2Vzc2lvblwiKTtcbiAgICAgICAgbGV0IHtwa2csIGFjdGl2aXR5fSA9IGhlbHBlcnMuZ2V0Q2hyb21lUGtnKHRoaXMub3B0cy5icm93c2VyTmFtZSk7XG4gICAgICAgIHRoaXMub3B0cy5hcHBQYWNrYWdlID0gdGhpcy5jYXBzLmFwcFBhY2thZ2UgPSBwa2c7XG4gICAgICAgIHRoaXMub3B0cy5hcHBBY3Rpdml0eSA9IHRoaXMuY2Fwcy5hcHBBY3Rpdml0eSA9IGFjdGl2aXR5O1xuICAgICAgICB0aGlzLmxvZy5pbmZvKGBDaHJvbWUtdHlwZSBwYWNrYWdlIGFuZCBhY3Rpdml0eSBhcmUgJHtwa2d9IGFuZCAke2FjdGl2aXR5fWApO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5vcHRzLnJlYm9vdCkge1xuICAgICAgICB0aGlzLnNldEF2ZEZyb21DYXBhYmlsaXRpZXMoY2Fwcyk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLm9wdHMuYXBwKSB7XG4gICAgICAgIC8vIGZpbmQgYW5kIGNvcHksIG9yIGRvd25sb2FkIGFuZCB1bnppcCBhbiBhcHAgdXJsIG9yIHBhdGhcbiAgICAgICAgdGhpcy5vcHRzLmFwcCA9IGF3YWl0IHRoaXMuaGVscGVycy5jb25maWd1cmVBcHAodGhpcy5vcHRzLmFwcCwgW0FQS19FWFRFTlNJT04sIEFQS1NfRVhURU5TSU9OXSk7XG4gICAgICAgIGF3YWl0IHRoaXMuY2hlY2tBcHBQcmVzZW50KCk7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMub3B0cy5hcHBQYWNrYWdlKSB7XG4gICAgICAgIC8vIHRoZSBhcHAgaXNuJ3QgYW4gYWN0dWFsIGFwcCBmaWxlIGJ1dCByYXRoZXIgc29tZXRoaW5nIHdlIHdhbnQgdG9cbiAgICAgICAgLy8gYXNzdW1lIGlzIG9uIHRoZSBkZXZpY2UgYW5kIGp1c3QgbGF1bmNoIHZpYSB0aGUgYXBwUGFja2FnZVxuICAgICAgICB0aGlzLmxvZy5pbmZvKGBTdGFydGluZyAnJHt0aGlzLm9wdHMuYXBwUGFja2FnZX0nIGRpcmVjdGx5IG9uIHRoZSBkZXZpY2VgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMubG9nLmluZm8oYE5laXRoZXIgJ2FwcCcgbm9yICdhcHBQYWNrYWdlJyB3YXMgc2V0LiBTdGFydGluZyBVaUF1dG9tYXRvcjIgYCArXG4gICAgICAgICAgJ3dpdGhvdXQgdGhlIHRhcmdldCBhcHBsaWNhdGlvbicpO1xuICAgICAgfVxuICAgICAgdGhpcy5vcHRzLmFkYlBvcnQgPSB0aGlzLm9wdHMuYWRiUG9ydCB8fCBERUZBVUxUX0FEQl9QT1JUO1xuXG4gICAgICBhd2FpdCB0aGlzLnN0YXJ0VWlBdXRvbWF0b3IyU2Vzc2lvbigpO1xuICAgICAgYXdhaXQgdGhpcy5maWxsRGV2aWNlRGV0YWlscygpO1xuICAgICAgaWYgKHRoaXMub3B0cy5tanBlZ1NjcmVlbnNob3RVcmwpIHtcbiAgICAgICAgdGhpcy5sb2cuaW5mbyhgU3RhcnRpbmcgTUpQRUcgc3RyZWFtIHJlYWRpbmcgVVJMOiAnJHt0aGlzLm9wdHMubWpwZWdTY3JlZW5zaG90VXJsfSdgKTtcbiAgICAgICAgdGhpcy5tanBlZ1N0cmVhbSA9IG5ldyBtanBlZy5NSnBlZ1N0cmVhbSh0aGlzLm9wdHMubWpwZWdTY3JlZW5zaG90VXJsKTtcbiAgICAgICAgYXdhaXQgdGhpcy5tanBlZ1N0cmVhbS5zdGFydCgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFtzZXNzaW9uSWQsIHRoaXMuY2Fwc107XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgYXdhaXQgdGhpcy5kZWxldGVTZXNzaW9uKCk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGZpbGxEZXZpY2VEZXRhaWxzICgpIHtcbiAgICB0aGlzLmNhcHMucGl4ZWxSYXRpbyA9IGF3YWl0IHRoaXMuZ2V0RGV2aWNlUGl4ZWxSYXRpbygpO1xuICAgIHRoaXMuY2Fwcy5zdGF0QmFySGVpZ2h0ID0gYXdhaXQgdGhpcy5nZXRTdGF0dXNCYXJIZWlnaHQoKTtcbiAgICB0aGlzLmNhcHMudmlld3BvcnRSZWN0ID0gYXdhaXQgdGhpcy5nZXRWaWV3UG9ydFJlY3QoKTtcbiAgfVxuXG4gIGdldCBkcml2ZXJEYXRhICgpIHtcbiAgICAvLyBUT0RPIGZpbGwgb3V0IHJlc291cmNlIGluZm8gaGVyZVxuICAgIHJldHVybiB7fTtcbiAgfVxuXG4gIGFzeW5jIGdldFNlc3Npb24gKCkge1xuICAgIGxldCBzZXNzaW9uRGF0YSA9IGF3YWl0IHN1cGVyLmdldFNlc3Npb24oKTtcbiAgICB0aGlzLmxvZy5kZWJ1ZygnR2V0dGluZyBzZXNzaW9uIGRldGFpbHMgZnJvbSBzZXJ2ZXIgdG8gbWl4IGluJyk7XG4gICAgbGV0IHVpYTJEYXRhID0gYXdhaXQgdGhpcy51aWF1dG9tYXRvcjIuandwcm94eS5jb21tYW5kKCcvJywgJ0dFVCcsIHt9KTtcbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgc2Vzc2lvbkRhdGEsIHVpYTJEYXRhKTtcbiAgfVxuXG4gIGlzRW11bGF0b3IgKCkge1xuICAgIHJldHVybiBoZWxwZXJzLmlzRW11bGF0b3IodGhpcy5hZGIsIHRoaXMub3B0cyk7XG4gIH1cblxuICBzZXRBdmRGcm9tQ2FwYWJpbGl0aWVzIChjYXBzKSB7XG4gICAgaWYgKHRoaXMub3B0cy5hdmQpIHtcbiAgICAgIHRoaXMubG9nLmluZm8oJ2F2ZCBuYW1lIGRlZmluZWQsIGlnbm9yaW5nIGRldmljZSBuYW1lIGFuZCBwbGF0Zm9ybSB2ZXJzaW9uJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICghY2Fwcy5kZXZpY2VOYW1lKSB7XG4gICAgICAgIHRoaXMubG9nLmVycm9yQW5kVGhyb3coJ2F2ZCBvciBkZXZpY2VOYW1lIHNob3VsZCBiZSBzcGVjaWZpZWQgd2hlbiByZWJvb3Qgb3B0aW9uIGlzIGVuYWJsZXMnKTtcbiAgICAgIH1cbiAgICAgIGlmICghY2Fwcy5wbGF0Zm9ybVZlcnNpb24pIHtcbiAgICAgICAgdGhpcy5sb2cuZXJyb3JBbmRUaHJvdygnYXZkIG9yIHBsYXRmb3JtVmVyc2lvbiBzaG91bGQgYmUgc3BlY2lmaWVkIHdoZW4gcmVib290IG9wdGlvbiBpcyBlbmFibGVkJyk7XG4gICAgICB9XG4gICAgICBsZXQgYXZkRGV2aWNlID0gY2Fwcy5kZXZpY2VOYW1lLnJlcGxhY2UoL1teYS16QS1aMC05Xy5dL2csICctJyk7XG4gICAgICB0aGlzLm9wdHMuYXZkID0gYCR7YXZkRGV2aWNlfV9fJHtjYXBzLnBsYXRmb3JtVmVyc2lvbn1gO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGFsbG9jYXRlU3lzdGVtUG9ydCAoKSB7XG4gICAgY29uc3QgZm9yd2FyZFBvcnQgPSBhc3luYyAobG9jYWxQb3J0KSA9PiB7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgRm9yd2FyZGluZyBVaUF1dG9tYXRvcjIgU2VydmVyIHBvcnQgJHtERVZJQ0VfUE9SVH0gdG8gbG9jYWwgcG9ydCAke2xvY2FsUG9ydH1gKTtcbiAgICAgIGlmICgoYXdhaXQgY2hlY2tQb3J0U3RhdHVzKGxvY2FsUG9ydCwgTE9DQUxIT1NUX0lQNCkpID09PSAnb3BlbicpIHtcbiAgICAgICAgdGhpcy5sb2cuZXJyb3JBbmRUaHJvdyhgVWlBdXRvbWF0b3IyIFNlcnZlciBjYW5ub3Qgc3RhcnQgYmVjYXVzZSB0aGUgbG9jYWwgcG9ydCAjJHtsb2NhbFBvcnR9IGlzIGJ1c3kuIGAgK1xuICAgICAgICAgIGBNYWtlIHN1cmUgdGhlIHBvcnQgeW91IHByb3ZpZGUgdmlhICdzeXN0ZW1Qb3J0JyBjYXBhYmlsaXR5IGlzIG5vdCBvY2N1cGllZC4gYCArXG4gICAgICAgICAgYFRoaXMgc2l0dWF0aW9uIG1pZ2h0IG9mdGVuIGJlIGEgcmVzdWx0IG9mIGFuIGluYWNjdXJhdGUgc2Vzc2lvbnMgbWFuYWdlbWVudCwgZS5nLiBgICtcbiAgICAgICAgICBgb2xkIGF1dG9tYXRpb24gc2Vzc2lvbnMgb24gdGhlIHNhbWUgZGV2aWNlIG11c3QgYWx3YXlzIGJlIGNsb3NlZCBiZWZvcmUgc3RhcnRpbmcgbmV3IG9uZXMuYCk7XG4gICAgICB9XG4gICAgICBhd2FpdCB0aGlzLmFkYi5mb3J3YXJkUG9ydChsb2NhbFBvcnQsIERFVklDRV9QT1JUKTtcbiAgICB9O1xuXG4gICAgaWYgKHRoaXMub3B0cy5zeXN0ZW1Qb3J0KSB7XG4gICAgICB0aGlzLl9oYXNTeXN0ZW1Qb3J0SW5DYXBzID0gdHJ1ZTtcbiAgICAgIHJldHVybiBhd2FpdCBmb3J3YXJkUG9ydCh0aGlzLm9wdHMuc3lzdGVtUG9ydCk7XG4gICAgfVxuXG4gICAgYXdhaXQgREVWSUNFX1BPUlRfQUxMT0NBVElPTl9HVUFSRChhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBbc3RhcnRQb3J0LCBlbmRQb3J0XSA9IERFVklDRV9QT1JUX1JBTkdFO1xuICAgICAgdHJ5IHtcbiAgICAgICAgdGhpcy5vcHRzLnN5c3RlbVBvcnQgPSBhd2FpdCBmaW5kQVBvcnROb3RJblVzZShzdGFydFBvcnQsIGVuZFBvcnQpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aGlzLmxvZy5lcnJvckFuZFRocm93KFxuICAgICAgICAgIGBDYW5ub3QgZmluZCBhbnkgZnJlZSBwb3J0IGluIHJhbmdlICR7c3RhcnRQb3J0fS4uJHtlbmRQb3J0fX0uIGAgK1xuICAgICAgICAgIGBQbGVhc2Ugc2V0IHRoZSBhdmFpbGFibGUgcG9ydCBudW1iZXIgYnkgcHJvdmlkaW5nIHRoZSBzeXN0ZW1Qb3J0IGNhcGFiaWxpdHkgb3IgYCArXG4gICAgICAgICAgYGRvdWJsZSBjaGVjayB0aGUgcHJvY2Vzc2VzIHRoYXQgYXJlIGxvY2tpbmcgcG9ydHMgd2l0aGluIHRoaXMgcmFuZ2UgYW5kIHRlcm1pbmF0ZSBgICtcbiAgICAgICAgICBgdGhlc2Ugd2hpY2ggYXJlIG5vdCBuZWVkZWQgYW55bW9yZWApO1xuICAgICAgfVxuICAgICAgYXdhaXQgZm9yd2FyZFBvcnQodGhpcy5vcHRzLnN5c3RlbVBvcnQpO1xuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgcmVsZWFzZVN5c3RlbVBvcnQgKCkge1xuICAgIGlmICghdGhpcy5vcHRzLnN5c3RlbVBvcnQgfHwgIXRoaXMuYWRiKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX2hhc1N5c3RlbVBvcnRJbkNhcHMpIHtcbiAgICAgIGF3YWl0IHRoaXMuYWRiLnJlbW92ZVBvcnRGb3J3YXJkKHRoaXMub3B0cy5zeXN0ZW1Qb3J0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXdhaXQgREVWSUNFX1BPUlRfQUxMT0NBVElPTl9HVUFSRChhc3luYyAoKSA9PiBhd2FpdCB0aGlzLmFkYi5yZW1vdmVQb3J0Rm9yd2FyZCh0aGlzLm9wdHMuc3lzdGVtUG9ydCkpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGFsbG9jYXRlTWpwZWdTZXJ2ZXJQb3J0ICgpIHtcbiAgICBpZiAodGhpcy5vcHRzLm1qcGVnU2VydmVyUG9ydCkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoYE1KUEVHIGJyb2FkY2FzdGluZyByZXF1ZXN0ZWQsIGZvcndhcmRpbmcgTUpQRUcgc2VydmVyIHBvcnQgJHtNSlBFR19TRVJWRVJfREVWSUNFX1BPUlR9IGAgK1xuICAgICAgICBgdG8gbG9jYWwgcG9ydCAke3RoaXMub3B0cy5tanBlZ1NlcnZlclBvcnR9YCk7XG4gICAgICBhd2FpdCB0aGlzLmFkYi5mb3J3YXJkUG9ydCh0aGlzLm9wdHMubWpwZWdTZXJ2ZXJQb3J0LCBNSlBFR19TRVJWRVJfREVWSUNFX1BPUlQpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHJlbGVhc2VNanBlZ1NlcnZlclBvcnQgKCkge1xuICAgIGlmICh0aGlzLm9wdHMubWpwZWdTZXJ2ZXJQb3J0KSB7XG4gICAgICBhd2FpdCB0aGlzLmFkYi5yZW1vdmVQb3J0Rm9yd2FyZCh0aGlzLm9wdHMubWpwZWdTZXJ2ZXJQb3J0KTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBzdGFydFVpQXV0b21hdG9yMlNlc3Npb24gKCkge1xuICAgIC8vIGdldCBkZXZpY2UgdWRpZCBmb3IgdGhpcyBzZXNzaW9uXG4gICAgbGV0IHt1ZGlkLCBlbVBvcnR9ID0gYXdhaXQgaGVscGVycy5nZXREZXZpY2VJbmZvRnJvbUNhcHModGhpcy5vcHRzKTtcbiAgICB0aGlzLm9wdHMudWRpZCA9IHVkaWQ7XG4gICAgdGhpcy5vcHRzLmVtUG9ydCA9IGVtUG9ydDtcblxuICAgIC8vIG5vdyB0aGF0IHdlIGtub3cgb3VyIGphdmEgdmVyc2lvbiBhbmQgZGV2aWNlIGluZm8sIHdlIGNhbiBjcmVhdGUgb3VyXG4gICAgLy8gQURCIGluc3RhbmNlXG4gICAgdGhpcy5hZGIgPSBhd2FpdCBhbmRyb2lkSGVscGVycy5jcmVhdGVBREIodGhpcy5vcHRzKTtcblxuICAgIGNvbnN0IGFwaUxldmVsID0gYXdhaXQgdGhpcy5hZGIuZ2V0QXBpTGV2ZWwoKTtcblxuICAgIGlmIChhcGlMZXZlbCA8IDIxKSB7XG4gICAgICB0aGlzLmxvZy5lcnJvckFuZFRocm93KCdVSUF1dG9tYXRvcjIgaXMgb25seSBzdXBwb3J0ZWQgc2luY2UgQW5kcm9pZCA1LjAgKExvbGxpcG9wKS4gJyArXG4gICAgICAgICdZb3UgY291bGQgc3RpbGwgdXNlIG90aGVyIHN1cHBvcnRlZCBiYWNrZW5kcyBpbiBvcmRlciB0byBhdXRvbWF0ZSBvbGRlciBBbmRyb2lkIHZlcnNpb25zLicpO1xuICAgIH1cblxuICAgIGlmIChhcGlMZXZlbCA+PSAyOCkgeyAvLyBBbmRyb2lkIFBcbiAgICAgIHRoaXMubG9nLmluZm8oJ1JlbGF4aW5nIGhpZGRlbiBhcGkgcG9saWN5Jyk7XG4gICAgICBhd2FpdCB0aGlzLmFkYi5zZXRIaWRkZW5BcGlQb2xpY3koJzEnLCAhIXRoaXMub3B0cy5pZ25vcmVIaWRkZW5BcGlQb2xpY3lFcnJvcik7XG4gICAgfVxuXG4gICAgLy8gY2hlY2sgaWYgd2UgaGF2ZSB0byBlbmFibGUvZGlzYWJsZSBncHMgYmVmb3JlIHJ1bm5pbmcgdGhlIGFwcGxpY2F0aW9uXG4gICAgaWYgKHV0aWwuaGFzVmFsdWUodGhpcy5vcHRzLmdwc0VuYWJsZWQpKSB7XG4gICAgICBpZiAodGhpcy5pc0VtdWxhdG9yKCkpIHtcbiAgICAgICAgdGhpcy5sb2cuaW5mbyhgVHJ5aW5nIHRvICR7dGhpcy5vcHRzLmdwc0VuYWJsZWQgPyAnZW5hYmxlJyA6ICdkaXNhYmxlJ30gZ3BzIGxvY2F0aW9uIHByb3ZpZGVyYCk7XG4gICAgICAgIGF3YWl0IHRoaXMuYWRiLnRvZ2dsZUdQU0xvY2F0aW9uUHJvdmlkZXIodGhpcy5vcHRzLmdwc0VuYWJsZWQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5sb2cud2FybihgU29ycnkhICdncHNFbmFibGVkJyBjYXBhYmlsaXR5IGlzIG9ubHkgYXZhaWxhYmxlIGZvciBlbXVsYXRvcnNgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBnZXQgYXBwUGFja2FnZSBldCBhbCBmcm9tIG1hbmlmZXN0IGlmIG5lY2Vzc2FyeVxuICAgIGNvbnN0IGFwcEluZm8gPSBhd2FpdCBoZWxwZXJzLmdldExhdW5jaEluZm8odGhpcy5hZGIsIHRoaXMub3B0cyk7XG4gICAgLy8gYW5kIGdldCBpdCBvbnRvIG91ciAnb3B0cycgb2JqZWN0IHNvIHdlIHVzZSBpdCBmcm9tIG5vdyBvblxuICAgIE9iamVjdC5hc3NpZ24odGhpcy5vcHRzLCBhcHBJbmZvIHx8IHt9KTtcblxuICAgIC8vIHNldCBhY3R1YWwgZGV2aWNlIG5hbWUsIHVkaWQsIHBsYXRmb3JtIHZlcnNpb24sIHNjcmVlbiBzaXplLCBzY3JlZW4gZGVuc2l0eSwgbW9kZWwgYW5kIG1hbnVmYWN0dXJlciBkZXRhaWxzXG4gICAgdGhpcy5jYXBzLmRldmljZU5hbWUgPSB0aGlzLmFkYi5jdXJEZXZpY2VJZDtcbiAgICB0aGlzLmNhcHMuZGV2aWNlVURJRCA9IHRoaXMub3B0cy51ZGlkO1xuXG4gICAgLy8gc3RhcnQgYW4gYXZkLCBzZXQgdGhlIGxhbmd1YWdlL2xvY2FsZSwgcGljayBhbiBlbXVsYXRvciwgZXRjLi4uXG4gICAgLy8gVE9ETyB3aXRoIG11bHRpcGxlIGRldmljZXMgd2UnbGwgbmVlZCB0byBwYXJhbWV0ZXJpemUgdGhpc1xuICAgIGF3YWl0IGhlbHBlcnMuaW5pdERldmljZSh0aGlzLmFkYiwgdGhpcy5vcHRzKTtcblxuICAgIC8vIFByZXBhcmUgdGhlIGRldmljZSBieSBmb3J3YXJkaW5nIHRoZSBVaUF1dG9tYXRvcjIgcG9ydFxuICAgIC8vIFRoaXMgY2FsbCBtdXRhdGVzIHRoaXMub3B0cy5zeXN0ZW1Qb3J0IGlmIGl0IGlzIG5vdCBzZXQgZXhwbGljaXRseVxuICAgIGF3YWl0IHRoaXMuYWxsb2NhdGVTeXN0ZW1Qb3J0KCk7XG5cbiAgICAvLyBQcmVwYXJlIHRoZSBkZXZpY2UgYnkgZm9yd2FyZGluZyB0aGUgVWlBdXRvbWF0b3IyIE1KUEVHIHNlcnZlciBwb3J0IChpZlxuICAgIC8vIGFwcGxpY2FibGUpXG4gICAgYXdhaXQgdGhpcy5hbGxvY2F0ZU1qcGVnU2VydmVyUG9ydCgpO1xuXG4gICAgLy8gc2V0IHVwIHRoZSBtb2RpZmllZCBVaUF1dG9tYXRvcjIgc2VydmVyIGV0Y1xuICAgIGF3YWl0IHRoaXMuaW5pdFVpQXV0b21hdG9yMlNlcnZlcigpO1xuXG4gICAgLy8gU2hvdWxkIGJlIGFmdGVyIGluc3RhbGxpbmcgaW8uYXBwaXVtLnNldHRpbmdzIGluIGhlbHBlcnMuaW5pdERldmljZVxuICAgIGlmICh0aGlzLm9wdHMuZGlzYWJsZVdpbmRvd0FuaW1hdGlvbiAmJiAoYXdhaXQgdGhpcy5hZGIuZ2V0QXBpTGV2ZWwoKSA8IDI2KSkgeyAvLyBBUEkgbGV2ZWwgMjYgaXMgQW5kcm9pZCA4LjAuXG4gICAgICAvLyBHcmFudGluZyBhbmRyb2lkLnBlcm1pc3Npb24uU0VUX0FOSU1BVElPTl9TQ0FMRSBpcyBuZWNlc3NhcnkgdG8gaGFuZGxlIGFuaW1hdGlvbnMgdW5kZXIgQVBJIGxldmVsIDI2XG4gICAgICAvLyBSZWFkIGh0dHBzOi8vZ2l0aHViLmNvbS9hcHBpdW0vYXBwaXVtL3B1bGwvMTE2NDAjaXNzdWVjb21tZW50LTQzODI2MDQ3N1xuICAgICAgLy8gYC0tbm8td2luZG93LWFuaW1hdGlvbmAgd29ya3Mgb3ZlciBBbmRyb2lkIDggdG8gZGlzYWJsZSBhbGwgb2YgYW5pbWF0aW9uc1xuICAgICAgaWYgKGF3YWl0IHRoaXMuYWRiLmlzQW5pbWF0aW9uT24oKSkge1xuICAgICAgICB0aGlzLmxvZy5pbmZvKCdEaXNhYmxpbmcgYW5pbWF0aW9uIHZpYSBpby5hcHBpdW0uc2V0dGluZ3MnKTtcbiAgICAgICAgYXdhaXQgdGhpcy5hZGIuc2V0QW5pbWF0aW9uU3RhdGUoZmFsc2UpO1xuICAgICAgICB0aGlzLl93YXNXaW5kb3dBbmltYXRpb25EaXNhYmxlZCA9IHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmxvZy5pbmZvKCdXaW5kb3cgYW5pbWF0aW9uIGlzIGFscmVhZHkgZGlzYWJsZWQnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBzZXQgdXAgYXBwIHVuZGVyIHRlc3RcbiAgICAvLyBwcmVwYXJlIG91ciBhY3R1YWwgQVVULCBnZXQgaXQgb24gdGhlIGRldmljZSwgZXRjLi4uXG4gICAgYXdhaXQgdGhpcy5pbml0QVVUKCk7XG5cbiAgICAvLyBBZGRpbmcgQVVUIHBhY2thZ2UgbmFtZSBpbiB0aGUgY2FwYWJpbGl0aWVzIGlmIHBhY2thZ2UgbmFtZSBub3QgZXhpc3QgaW4gY2Fwc1xuICAgIGlmICghdGhpcy5jYXBzLmFwcFBhY2thZ2UgJiYgYXBwSW5mbykge1xuICAgICAgdGhpcy5jYXBzLmFwcFBhY2thZ2UgPSBhcHBJbmZvLmFwcFBhY2thZ2U7XG4gICAgfVxuXG4gICAgLy8gbGF1bmNoIFVpQXV0b21hdG9yMiBhbmQgd2FpdCB0aWxsIGl0cyBvbmxpbmUgYW5kIHdlIGhhdmUgYSBzZXNzaW9uXG4gICAgYXdhaXQgdGhpcy51aWF1dG9tYXRvcjIuc3RhcnRTZXNzaW9uKHRoaXMuY2Fwcyk7XG5cbiAgICBhd2FpdCB0aGlzLmFkZERldmljZUluZm9Ub0NhcHMoKTtcblxuICAgIC8vIFVubG9jayB0aGUgZGV2aWNlIGFmdGVyIHRoZSBzZXNzaW9uIGlzIHN0YXJ0ZWQuXG4gICAgaWYgKCF0aGlzLm9wdHMuc2tpcFVubG9jaykge1xuICAgICAgLy8gdW5sb2NrIHRoZSBkZXZpY2UgdG8gcHJlcGFyZSBpdCBmb3IgdGVzdGluZ1xuICAgICAgYXdhaXQgaGVscGVycy51bmxvY2sodGhpcywgdGhpcy5hZGIsIHRoaXMuY2Fwcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGAnc2tpcFVubG9jaycgY2FwYWJpbGl0eSBzZXQsIHNvIHNraXBwaW5nIGRldmljZSB1bmxvY2tgKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5pc0Nocm9tZVNlc3Npb24pIHsgLy8gc3RhcnQgYSBjaHJvbWVkcml2ZXIgc2Vzc2lvblxuICAgICAgYXdhaXQgdGhpcy5zdGFydENocm9tZVNlc3Npb24odGhpcyk7XG4gICAgfSBlbHNlIGlmICh0aGlzLm9wdHMuYXV0b0xhdW5jaCAmJiB0aGlzLm9wdHMuYXBwUGFja2FnZSkge1xuICAgICAgYXdhaXQgdGhpcy5lbnN1cmVBcHBTdGFydHMoKTtcbiAgICB9XG5cbiAgICAvLyBpZiB0aGUgaW5pdGlhbCBvcmllbnRhdGlvbiBpcyByZXF1ZXN0ZWQsIHNldCBpdFxuICAgIGlmICh1dGlsLmhhc1ZhbHVlKHRoaXMub3B0cy5vcmllbnRhdGlvbikpIHtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGBTZXR0aW5nIGluaXRpYWwgb3JpZW50YXRpb24gdG8gJyR7dGhpcy5vcHRzLm9yaWVudGF0aW9ufSdgKTtcbiAgICAgIGF3YWl0IHRoaXMuc2V0T3JpZW50YXRpb24odGhpcy5vcHRzLm9yaWVudGF0aW9uKTtcbiAgICB9XG5cbiAgICAvLyBpZiB3ZSB3YW50IHRvIGltbWVkaWF0ZWx5IGdldCBpbnRvIGEgd2Vidmlldywgc2V0IG91ciBjb250ZXh0XG4gICAgLy8gYXBwcm9wcmlhdGVseVxuICAgIGlmICh0aGlzLm9wdHMuYXV0b1dlYnZpZXcpIHtcbiAgICAgIGNvbnN0IHZpZXdOYW1lID0gdGhpcy5kZWZhdWx0V2Vidmlld05hbWUoKTtcbiAgICAgIGNvbnN0IHRpbWVvdXQgPSB0aGlzLm9wdHMuYXV0b1dlYnZpZXdUaW1lb3V0IHx8IDIwMDA7XG4gICAgICB0aGlzLmxvZy5pbmZvKGBTZXR0aW5nIGF1dG8gd2VidmlldyB0byBjb250ZXh0ICcke3ZpZXdOYW1lfScgd2l0aCB0aW1lb3V0ICR7dGltZW91dH1tc2ApO1xuICAgICAgYXdhaXQgcmV0cnlJbnRlcnZhbCh0aW1lb3V0IC8gNTAwLCA1MDAsIHRoaXMuc2V0Q29udGV4dC5iaW5kKHRoaXMpLCB2aWV3TmFtZSk7XG4gICAgfVxuXG4gICAgLy8gbm93IHRoYXQgZXZlcnl0aGluZyBoYXMgc3RhcnRlZCBzdWNjZXNzZnVsbHksIHR1cm4gb24gcHJveHlpbmcgc28gYWxsXG4gICAgLy8gc3Vic2VxdWVudCBzZXNzaW9uIHJlcXVlc3RzIGdvIHN0cmFpZ2h0IHRvL2Zyb20gdWlhdXRvbWF0b3IyXG4gICAgdGhpcy5qd3BQcm94eUFjdGl2ZSA9IHRydWU7XG4gIH1cblxuICBhc3luYyBhZGREZXZpY2VJbmZvVG9DYXBzICgpIHtcbiAgICBjb25zdCB7XG4gICAgICBhcGlWZXJzaW9uLFxuICAgICAgcGxhdGZvcm1WZXJzaW9uLFxuICAgICAgbWFudWZhY3R1cmVyLFxuICAgICAgbW9kZWwsXG4gICAgICByZWFsRGlzcGxheVNpemUsXG4gICAgICBkaXNwbGF5RGVuc2l0eSxcbiAgICB9ID0gYXdhaXQgdGhpcy5tb2JpbGVHZXREZXZpY2VJbmZvKCk7XG4gICAgdGhpcy5jYXBzLmRldmljZUFwaUxldmVsID0gcGFyc2VJbnQoYXBpVmVyc2lvbiwgMTApO1xuICAgIHRoaXMuY2Fwcy5wbGF0Zm9ybVZlcnNpb24gPSBwbGF0Zm9ybVZlcnNpb247XG4gICAgdGhpcy5jYXBzLmRldmljZVNjcmVlblNpemUgPSByZWFsRGlzcGxheVNpemU7XG4gICAgdGhpcy5jYXBzLmRldmljZVNjcmVlbkRlbnNpdHkgPSBkaXNwbGF5RGVuc2l0eTtcbiAgICB0aGlzLmNhcHMuZGV2aWNlTW9kZWwgPSBtb2RlbDtcbiAgICB0aGlzLmNhcHMuZGV2aWNlTWFudWZhY3R1cmVyID0gbWFudWZhY3R1cmVyO1xuICB9XG5cbiAgYXN5bmMgaW5pdFVpQXV0b21hdG9yMlNlcnZlciAoKSB7XG4gICAgLy8gYnJva2VuIG91dCBmb3IgcmVhZGFiaWxpdHlcbiAgICBjb25zdCB1aWF1dG9tYXRvcjJPcHRzID0ge1xuICAgICAgaG9zdDogdGhpcy5vcHRzLnJlbW90ZUFkYkhvc3QgfHwgdGhpcy5vcHRzLmhvc3QgfHwgTE9DQUxIT1NUX0lQNCxcbiAgICAgIHN5c3RlbVBvcnQ6IHRoaXMub3B0cy5zeXN0ZW1Qb3J0LFxuICAgICAgZGV2aWNlUG9ydDogREVWSUNFX1BPUlQsXG4gICAgICBhZGI6IHRoaXMuYWRiLFxuICAgICAgYXBrOiB0aGlzLm9wdHMuYXBwLFxuICAgICAgdG1wRGlyOiB0aGlzLm9wdHMudG1wRGlyLFxuICAgICAgYXBwUGFja2FnZTogdGhpcy5vcHRzLmFwcFBhY2thZ2UsXG4gICAgICBhcHBBY3Rpdml0eTogdGhpcy5vcHRzLmFwcEFjdGl2aXR5LFxuICAgICAgZGlzYWJsZVdpbmRvd0FuaW1hdGlvbjogISF0aGlzLm9wdHMuZGlzYWJsZVdpbmRvd0FuaW1hdGlvbixcbiAgICAgIGRpc2FibGVTdXBwcmVzc0FjY2Vzc2liaWxpdHlTZXJ2aWNlOiB0aGlzLm9wdHMuZGlzYWJsZVN1cHByZXNzQWNjZXNzaWJpbGl0eVNlcnZpY2UsXG4gICAgICByZWFkVGltZW91dDogdGhpcy5vcHRzLnVpYXV0b21hdG9yMlNlcnZlclJlYWRUaW1lb3V0LFxuICAgIH07XG4gICAgLy8gbm93IHRoYXQgd2UgaGF2ZSBwYWNrYWdlIGFuZCBhY3Rpdml0eSwgd2UgY2FuIGNyZWF0ZSBhbiBpbnN0YW5jZSBvZlxuICAgIC8vIHVpYXV0b21hdG9yMiB3aXRoIHRoZSBhcHByb3ByaWF0ZSBvcHRpb25zXG4gICAgdGhpcy51aWF1dG9tYXRvcjIgPSBuZXcgVWlBdXRvbWF0b3IyU2VydmVyKHRoaXMubG9nLCB1aWF1dG9tYXRvcjJPcHRzKTtcbiAgICB0aGlzLnByb3h5UmVxUmVzID0gdGhpcy51aWF1dG9tYXRvcjIucHJveHlSZXFSZXMuYmluZCh0aGlzLnVpYXV0b21hdG9yMik7XG4gICAgdGhpcy5wcm94eUNvbW1hbmQgPSB0aGlzLnVpYXV0b21hdG9yMi5wcm94eUNvbW1hbmQuYmluZCh0aGlzLnVpYXV0b21hdG9yMik7XG5cbiAgICBpZiAodGhpcy5vcHRzLnNraXBTZXJ2ZXJJbnN0YWxsYXRpb24pIHtcbiAgICAgIHRoaXMubG9nLmluZm8oYCdza2lwU2VydmVySW5zdGFsbGF0aW9uJyBpcyBzZXQuIFNraXBwaW5nIFVJQXV0b21hdG9yMiBzZXJ2ZXIgaW5zdGFsbGF0aW9uLmApO1xuICAgIH0gZWxzZSB7XG4gICAgICBhd2FpdCB0aGlzLnVpYXV0b21hdG9yMi5pbnN0YWxsU2VydmVyQXBrKHRoaXMub3B0cy51aWF1dG9tYXRvcjJTZXJ2ZXJJbnN0YWxsVGltZW91dCk7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLmFkYi5hZGRUb0RldmljZUlkbGVXaGl0ZWxpc3QoXG4gICAgICAgICAgU0VUVElOR1NfSEVMUEVSX1BLR19JRCwgU0VSVkVSX1BBQ0tBR0VfSUQsIFNFUlZFUl9URVNUX1BBQ0tBR0VfSUQsXG4gICAgICAgICk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRoaXMubG9nLndhcm4oYENhbm5vdCBhZGQgc2VydmVyIHBhY2thZ2VzIHRvIHRoZSBEb3plIHdoaXRlbGlzdC4gT3JpZ2luYWwgZXJyb3I6IGAgK1xuICAgICAgICAgIChlLnN0ZGVyciB8fCBlLm1lc3NhZ2UpKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBhc3luYyBpbml0QVVUICgpIHtcbiAgICAvLyBVbmluc3RhbGwgYW55IHVuaW5zdGFsbE90aGVyUGFja2FnZXMgd2hpY2ggd2VyZSBzcGVjaWZpZWQgaW4gY2Fwc1xuICAgIGlmICh0aGlzLm9wdHMudW5pbnN0YWxsT3RoZXJQYWNrYWdlcykge1xuICAgICAgYXdhaXQgaGVscGVycy51bmluc3RhbGxPdGhlclBhY2thZ2VzKFxuICAgICAgICB0aGlzLmFkYixcbiAgICAgICAgaGVscGVycy5wYXJzZUFycmF5KHRoaXMub3B0cy51bmluc3RhbGxPdGhlclBhY2thZ2VzKSxcbiAgICAgICAgW1NFVFRJTkdTX0hFTFBFUl9QS0dfSUQsIFNFUlZFUl9QQUNLQUdFX0lELCBTRVJWRVJfVEVTVF9QQUNLQUdFX0lEXVxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBJbnN0YWxsIGFueSBcIm90aGVyQXBwc1wiIHRoYXQgd2VyZSBzcGVjaWZpZWQgaW4gY2Fwc1xuICAgIGlmICh0aGlzLm9wdHMub3RoZXJBcHBzKSB7XG4gICAgICBsZXQgb3RoZXJBcHBzO1xuICAgICAgdHJ5IHtcbiAgICAgICAgb3RoZXJBcHBzID0gaGVscGVycy5wYXJzZUFycmF5KHRoaXMub3B0cy5vdGhlckFwcHMpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aGlzLmxvZy5lcnJvckFuZFRocm93KGBDb3VsZCBub3QgcGFyc2UgXCJvdGhlckFwcHNcIiBjYXBhYmlsaXR5OiAke2UubWVzc2FnZX1gKTtcbiAgICAgIH1cbiAgICAgIG90aGVyQXBwcyA9IGF3YWl0IEIuYWxsKG90aGVyQXBwc1xuICAgICAgICAubWFwKChhcHApID0+IHRoaXMuaGVscGVycy5jb25maWd1cmVBcHAoYXBwLCBbQVBLX0VYVEVOU0lPTiwgQVBLU19FWFRFTlNJT05dKSkpO1xuICAgICAgYXdhaXQgaGVscGVycy5pbnN0YWxsT3RoZXJBcGtzKG90aGVyQXBwcywgdGhpcy5hZGIsIHRoaXMub3B0cyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMub3B0cy5hcHApIHtcbiAgICAgIGlmICh0aGlzLm9wdHMubm9SZXNldCAmJiAhKGF3YWl0IHRoaXMuYWRiLmlzQXBwSW5zdGFsbGVkKHRoaXMub3B0cy5hcHBQYWNrYWdlKSlcbiAgICAgICAgICB8fCAhdGhpcy5vcHRzLm5vUmVzZXQpIHtcbiAgICAgICAgaWYgKCF0aGlzLm9wdHMubm9TaWduICYmICFhd2FpdCB0aGlzLmFkYi5jaGVja0Fwa0NlcnQodGhpcy5vcHRzLmFwcCwgdGhpcy5vcHRzLmFwcFBhY2thZ2UsIHtcbiAgICAgICAgICByZXF1aXJlRGVmYXVsdENlcnQ6IGZhbHNlLFxuICAgICAgICB9KSkge1xuICAgICAgICAgIGF3YWl0IGhlbHBlcnMuc2lnbkFwcCh0aGlzLmFkYiwgdGhpcy5vcHRzLmFwcCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLm9wdHMuc2tpcFVuaW5zdGFsbCkge1xuICAgICAgICAgIGF3YWl0IHRoaXMuYWRiLnVuaW5zdGFsbEFwayh0aGlzLm9wdHMuYXBwUGFja2FnZSk7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgaGVscGVycy5pbnN0YWxsQXBrKHRoaXMuYWRiLCB0aGlzLm9wdHMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5sb2cuZGVidWcoJ25vUmVzZXQgaGFzIGJlZW4gcmVxdWVzdGVkIGFuZCB0aGUgYXBwIGlzIGFscmVhZHkgaW5zdGFsbGVkLiBEb2luZyBub3RoaW5nJyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh0aGlzLm9wdHMuZnVsbFJlc2V0KSB7XG4gICAgICAgIHRoaXMubG9nLmVycm9yQW5kVGhyb3coJ0Z1bGwgcmVzZXQgcmVxdWlyZXMgYW4gYXBwIGNhcGFiaWxpdHksIHVzZSBmYXN0UmVzZXQgaWYgYXBwIGlzIG5vdCBwcm92aWRlZCcpO1xuICAgICAgfVxuICAgICAgdGhpcy5sb2cuZGVidWcoJ05vIGFwcCBjYXBhYmlsaXR5LiBBc3N1bWluZyBpdCBpcyBhbHJlYWR5IG9uIHRoZSBkZXZpY2UnKTtcbiAgICAgIGlmICh0aGlzLm9wdHMuZmFzdFJlc2V0ICYmIHRoaXMub3B0cy5hcHBQYWNrYWdlKSB7XG4gICAgICAgIGF3YWl0IGhlbHBlcnMucmVzZXRBcHAodGhpcy5hZGIsIHRoaXMub3B0cyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZW5zdXJlQXBwU3RhcnRzICgpIHtcbiAgICAvLyBtYWtlIHN1cmUgd2UgaGF2ZSBhbiBhY3Rpdml0eSBhbmQgcGFja2FnZSB0byB3YWl0IGZvclxuICAgIGNvbnN0IGFwcFdhaXRQYWNrYWdlID0gdGhpcy5vcHRzLmFwcFdhaXRQYWNrYWdlIHx8IHRoaXMub3B0cy5hcHBQYWNrYWdlO1xuICAgIGNvbnN0IGFwcFdhaXRBY3Rpdml0eSA9IHRoaXMub3B0cy5hcHBXYWl0QWN0aXZpdHkgfHwgdGhpcy5vcHRzLmFwcEFjdGl2aXR5O1xuXG4gICAgdGhpcy5sb2cuaW5mbyhgU3RhcnRpbmcgJyR7dGhpcy5vcHRzLmFwcFBhY2thZ2V9LyR7dGhpcy5vcHRzLmFwcEFjdGl2aXR5fSBgICtcbiAgICAgIGBhbmQgd2FpdGluZyBmb3IgJyR7YXBwV2FpdFBhY2thZ2V9LyR7YXBwV2FpdEFjdGl2aXR5fSdgKTtcblxuICAgIGlmICh0aGlzLmNhcHMuYW5kcm9pZENvdmVyYWdlKSB7XG4gICAgICB0aGlzLmxvZy5pbmZvKGBhbmRyb2lkQ292ZXJhZ2UgaXMgY29uZmlndXJlZC4gYCArXG4gICAgICAgIGAgU3RhcnRpbmcgaW5zdHJ1bWVudGF0aW9uIG9mICcke3RoaXMuY2Fwcy5hbmRyb2lkQ292ZXJhZ2V9Jy4uLmApO1xuICAgICAgYXdhaXQgdGhpcy5hZGIuYW5kcm9pZENvdmVyYWdlKHRoaXMuY2Fwcy5hbmRyb2lkQ292ZXJhZ2UsIGFwcFdhaXRQYWNrYWdlLCBhcHBXYWl0QWN0aXZpdHkpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodGhpcy5vcHRzLm5vUmVzZXQgJiYgIXRoaXMub3B0cy5mb3JjZUFwcExhdW5jaFxuICAgICAgICAmJiBhd2FpdCB0aGlzLmFkYi5wcm9jZXNzRXhpc3RzKHRoaXMub3B0cy5hcHBQYWNrYWdlKSkge1xuICAgICAgdGhpcy5sb2cuaW5mbyhgJyR7dGhpcy5vcHRzLmFwcFBhY2thZ2V9JyBpcyBhbHJlYWR5IHJ1bm5pbmcgYW5kIG5vUmVzZXQgaXMgZW5hYmxlZC4gYCArXG4gICAgICAgIGBTZXQgZm9yY2VBcHBMYXVuY2ggY2FwYWJpbGl0eSB0byB0cnVlIGlmIHRoZSBhcHAgbXVzdCBiZSBmb3JjZWZ1bGx5IHJlc3RhcnRlZCBvbiBzZXNzaW9uIHN0YXJ0dXAuYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGF3YWl0IHRoaXMuYWRiLnN0YXJ0QXBwKHtcbiAgICAgIHBrZzogdGhpcy5vcHRzLmFwcFBhY2thZ2UsXG4gICAgICBhY3Rpdml0eTogdGhpcy5vcHRzLmFwcEFjdGl2aXR5LFxuICAgICAgYWN0aW9uOiB0aGlzLm9wdHMuaW50ZW50QWN0aW9uIHx8ICdhbmRyb2lkLmludGVudC5hY3Rpb24uTUFJTicsXG4gICAgICBjYXRlZ29yeTogdGhpcy5vcHRzLmludGVudENhdGVnb3J5IHx8ICdhbmRyb2lkLmludGVudC5jYXRlZ29yeS5MQVVOQ0hFUicsXG4gICAgICBmbGFnczogdGhpcy5vcHRzLmludGVudEZsYWdzIHx8ICcweDEwMjAwMDAwJywgLy8gRkxBR19BQ1RJVklUWV9ORVdfVEFTSyB8IEZMQUdfQUNUSVZJVFlfUkVTRVRfVEFTS19JRl9ORUVERURcbiAgICAgIHdhaXRQa2c6IHRoaXMub3B0cy5hcHBXYWl0UGFja2FnZSxcbiAgICAgIHdhaXRBY3Rpdml0eTogdGhpcy5vcHRzLmFwcFdhaXRBY3Rpdml0eSxcbiAgICAgIHdhaXRGb3JMYXVuY2g6IHRoaXMub3B0cy5hcHBXYWl0Rm9yTGF1bmNoLFxuICAgICAgd2FpdER1cmF0aW9uOiB0aGlzLm9wdHMuYXBwV2FpdER1cmF0aW9uLFxuICAgICAgb3B0aW9uYWxJbnRlbnRBcmd1bWVudHM6IHRoaXMub3B0cy5vcHRpb25hbEludGVudEFyZ3VtZW50cyxcbiAgICAgIHN0b3BBcHA6IHRoaXMub3B0cy5mb3JjZUFwcExhdW5jaCB8fCAhdGhpcy5vcHRzLmRvbnRTdG9wQXBwT25SZXNldCxcbiAgICAgIHJldHJ5OiB0cnVlLFxuICAgICAgdXNlcjogdGhpcy5vcHRzLnVzZXJQcm9maWxlLFxuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgZGVsZXRlU2Vzc2lvbiAoKSB7XG4gICAgdGhpcy5sb2cuZGVidWcoJ0RlbGV0aW5nIFVpQXV0b21hdG9yMiBzZXNzaW9uJyk7XG5cbiAgICBjb25zdCBzY3JlZW5SZWNvcmRpbmdTdG9wVGFza3MgPSBbYXN5bmMgKCkgPT4ge1xuICAgICAgaWYgKCFfLmlzRW1wdHkodGhpcy5fc2NyZWVuUmVjb3JkaW5nUHJvcGVydGllcykpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5zdG9wUmVjb3JkaW5nU2NyZWVuKCk7XG4gICAgICB9XG4gICAgfSwgYXN5bmMgKCkgPT4ge1xuICAgICAgaWYgKGF3YWl0IHRoaXMubW9iaWxlSXNNZWRpYVByb2plY3Rpb25SZWNvcmRpbmdSdW5uaW5nKCkpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5tb2JpbGVTdG9wTWVkaWFQcm9qZWN0aW9uUmVjb3JkaW5nKCk7XG4gICAgICB9XG4gICAgfSwgYXN5bmMgKCkgPT4ge1xuICAgICAgaWYgKCFfLmlzRW1wdHkodGhpcy5fc2NyZWVuU3RyZWFtaW5nUHJvcHMpKSB7XG4gICAgICAgIGF3YWl0IHRoaXMubW9iaWxlU3RvcFNjcmVlblN0cmVhbWluZygpO1xuICAgICAgfVxuICAgIH1dO1xuXG4gICAgYXdhaXQgYW5kcm9pZEhlbHBlcnMucmVtb3ZlQWxsU2Vzc2lvbldlYlNvY2tldEhhbmRsZXJzKHRoaXMuc2VydmVyLCB0aGlzLnNlc3Npb25JZCk7XG5cbiAgICBpZiAodGhpcy51aWF1dG9tYXRvcjIpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRoaXMuc3RvcENocm9tZWRyaXZlclByb3hpZXMoKTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICB0aGlzLmxvZy53YXJuKGBVbmFibGUgdG8gc3RvcCBDaHJvbWVEcml2ZXIgcHJveGllczogJHtlcnIubWVzc2FnZX1gKTtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLmp3cFByb3h5QWN0aXZlKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy51aWF1dG9tYXRvcjIuZGVsZXRlU2Vzc2lvbigpO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICB0aGlzLmxvZy53YXJuKGBVbmFibGUgdG8gcHJveHkgZGVsZXRlU2Vzc2lvbiB0byBVaUF1dG9tYXRvcjI6ICR7ZXJyLm1lc3NhZ2V9YCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHRoaXMudWlhdXRvbWF0b3IyID0gbnVsbDtcbiAgICB9XG4gICAgdGhpcy5qd3BQcm94eUFjdGl2ZSA9IGZhbHNlO1xuXG4gICAgaWYgKHRoaXMuYWRiKSB7XG4gICAgICBhd2FpdCBCLmFsbChzY3JlZW5SZWNvcmRpbmdTdG9wVGFza3MubWFwKCh0YXNrKSA9PiB7XG4gICAgICAgIChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHRhc2soKTtcbiAgICAgICAgICB9IGNhdGNoIChpZ24pIHt9XG4gICAgICAgIH0pKCk7XG4gICAgICB9KSk7XG5cbiAgICAgIGlmICh0aGlzLmNhcHMuYW5kcm9pZENvdmVyYWdlKSB7XG4gICAgICAgIHRoaXMubG9nLmluZm8oJ1NodXR0aW5nIGRvd24gdGhlIGFkYiBwcm9jZXNzIG9mIGluc3RydW1lbnRhdGlvbi4uLicpO1xuICAgICAgICBhd2FpdCB0aGlzLmFkYi5lbmRBbmRyb2lkQ292ZXJhZ2UoKTtcbiAgICAgICAgLy8gVXNlIHRoaXMgYnJvYWRjYXN0IGludGVudCB0byBub3RpZnkgaXQncyB0aW1lIHRvIGR1bXAgY292ZXJhZ2UgdG8gZmlsZVxuICAgICAgICBpZiAodGhpcy5jYXBzLmFuZHJvaWRDb3ZlcmFnZUVuZEludGVudCkge1xuICAgICAgICAgIHRoaXMubG9nLmluZm8oYFNlbmRpbmcgaW50ZW50IGJyb2FkY2FzdCAnJHt0aGlzLmNhcHMuYW5kcm9pZENvdmVyYWdlRW5kSW50ZW50fScgYXQgdGhlIGVuZCBvZiBpbnN0cnVtZW50aW5nLmApO1xuICAgICAgICAgIGF3YWl0IHRoaXMuYWRiLmJyb2FkY2FzdCh0aGlzLmNhcHMuYW5kcm9pZENvdmVyYWdlRW5kSW50ZW50KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmxvZy53YXJuKCdObyBhbmRyb2lkQ292ZXJhZ2VFbmRJbnRlbnQgaXMgY29uZmlndXJlZCBpbiBjYXBzLiBQb3NzaWJseSB5b3UgY2Fubm90IGdldCBjb3ZlcmFnZSBmaWxlLicpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5vcHRzLmFwcFBhY2thZ2UpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzQ2hyb21lU2Vzc2lvbiAmJiAoKCF0aGlzLm9wdHMuZG9udFN0b3BBcHBPblJlc2V0ICYmICF0aGlzLm9wdHMubm9SZXNldClcbiAgICAgICAgICAgIHx8ICh0aGlzLm9wdHMubm9SZXNldCAmJiB0aGlzLm9wdHMuc2hvdWxkVGVybWluYXRlQXBwKSkpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5hZGIuZm9yY2VTdG9wKHRoaXMub3B0cy5hcHBQYWNrYWdlKTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMubG9nLndhcm4oYFVuYWJsZSB0byBmb3JjZSBzdG9wIGFwcDogJHtlcnIubWVzc2FnZX1gKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMub3B0cy5mdWxsUmVzZXQgJiYgIXRoaXMub3B0cy5za2lwVW5pbnN0YWxsKSB7XG4gICAgICAgICAgdGhpcy5sb2cuZGVidWcoYENhcGFiaWxpdHkgJ2Z1bGxSZXNldCcgc2V0IHRvICd0cnVlJywgVW5pbnN0YWxsaW5nICcke3RoaXMub3B0cy5hcHBQYWNrYWdlfSdgKTtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5hZGIudW5pbnN0YWxsQXBrKHRoaXMub3B0cy5hcHBQYWNrYWdlKTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMubG9nLndhcm4oYFVuYWJsZSB0byB1bmluc3RhbGwgYXBwOiAke2Vyci5tZXNzYWdlfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gVGhpcyB2YWx1ZSBjYW4gYmUgdHJ1ZSBpZiB0ZXN0IHRhcmdldCBkZXZpY2UgaXMgPD0gMjZcbiAgICAgIGlmICh0aGlzLl93YXNXaW5kb3dBbmltYXRpb25EaXNhYmxlZCkge1xuICAgICAgICB0aGlzLmxvZy5pbmZvKCdSZXN0b3Jpbmcgd2luZG93IGFuaW1hdGlvbiBzdGF0ZScpO1xuICAgICAgICBhd2FpdCB0aGlzLmFkYi5zZXRBbmltYXRpb25TdGF0ZSh0cnVlKTtcbiAgICAgIH1cbiAgICAgIGF3YWl0IHRoaXMuYWRiLnN0b3BMb2djYXQoKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRoaXMucmVsZWFzZVN5c3RlbVBvcnQoKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHRoaXMubG9nLndhcm4oYFVuYWJsZSB0byByZW1vdmUgc3lzdGVtIHBvcnQgZm9yd2FyZDogJHtlcnJvci5tZXNzYWdlfWApO1xuICAgICAgICAvLyBJZ25vcmUsIHRoaXMgYmxvY2sgd2lsbCBhbHNvIGJlIGNhbGxlZCB3aGVuIHdlIGZhbGwgaW4gY2F0Y2ggYmxvY2tcbiAgICAgICAgLy8gYW5kIGJlZm9yZSBldmVuIHBvcnQgZm9yd2FyZC5cbiAgICAgIH1cbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRoaXMucmVsZWFzZU1qcGVnU2VydmVyUG9ydCgpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgdGhpcy5sb2cud2FybihgVW5hYmxlIHRvIHJlbW92ZSBNSlBFRyBzZXJ2ZXIgcG9ydCBmb3J3YXJkOiAke2Vycm9yLm1lc3NhZ2V9YCk7XG4gICAgICAgIC8vIElnbm9yZSwgdGhpcyBibG9jayB3aWxsIGFsc28gYmUgY2FsbGVkIHdoZW4gd2UgZmFsbCBpbiBjYXRjaCBibG9ja1xuICAgICAgICAvLyBhbmQgYmVmb3JlIGV2ZW4gcG9ydCBmb3J3YXJkLlxuICAgICAgfVxuXG4gICAgICBpZiAoYXdhaXQgdGhpcy5hZGIuZ2V0QXBpTGV2ZWwoKSA+PSAyOCkgeyAvLyBBbmRyb2lkIFBcbiAgICAgICAgdGhpcy5sb2cuaW5mbygnUmVzdG9yaW5nIGhpZGRlbiBhcGkgcG9saWN5IHRvIHRoZSBkZXZpY2UgZGVmYXVsdCBjb25maWd1cmF0aW9uJyk7XG4gICAgICAgIGF3YWl0IHRoaXMuYWRiLnNldERlZmF1bHRIaWRkZW5BcGlQb2xpY3koISF0aGlzLm9wdHMuaWdub3JlSGlkZGVuQXBpUG9saWN5RXJyb3IpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5vcHRzLnJlYm9vdCkge1xuICAgICAgICBsZXQgYXZkTmFtZSA9IHRoaXMub3B0cy5hdmQucmVwbGFjZSgnQCcsICcnKTtcbiAgICAgICAgdGhpcy5sb2cuZGVidWcoYENsb3NpbmcgZW11bGF0b3IgJyR7YXZkTmFtZX0nYCk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy5hZGIua2lsbEVtdWxhdG9yKGF2ZE5hbWUpO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICB0aGlzLmxvZy53YXJuKGBVbmFibGUgdG8gY2xvc2UgZW11bGF0b3I6ICR7ZXJyLm1lc3NhZ2V9YCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHRoaXMubWpwZWdTdHJlYW0pIHtcbiAgICAgIHRoaXMubG9nLmluZm8oJ0Nsb3NpbmcgTUpQRUcgc3RyZWFtJyk7XG4gICAgICB0aGlzLm1qcGVnU3RyZWFtLnN0b3AoKTtcbiAgICB9XG4gICAgYXdhaXQgc3VwZXIuZGVsZXRlU2Vzc2lvbigpO1xuICB9XG5cbiAgYXN5bmMgY2hlY2tBcHBQcmVzZW50ICgpIHtcbiAgICB0aGlzLmxvZy5kZWJ1ZygnQ2hlY2tpbmcgd2hldGhlciBhcHAgaXMgYWN0dWFsbHkgcHJlc2VudCcpO1xuICAgIGlmICghKGF3YWl0IGZzLmV4aXN0cyh0aGlzLm9wdHMuYXBwKSkpIHtcbiAgICAgIHRoaXMubG9nLmVycm9yQW5kVGhyb3coYENvdWxkIG5vdCBmaW5kIGFwcCBhcGsgYXQgJyR7dGhpcy5vcHRzLmFwcH0nYCk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgb25TZXR0aW5nc1VwZGF0ZSAoKSB7XG4gICAgLy8gaW50ZW50aW9uYWxseSBkbyBub3RoaW5nIGhlcmUsIHNpbmNlIGNvbW1hbmRzLnVwZGF0ZVNldHRpbmdzIHByb3hpZXNcbiAgICAvLyBzZXR0aW5ncyB0byB0aGUgdWlhdXRvMiBzZXJ2ZXIgYWxyZWFkeVxuICB9XG5cbiAgLy8gTmVlZCB0byBvdmVycmlkZSBhbmRyb2lkLWRyaXZlcidzIHZlcnNpb24gb2YgdGhpcyBzaW5jZSB3ZSBkb24ndCBhY3R1YWxseVxuICAvLyBoYXZlIGEgYm9vdHN0cmFwOyBpbnN0ZWFkIHdlIGp1c3QgcmVzdGFydCBhZGIgYW5kIHJlLWZvcndhcmQgdGhlIFVpQXV0b21hdG9yMlxuICAvLyBwb3J0XG4gIGFzeW5jIHdyYXBCb290c3RyYXBEaXNjb25uZWN0ICh3cmFwcGVkKSB7XG4gICAgYXdhaXQgd3JhcHBlZCgpO1xuICAgIGF3YWl0IHRoaXMuYWRiLnJlc3RhcnQoKTtcbiAgICBhd2FpdCB0aGlzLmFsbG9jYXRlU3lzdGVtUG9ydCgpO1xuICAgIGF3YWl0IHRoaXMuYWxsb2NhdGVNanBlZ1NlcnZlclBvcnQoKTtcbiAgfVxuXG4gIHByb3h5QWN0aXZlIChzZXNzaW9uSWQpIHtcbiAgICBzdXBlci5wcm94eUFjdGl2ZShzZXNzaW9uSWQpO1xuXG4gICAgLy8gd2UgYWx3YXlzIGhhdmUgYW4gYWN0aXZlIHByb3h5IHRvIHRoZSBVaUF1dG9tYXRvcjIgc2VydmVyXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBjYW5Qcm94eSAoc2Vzc2lvbklkKSB7XG4gICAgc3VwZXIuY2FuUHJveHkoc2Vzc2lvbklkKTtcblxuICAgIC8vIHdlIGNhbiBhbHdheXMgcHJveHkgdG8gdGhlIHVpYXV0b21hdG9yMiBzZXJ2ZXJcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGdldFByb3h5QXZvaWRMaXN0IChzZXNzaW9uSWQpIHtcbiAgICBzdXBlci5nZXRQcm94eUF2b2lkTGlzdChzZXNzaW9uSWQpO1xuICAgIC8vIHdlIGFyZSBtYWludGFpbmluZyB0d28gc2V0cyBvZiBOT19QUk9YWSBsaXN0cywgb25lIGZvciBjaHJvbWVkcml2ZXIoQ0hST01FX05PX1BST1hZKVxuICAgIC8vIGFuZCBvbmUgZm9yIHVpYXV0b21hdG9yMihOT19QUk9YWSksIGJhc2VkIG9uIGN1cnJlbnQgY29udGV4dCB3aWxsIHJldHVybiByZWxhdGVkIE5PX1BST1hZIGxpc3RcbiAgICBpZiAodXRpbC5oYXNWYWx1ZSh0aGlzLmNocm9tZWRyaXZlcikpIHtcbiAgICAgIC8vIGlmIHRoZSBjdXJyZW50IGNvbnRleHQgaXMgd2VidmlldyhjaHJvbWVkcml2ZXIpLCB0aGVuIHJldHVybiBDSFJPTUVfTk9fUFJPWFkgbGlzdFxuICAgICAgdGhpcy5qd3BQcm94eUF2b2lkID0gQ0hST01FX05PX1BST1hZO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmp3cFByb3h5QXZvaWQgPSBOT19QUk9YWTtcbiAgICB9XG4gICAgaWYgKHRoaXMub3B0cy5uYXRpdmVXZWJTY3JlZW5zaG90KSB7XG4gICAgICB0aGlzLmp3cFByb3h5QXZvaWQgPSBbLi4udGhpcy5qd3BQcm94eUF2b2lkLCBbJ0dFVCcsIG5ldyBSZWdFeHAoJ14vc2Vzc2lvbi9bXi9dKy9zY3JlZW5zaG90JyldXTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5qd3BQcm94eUF2b2lkO1xuICB9XG5cbiAgZ2V0IGlzQ2hyb21lU2Vzc2lvbiAoKSB7XG4gICAgcmV0dXJuIGhlbHBlcnMuaXNDaHJvbWVCcm93c2VyKHRoaXMub3B0cy5icm93c2VyTmFtZSk7XG4gIH1cbn1cblxuLy8gZmlyc3QgYWRkIHRoZSBhbmRyb2lkLWRyaXZlciBjb21tYW5kcyB3aGljaCB3ZSB3aWxsIGZhbGwgYmFjayB0b1xuZm9yIChsZXQgW2NtZCwgZm5dIG9mIF8udG9QYWlycyhhbmRyb2lkQ29tbWFuZHMpKSB7XG4gIEFuZHJvaWRVaWF1dG9tYXRvcjJEcml2ZXIucHJvdG90eXBlW2NtZF0gPSBmbjtcbn1cblxuLy8gdGhlbiBvdmVyd3JpdGUgd2l0aCBhbnkgdWlhdXRvbWF0b3IyLXNwZWNpZmljIGNvbW1hbmRzXG5mb3IgKGxldCBbY21kLCBmbl0gb2YgXy50b1BhaXJzKGNvbW1hbmRzKSkge1xuICBBbmRyb2lkVWlhdXRvbWF0b3IyRHJpdmVyLnByb3RvdHlwZVtjbWRdID0gZm47XG59XG5cbmV4cG9ydCB7IEFuZHJvaWRVaWF1dG9tYXRvcjJEcml2ZXIgfTtcbmV4cG9ydCBkZWZhdWx0IEFuZHJvaWRVaWF1dG9tYXRvcjJEcml2ZXI7XG4iXSwibWFwcGluZ3Mi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LEVBQ3pELENBQUMsS0FBSyxFQUFFLElBQUlBLE1BQU0sQ0FBQywwQ0FBMEMsQ0FBQyxDQUFDLEVBQy9ELENBQUMsS0FBSyxFQUFFLElBQUlBLE1BQU0sQ0FBQyx3Q0FBd0MsQ0FBQyxDQUFDLEVBQzdELENBQUMsS0FBSyxFQUFFLElBQUlBLE1BQU0sQ0FBQywyQkFBMkIsQ0FBQyxDQUFDLEVBQ2hELENBQUMsS0FBSyxFQUFFLElBQUlBLE1BQU0sQ0FBQywwQkFBMEIsQ0FBQyxDQUFDLEVBQy9DLENBQUMsS0FBSyxFQUFFLElBQUlBLE1BQU0sQ0FBQyxvQ0FBb0MsQ0FBQyxDQUFDLEVBQ3pELENBQUMsS0FBSyxFQUFFLElBQUlBLE1BQU0sQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDLEVBQ2pELENBQUMsS0FBSyxFQUFFLElBQUlBLE1BQU0sQ0FBQywwQkFBMEIsQ0FBQyxDQUFDLEVBQy9DLENBQUMsS0FBSyxFQUFFLElBQUlBLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLEVBQzFDLENBQUMsTUFBTSxFQUFFLElBQUlBLE1BQU0sQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDLEVBQ3BELENBQUMsTUFBTSxFQUFFLElBQUlBLE1BQU0sQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDLEVBQy9DLENBQUMsTUFBTSxFQUFFLElBQUlBLE1BQU0sQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDLEVBQ25ELENBQUMsTUFBTSxFQUFFLElBQUlBLE1BQU0sQ0FBQywwQkFBMEIsQ0FBQyxDQUFDLEVBQ2hELENBQUMsTUFBTSxFQUFFLElBQUlBLE1BQU0sQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDLEVBQ25FLENBQUMsTUFBTSxFQUFFLElBQUlBLE1BQU0sQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDLEVBQ3hELENBQUMsTUFBTSxFQUFFLElBQUlBLE1BQU0sQ0FBQyx1Q0FBdUMsQ0FBQyxDQUFDLEVBQzdELENBQUMsTUFBTSxFQUFFLElBQUlBLE1BQU0sQ0FBQyxzREFBc0QsQ0FBQyxDQUFDLEVBQzVFLENBQUMsTUFBTSxFQUFFLElBQUlBLE1BQU0sQ0FB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
758
+ AndroidUiautomator2Driver.newMethodMap = method_map_1.newMethodMap;
759
+ AndroidUiautomator2Driver.executeMethodMap = execute_method_map_1.executeMethodMap;
760
+ require("./commands");
761
+ //# sourceMappingURL=driver.js.map