appium-uiautomator2-driver 2.29.11 → 2.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/build/index.d.ts +4 -0
  3. package/build/index.d.ts.map +1 -0
  4. package/build/index.js +8 -15
  5. package/build/index.js.map +1 -0
  6. package/build/lib/commands/actions.d.ts +2 -0
  7. package/build/lib/commands/actions.d.ts.map +1 -0
  8. package/build/lib/commands/actions.js +67 -62
  9. package/build/lib/commands/actions.js.map +1 -1
  10. package/build/lib/commands/alert.d.ts +2 -0
  11. package/build/lib/commands/alert.d.ts.map +1 -0
  12. package/build/lib/commands/alert.js +28 -26
  13. package/build/lib/commands/alert.js.map +1 -1
  14. package/build/lib/commands/app-strings.d.ts +3 -0
  15. package/build/lib/commands/app-strings.d.ts.map +1 -0
  16. package/build/lib/commands/app-strings.js +86 -57
  17. package/build/lib/commands/app-strings.js.map +1 -1
  18. package/build/lib/commands/battery.d.ts +2 -0
  19. package/build/lib/commands/battery.d.ts.map +1 -0
  20. package/build/lib/commands/battery.js +26 -16
  21. package/build/lib/commands/battery.js.map +1 -1
  22. package/build/lib/commands/element.d.ts +2 -0
  23. package/build/lib/commands/element.d.ts.map +1 -0
  24. package/build/lib/commands/element.js +140 -159
  25. package/build/lib/commands/element.js.map +1 -1
  26. package/build/lib/commands/find.d.ts +2 -0
  27. package/build/lib/commands/find.d.ts.map +1 -0
  28. package/build/lib/commands/find.js +39 -25
  29. package/build/lib/commands/find.js.map +1 -1
  30. package/build/lib/commands/general.d.ts +4 -0
  31. package/build/lib/commands/general.d.ts.map +1 -0
  32. package/build/lib/commands/general.js +217 -215
  33. package/build/lib/commands/general.js.map +1 -1
  34. package/build/lib/commands/gestures.d.ts +2 -0
  35. package/build/lib/commands/gestures.d.ts.map +1 -0
  36. package/build/lib/commands/gestures.js +206 -193
  37. package/build/lib/commands/gestures.js.map +1 -1
  38. package/build/lib/commands/index.d.ts +2 -0
  39. package/build/lib/commands/index.d.ts.map +1 -0
  40. package/build/lib/commands/index.js +13 -22
  41. package/build/lib/commands/index.js.map +1 -1
  42. package/build/lib/commands/mixins.d.ts +84 -0
  43. package/build/lib/commands/mixins.d.ts.map +1 -0
  44. package/build/lib/commands/mixins.js +23 -0
  45. package/build/lib/commands/mixins.js.map +1 -0
  46. package/build/lib/commands/screenshot.d.ts +2 -0
  47. package/build/lib/commands/screenshot.d.ts.map +1 -0
  48. package/build/lib/commands/screenshot.js +77 -62
  49. package/build/lib/commands/screenshot.js.map +1 -1
  50. package/build/lib/commands/touch.d.ts +2 -0
  51. package/build/lib/commands/touch.d.ts.map +1 -0
  52. package/build/lib/commands/touch.js +48 -38
  53. package/build/lib/commands/touch.js.map +1 -1
  54. package/build/lib/commands/types.d.ts +452 -0
  55. package/build/lib/commands/types.d.ts.map +1 -0
  56. package/build/lib/commands/types.js +3 -0
  57. package/build/lib/commands/types.js.map +1 -0
  58. package/build/lib/commands/viewport.d.ts +2 -0
  59. package/build/lib/commands/viewport.d.ts.map +1 -0
  60. package/build/lib/commands/viewport.js +37 -35
  61. package/build/lib/commands/viewport.js.map +1 -1
  62. package/build/lib/constraints.d.ts +334 -0
  63. package/build/lib/constraints.d.ts.map +1 -0
  64. package/build/lib/constraints.js +51 -0
  65. package/build/lib/constraints.js.map +1 -0
  66. package/build/lib/css-converter.d.ts +45 -0
  67. package/build/lib/css-converter.d.ts.map +1 -0
  68. package/build/lib/css-converter.js +272 -175
  69. package/build/lib/css-converter.js.map +1 -1
  70. package/build/lib/driver.d.ts +912 -0
  71. package/build/lib/driver.d.ts.map +1 -0
  72. package/build/lib/driver.js +738 -482
  73. package/build/lib/driver.js.map +1 -1
  74. package/build/lib/execute-method-map.d.ts +477 -0
  75. package/build/lib/execute-method-map.d.ts.map +1 -0
  76. package/build/lib/execute-method-map.js +542 -0
  77. package/build/lib/execute-method-map.js.map +1 -0
  78. package/build/lib/extensions.d.ts +3 -0
  79. package/build/lib/extensions.d.ts.map +1 -0
  80. package/build/lib/extensions.js +7 -9
  81. package/build/lib/extensions.js.map +1 -1
  82. package/build/lib/helpers.d.ts +7 -0
  83. package/build/lib/helpers.d.ts.map +1 -0
  84. package/build/lib/helpers.js +36 -29
  85. package/build/lib/helpers.js.map +1 -1
  86. package/build/lib/logger.d.ts +3 -0
  87. package/build/lib/logger.d.ts.map +1 -0
  88. package/build/lib/logger.js +5 -10
  89. package/build/lib/logger.js.map +1 -1
  90. package/build/lib/method-map.d.ts +389 -0
  91. package/build/lib/method-map.d.ts.map +1 -0
  92. package/build/lib/method-map.js +11 -17
  93. package/build/lib/method-map.js.map +1 -1
  94. package/build/lib/types.d.ts +45 -0
  95. package/build/lib/types.d.ts.map +1 -0
  96. package/build/lib/types.js +3 -0
  97. package/build/lib/types.js.map +1 -0
  98. package/build/lib/uiautomator2.d.ts +45 -0
  99. package/build/lib/uiautomator2.d.ts.map +1 -0
  100. package/build/lib/uiautomator2.js +340 -299
  101. package/build/lib/uiautomator2.js.map +1 -1
  102. package/build/lib/utils.d.ts +10 -0
  103. package/build/lib/utils.d.ts.map +1 -0
  104. package/build/lib/utils.js +23 -16
  105. package/build/lib/utils.js.map +1 -1
  106. package/build/tsconfig.tsbuildinfo +1 -0
  107. package/index.js +5 -3
  108. package/lib/commands/actions.js +115 -101
  109. package/lib/commands/alert.js +36 -44
  110. package/lib/commands/app-strings.js +79 -58
  111. package/lib/commands/battery.js +27 -28
  112. package/lib/commands/element.js +231 -134
  113. package/lib/commands/find.js +40 -21
  114. package/lib/commands/general.js +271 -336
  115. package/lib/commands/gestures.js +252 -366
  116. package/lib/commands/index.js +11 -31
  117. package/lib/commands/mixins.ts +167 -0
  118. package/lib/commands/screenshot.js +80 -76
  119. package/lib/commands/touch.js +64 -31
  120. package/lib/commands/types.ts +473 -0
  121. package/lib/commands/viewport.js +43 -31
  122. package/lib/constraints.ts +53 -0
  123. package/lib/css-converter.js +9 -1
  124. package/lib/{driver.js → driver.ts} +383 -225
  125. package/lib/execute-method-map.ts +573 -0
  126. package/lib/method-map.ts +11 -0
  127. package/lib/types.ts +59 -0
  128. package/lib/uiautomator2.js +21 -2
  129. package/lib/utils.js +2 -2
  130. package/npm-shrinkwrap.json +363 -492
  131. package/package.json +95 -69
  132. package/build/lib/desired-caps.js +0 -71
  133. package/build/lib/desired-caps.js.map +0 -1
  134. package/lib/desired-caps.js +0 -70
  135. package/lib/method-map.js +0 -11
@@ -1,520 +1,776 @@
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]);
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
+ }
56
182
  }
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;
183
+ validateDesiredCaps(caps) {
184
+ return (driver_1.BaseDriver.prototype.validateDesiredCaps.call(this, caps) &&
185
+ appium_android_driver_1.androidHelpers.validateDesiredCaps(caps));
117
186
  }
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}`;
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
+ }
148
251
  }
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);
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 };
161
259
  }
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;
260
+ get driverData() {
261
+ // TODO fill out resource info here
262
+ return {};
175
263
  }
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));
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 };
180
269
  }
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);
270
+ isEmulator() {
271
+ return helpers.isEmulator(this.adb, this.opts);
186
272
  }
187
- }
188
- async releaseMjpegServerPort() {
189
- if (this.opts.mjpegServerPort) {
190
- await this.adb.removePortForward(this.opts.mjpegServerPort);
273
+ setAvdFromCapabilities(caps) {
274
+ if (this.opts.avd) {
275
+ this.log.info('avd name defined, ignoring device name and platform version');
276
+ }
277
+ else {
278
+ if (!caps.deviceName) {
279
+ this.log.errorAndThrow('avd or deviceName should be specified when reboot option is enables');
280
+ throw new Error(); // unreachable
281
+ }
282
+ if (!caps.platformVersion) {
283
+ this.log.errorAndThrow('avd or platformVersion should be specified when reboot option is enabled');
284
+ throw new Error(); // unreachable
285
+ }
286
+ const avdDevice = caps.deviceName.replace(/[^a-zA-Z0-9_.]/g, '-');
287
+ this.opts.avd = `${avdDevice}__${caps.platformVersion}`;
288
+ }
191
289
  }
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.');
290
+ async allocateSystemPort() {
291
+ const forwardPort = async (localPort) => {
292
+ this.log.debug(`Forwarding UiAutomator2 Server port ${DEVICE_PORT} to local port ${localPort}`);
293
+ if ((await (0, portscanner_1.checkPortStatus)(localPort, LOCALHOST_IP4)) === 'open') {
294
+ this.log.errorAndThrow(`UiAutomator2 Server cannot start because the local port #${localPort} is busy. ` +
295
+ `Make sure the port you provide via 'systemPort' capability is not occupied. ` +
296
+ `This situation might often be a result of an inaccurate sessions management, e.g. ` +
297
+ `old automation sessions on the same device must always be closed before starting new ones.`);
298
+ }
299
+ await this.adb.forwardPort(localPort, DEVICE_PORT);
300
+ };
301
+ if (this.systemPort) {
302
+ this._hasSystemPortInCaps = true;
303
+ return await forwardPort(this.systemPort);
304
+ }
305
+ await DEVICE_PORT_ALLOCATION_GUARD(async () => {
306
+ const [startPort, endPort] = DEVICE_PORT_RANGE;
307
+ try {
308
+ this.systemPort = await (0, portscanner_1.findAPortNotInUse)(startPort, endPort);
309
+ }
310
+ catch (e) {
311
+ this.log.errorAndThrow(`Cannot find any free port in range ${startPort}..${endPort}}. ` +
312
+ `Please set the available port number by providing the systemPort capability or ` +
313
+ `double check the processes that are locking ports within this range and terminate ` +
314
+ `these which are not needed anymore`);
315
+ throw new Error(); // unreachable
316
+ }
317
+ await forwardPort(this.systemPort);
318
+ });
204
319
  }
205
- if (apiLevel >= 28) {
206
- this.log.info('Relaxing hidden api policy');
207
- await this.adb.setHiddenApiPolicy('1', !!this.opts.ignoreHiddenApiPolicyError);
320
+ async releaseSystemPort() {
321
+ if (!this.systemPort || !this.adb) {
322
+ return;
323
+ }
324
+ if (this._hasSystemPortInCaps) {
325
+ await this.adb.removePortForward(this.systemPort);
326
+ }
327
+ else {
328
+ await DEVICE_PORT_ALLOCATION_GUARD(async () => await this.adb.removePortForward(this.systemPort));
329
+ }
208
330
  }
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
- }
331
+ async allocateMjpegServerPort() {
332
+ if (this.opts.mjpegServerPort) {
333
+ this.log.debug(`MJPEG broadcasting requested, forwarding MJPEG server port ${MJPEG_SERVER_DEVICE_PORT} ` +
334
+ `to local port ${this.opts.mjpegServerPort}`);
335
+ await this.adb.forwardPort(this.opts.mjpegServerPort, MJPEG_SERVER_DEVICE_PORT);
336
+ }
216
337
  }
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
- }
338
+ async releaseMjpegServerPort() {
339
+ if (this.opts.mjpegServerPort) {
340
+ await this.adb.removePortForward(this.opts.mjpegServerPort);
341
+ }
233
342
  }
234
- await this.initAUT();
235
- if (!this.caps.appPackage && appInfo) {
236
- this.caps.appPackage = appInfo.appPackage;
343
+ async startUiAutomator2Session(caps) {
344
+ // get device udid for this session
345
+ const { udid, emPort } = await helpers.getDeviceInfoFromCaps(this.opts);
346
+ this.opts.udid = udid;
347
+ // @ts-expect-error do not put random stuff on opts
348
+ this.opts.emPort = emPort;
349
+ // now that we know our java version and device info, we can create our
350
+ // ADB instance
351
+ this.adb = await appium_android_driver_1.androidHelpers.createADB(this.opts);
352
+ const apiLevel = await this.adb.getApiLevel();
353
+ if (apiLevel < 21) {
354
+ this.log.errorAndThrow('UIAutomator2 is only supported since Android 5.0 (Lollipop). ' +
355
+ 'You could still use other supported backends in order to automate older Android versions.');
356
+ }
357
+ if (apiLevel >= 28) {
358
+ // Android P
359
+ this.log.info('Relaxing hidden api policy');
360
+ await this.adb.setHiddenApiPolicy('1', !!this.opts.ignoreHiddenApiPolicyError);
361
+ }
362
+ // check if we have to enable/disable gps before running the application
363
+ if (support_1.util.hasValue(this.opts.gpsEnabled)) {
364
+ if (this.isEmulator()) {
365
+ this.log.info(`Trying to ${this.opts.gpsEnabled ? 'enable' : 'disable'} gps location provider`);
366
+ await this.adb.toggleGPSLocationProvider(this.opts.gpsEnabled);
367
+ }
368
+ else {
369
+ this.log.warn(`Sorry! 'gpsEnabled' capability is only available for emulators`);
370
+ }
371
+ }
372
+ // get appPackage et al from manifest if necessary
373
+ const appInfo = await helpers.getLaunchInfo(this.adb, this.opts);
374
+ // and get it onto our 'opts' object so we use it from now on
375
+ this.opts = { ...this.opts, ...(appInfo ?? {}) };
376
+ // set actual device name, udid, platform version, screen size, screen density, model and manufacturer details
377
+ const sessionInfo = {
378
+ deviceName: this.adb.curDeviceId,
379
+ deviceUDID: this.opts.udid,
380
+ };
381
+ const capsWithSessionInfo = {
382
+ ...caps,
383
+ ...sessionInfo,
384
+ };
385
+ // start an avd, set the language/locale, pick an emulator, etc...
386
+ // TODO with multiple devices we'll need to parameterize this
387
+ await helpers.initDevice(this.adb, this.opts);
388
+ // Prepare the device by forwarding the UiAutomator2 port
389
+ // This call mutates this.systemPort if it is not set explicitly
390
+ await this.allocateSystemPort();
391
+ // Prepare the device by forwarding the UiAutomator2 MJPEG server port (if
392
+ // applicable)
393
+ await this.allocateMjpegServerPort();
394
+ // set up the modified UiAutomator2 server etc
395
+ const uiautomator2 = await this.initUiAutomator2Server();
396
+ // Should be after installing io.appium.settings in helpers.initDevice
397
+ if (this.opts.disableWindowAnimation && (await this.adb.getApiLevel()) < 26) {
398
+ // API level 26 is Android 8.0.
399
+ // Granting android.permission.SET_ANIMATION_SCALE is necessary to handle animations under API level 26
400
+ // Read https://github.com/appium/appium/pull/11640#issuecomment-438260477
401
+ // `--no-window-animation` works over Android 8 to disable all of animations
402
+ if (await this.adb.isAnimationOn()) {
403
+ this.log.info('Disabling animation via io.appium.settings');
404
+ await this.adb.setAnimationState(false);
405
+ this._wasWindowAnimationDisabled = true;
406
+ }
407
+ else {
408
+ this.log.info('Window animation is already disabled');
409
+ }
410
+ }
411
+ // set up app under test
412
+ // prepare our actual AUT, get it on the device, etc...
413
+ await this.initAUT();
414
+ // Adding AUT package name in the capabilities if package name not exist in caps
415
+ if (!capsWithSessionInfo.appPackage && appInfo) {
416
+ capsWithSessionInfo.appPackage = appInfo.appPackage;
417
+ }
418
+ // launch UiAutomator2 and wait till its online and we have a session
419
+ await uiautomator2.startSession(capsWithSessionInfo);
420
+ const capsWithSessionAndDeviceInfo = {
421
+ ...capsWithSessionInfo,
422
+ ...(await this.getDeviceInfoFromUia2()),
423
+ };
424
+ // Unlock the device after the session is started.
425
+ if (!this.opts.skipUnlock) {
426
+ // unlock the device to prepare it for testing
427
+ await helpers.unlock(this, this.adb, this.caps);
428
+ }
429
+ else {
430
+ this.log.debug(`'skipUnlock' capability set, so skipping device unlock`);
431
+ }
432
+ if (this.isChromeSession) {
433
+ // start a chromedriver session
434
+ await this.startChromeSession();
435
+ }
436
+ else if (this.opts.autoLaunch && this.opts.appPackage) {
437
+ await this.ensureAppStarts();
438
+ }
439
+ // if the initial orientation is requested, set it
440
+ if (support_1.util.hasValue(this.opts.orientation)) {
441
+ this.log.debug(`Setting initial orientation to '${this.opts.orientation}'`);
442
+ await this.setOrientation(this.opts.orientation);
443
+ }
444
+ // if we want to immediately get into a webview, set our context
445
+ // appropriately
446
+ if (this.opts.autoWebview) {
447
+ const viewName = this.defaultWebviewName();
448
+ const timeout = this.opts.autoWebviewTimeout || 2000;
449
+ this.log.info(`Setting auto webview to context '${viewName}' with timeout ${timeout}ms`);
450
+ await (0, asyncbox_1.retryInterval)(timeout / 500, 500, this.setContext.bind(this), viewName);
451
+ }
452
+ // now that everything has started successfully, turn on proxying so all
453
+ // subsequent session requests go straight to/from uiautomator2
454
+ this.jwpProxyActive = true;
455
+ return { ...capsWithSessionAndDeviceInfo, ...(await this.getDeviceDetails()) };
237
456
  }
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`);
457
+ async getDeviceInfoFromUia2() {
458
+ const { apiVersion, platformVersion, manufacturer, model, realDisplaySize, displayDensity } = await this.mobileGetDeviceInfo();
459
+ return {
460
+ deviceApiLevel: lodash_1.default.parseInt(apiVersion),
461
+ platformVersion,
462
+ deviceManufacturer: manufacturer,
463
+ deviceModel: model,
464
+ deviceScreenSize: realDisplaySize,
465
+ deviceScreenDensity: displayDensity,
466
+ };
244
467
  }
245
- if (this.isChromeSession) {
246
- await this.startChromeSession(this);
247
- } else if (this.opts.autoLaunch && this.opts.appPackage) {
248
- await this.ensureAppStarts();
468
+ async initUiAutomator2Server() {
469
+ // broken out for readability
470
+ const uiautomator2Opts = {
471
+ // @ts-expect-error FIXME: maybe `address` instead of `host`?
472
+ host: this.opts.remoteAdbHost || this.opts.host || LOCALHOST_IP4,
473
+ systemPort: this.systemPort,
474
+ devicePort: DEVICE_PORT,
475
+ adb: this.adb,
476
+ apk: this.opts.app,
477
+ tmpDir: this.opts.tmpDir,
478
+ appPackage: this.opts.appPackage,
479
+ appActivity: this.opts.appActivity,
480
+ disableWindowAnimation: !!this.opts.disableWindowAnimation,
481
+ disableSuppressAccessibilityService: this.opts.disableSuppressAccessibilityService,
482
+ readTimeout: this.opts.uiautomator2ServerReadTimeout,
483
+ };
484
+ // now that we have package and activity, we can create an instance of
485
+ // uiautomator2 with the appropriate options
486
+ this.uiautomator2 = new uiautomator2_1.UiAutomator2Server(this.log, uiautomator2Opts);
487
+ this.proxyReqRes = this.uiautomator2.proxyReqRes.bind(this.uiautomator2);
488
+ this.proxyCommand = this.uiautomator2.proxyCommand.bind(this.uiautomator2);
489
+ if (this.opts.skipServerInstallation) {
490
+ this.log.info(`'skipServerInstallation' is set. Skipping UIAutomator2 server installation.`);
491
+ }
492
+ else {
493
+ await this.uiautomator2.installServerApk(this.opts.uiautomator2ServerInstallTimeout);
494
+ try {
495
+ await this.adb.addToDeviceIdleWhitelist(appium_android_driver_1.SETTINGS_HELPER_PKG_ID, uiautomator2_1.SERVER_PACKAGE_ID, uiautomator2_1.SERVER_TEST_PACKAGE_ID);
496
+ }
497
+ catch (e) {
498
+ const err = e;
499
+ this.log.warn(`Cannot add server packages to the Doze whitelist. Original error: ` +
500
+ (err.stderr || err.message));
501
+ }
502
+ }
503
+ return this.uiautomator2;
249
504
  }
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);
505
+ async initAUT() {
506
+ // Uninstall any uninstallOtherPackages which were specified in caps
507
+ if (this.opts.uninstallOtherPackages) {
508
+ 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]);
509
+ }
510
+ // Install any "otherApps" that were specified in caps
511
+ if (this.opts.otherApps) {
512
+ let otherApps;
513
+ try {
514
+ otherApps = helpers.parseArray(this.opts.otherApps);
515
+ }
516
+ catch (e) {
517
+ this.log.errorAndThrow(`Could not parse "otherApps" capability: ${e.message}`);
518
+ throw new Error(); // unrechable
519
+ }
520
+ otherApps = await bluebird_1.default.all(otherApps.map((app) => this.helpers.configureApp(app, [extensions_1.APK_EXTENSION, extensions_1.APKS_EXTENSION])));
521
+ await helpers.installOtherApks(otherApps, this.adb, this.opts);
522
+ }
523
+ if (this.opts.app) {
524
+ if ((this.opts.noReset && !(await this.adb.isAppInstalled(this.opts.appPackage))) ||
525
+ !this.opts.noReset) {
526
+ if (!this.opts.noSign &&
527
+ !(await this.adb.checkApkCert(this.opts.app, this.opts.appPackage, {
528
+ requireDefaultCert: false,
529
+ }))) {
530
+ await helpers.signApp(this.adb, this.opts.app);
531
+ }
532
+ if (!this.opts.skipUninstall) {
533
+ await this.adb.uninstallApk(this.opts.appPackage);
534
+ }
535
+ await helpers.installApk(this.adb, this.opts);
536
+ }
537
+ else {
538
+ this.log.debug('noReset has been requested and the app is already installed. Doing nothing');
539
+ }
540
+ }
541
+ else {
542
+ if (this.opts.fullReset) {
543
+ this.log.errorAndThrow('Full reset requires an app capability, use fastReset if app is not provided');
544
+ }
545
+ this.log.debug('No app capability. Assuming it is already on the device');
546
+ if (this.opts.fastReset && this.opts.appPackage) {
547
+ await helpers.resetApp(this.adb, this.opts);
548
+ }
549
+ }
253
550
  }
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);
551
+ async ensureAppStarts() {
552
+ // make sure we have an activity and package to wait for
553
+ const appWaitPackage = this.opts.appWaitPackage || this.opts.appPackage;
554
+ const appWaitActivity = this.opts.appWaitActivity || this.opts.appActivity;
555
+ this.log.info(`Starting '${this.opts.appPackage}/${this.opts.appActivity} ` +
556
+ `and waiting for '${appWaitPackage}/${appWaitActivity}'`);
557
+ if (this.caps.androidCoverage) {
558
+ this.log.info(`androidCoverage is configured. ` +
559
+ ` Starting instrumentation of '${this.caps.androidCoverage}'...`);
560
+ await this.adb.androidCoverage(this.caps.androidCoverage, appWaitPackage, appWaitActivity);
561
+ return;
562
+ }
563
+ if (this.opts.noReset &&
564
+ !this.opts.forceAppLaunch &&
565
+ (await this.adb.processExists(this.opts.appPackage))) {
566
+ this.log.info(`'${this.opts.appPackage}' is already running and noReset is enabled. ` +
567
+ `Set forceAppLaunch capability to true if the app must be forcefully restarted on session startup.`);
568
+ return;
569
+ }
570
+ await this.adb.startApp({
571
+ pkg: this.opts.appPackage,
572
+ activity: this.opts.appActivity,
573
+ action: this.opts.intentAction || 'android.intent.action.MAIN',
574
+ category: this.opts.intentCategory || 'android.intent.category.LAUNCHER',
575
+ flags: this.opts.intentFlags || '0x10200000',
576
+ waitPkg: this.opts.appWaitPackage,
577
+ waitActivity: this.opts.appWaitActivity,
578
+ waitForLaunch: this.opts.appWaitForLaunch,
579
+ waitDuration: this.opts.appWaitDuration,
580
+ optionalIntentArguments: this.opts.optionalIntentArguments,
581
+ stopApp: this.opts.forceAppLaunch || !this.opts.dontStopAppOnReset,
582
+ retry: true,
583
+ user: this.opts.userProfile,
584
+ });
259
585
  }
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
- }
586
+ async deleteSession() {
587
+ this.log.debug('Deleting UiAutomator2 session');
588
+ const screenRecordingStopTasks = [
589
+ async () => {
590
+ if (!lodash_1.default.isEmpty(this._screenRecordingProperties)) {
591
+ await this.stopRecordingScreen();
592
+ }
593
+ },
594
+ async () => {
595
+ if (await this.mobileIsMediaProjectionRecordingRunning()) {
596
+ await this.mobileStopMediaProjectionRecording();
597
+ }
598
+ },
599
+ async () => {
600
+ if (!lodash_1.default.isEmpty(this._screenStreamingProps)) {
601
+ await this.mobileStopScreenStreaming();
602
+ }
603
+ },
604
+ ];
605
+ await appium_android_driver_1.androidHelpers.removeAllSessionWebSocketHandlers(this.server, this.sessionId);
606
+ if (this.uiautomator2) {
607
+ try {
608
+ await this.stopChromedriverProxies();
609
+ }
610
+ catch (err) {
611
+ this.log.warn(`Unable to stop ChromeDriver proxies: ${err.message}`);
612
+ }
613
+ if (this.jwpProxyActive) {
614
+ try {
615
+ await this.uiautomator2.deleteSession();
616
+ }
617
+ catch (err) {
618
+ this.log.warn(`Unable to proxy deleteSession to UiAutomator2: ${err.message}`);
619
+ }
620
+ }
621
+ this.uiautomator2 = undefined;
622
+ }
623
+ this.jwpProxyActive = false;
624
+ if (this.adb) {
625
+ await bluebird_1.default.all(screenRecordingStopTasks.map((task) => {
626
+ (async () => {
627
+ try {
628
+ await task();
629
+ }
630
+ catch (ign) { }
631
+ })();
632
+ }));
633
+ if (this.caps.androidCoverage) {
634
+ this.log.info('Shutting down the adb process of instrumentation...');
635
+ await this.adb.endAndroidCoverage();
636
+ // Use this broadcast intent to notify it's time to dump coverage to file
637
+ if (this.caps.androidCoverageEndIntent) {
638
+ this.log.info(`Sending intent broadcast '${this.caps.androidCoverageEndIntent}' at the end of instrumenting.`);
639
+ await this.adb.broadcast(this.caps.androidCoverageEndIntent);
640
+ }
641
+ else {
642
+ this.log.warn('No androidCoverageEndIntent is configured in caps. Possibly you cannot get coverage file.');
643
+ }
644
+ }
645
+ if (this.opts.appPackage) {
646
+ if (!this.isChromeSession &&
647
+ ((!this.opts.dontStopAppOnReset && !this.opts.noReset) ||
648
+ (this.opts.noReset && this.opts.shouldTerminateApp))) {
649
+ try {
650
+ await this.adb.forceStop(this.opts.appPackage);
651
+ }
652
+ catch (err) {
653
+ this.log.warn(`Unable to force stop app: ${err.message}`);
654
+ }
655
+ }
656
+ if (this.opts.fullReset && !this.opts.skipUninstall) {
657
+ this.log.debug(`Capability 'fullReset' set to 'true', Uninstalling '${this.opts.appPackage}'`);
658
+ try {
659
+ await this.adb.uninstallApk(this.opts.appPackage);
660
+ }
661
+ catch (err) {
662
+ this.log.warn(`Unable to uninstall app: ${err.message}`);
663
+ }
664
+ }
665
+ }
666
+ // This value can be true if test target device is <= 26
667
+ if (this._wasWindowAnimationDisabled) {
668
+ this.log.info('Restoring window animation state');
669
+ await this.adb.setAnimationState(true);
670
+ }
671
+ await this.adb.stopLogcat();
672
+ try {
673
+ await this.releaseSystemPort();
674
+ }
675
+ catch (error) {
676
+ this.log.warn(`Unable to remove system port forward: ${error.message}`);
677
+ // Ignore, this block will also be called when we fall in catch block
678
+ // and before even port forward.
679
+ }
680
+ try {
681
+ await this.releaseMjpegServerPort();
682
+ }
683
+ catch (error) {
684
+ this.log.warn(`Unable to remove MJPEG server port forward: ${error.message}`);
685
+ // Ignore, this block will also be called when we fall in catch block
686
+ // and before even port forward.
687
+ }
688
+ if ((await this.adb.getApiLevel()) >= 28) {
689
+ // Android P
690
+ this.log.info('Restoring hidden api policy to the device default configuration');
691
+ await this.adb.setDefaultHiddenApiPolicy(!!this.opts.ignoreHiddenApiPolicyError);
692
+ }
693
+ // @ts-expect-error unknown option
694
+ if (this.opts.reboot) {
695
+ const avdName = this.opts.avd.replace('@', '');
696
+ this.log.debug(`Closing emulator '${avdName}'`);
697
+ try {
698
+ await this.adb.killEmulator(avdName);
699
+ }
700
+ catch (err) {
701
+ this.log.warn(`Unable to close emulator: ${err.message}`);
702
+ }
703
+ }
704
+ }
705
+ if (this.mjpegStream) {
706
+ this.log.info('Closing MJPEG stream');
707
+ this.mjpegStream.stop();
708
+ }
709
+ await driver_1.BaseDriver.prototype.deleteSession.call(this);
304
710
  }
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]);
711
+ async checkAppPresent() {
712
+ this.log.debug('Checking whether app is actually present');
713
+ if (!(await support_1.fs.exists(this.opts.app))) {
714
+ this.log.errorAndThrow(`Could not find app apk at '${this.opts.app}'`);
715
+ throw new Error(); // unreachable
716
+ }
309
717
  }
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);
718
+ async onSettingsUpdate() {
719
+ // intentionally do nothing here, since commands.updateSettings proxies
720
+ // settings to the uiauto2 server already
319
721
  }
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
- }
722
+ // Need to override android-driver's version of this since we don't actually
723
+ // have a bootstrap; instead we just restart adb and re-forward the UiAutomator2
724
+ // port
725
+ async wrapBootstrapDisconnect(wrapped) {
726
+ await wrapped();
727
+ this.adb.restart();
728
+ await this.allocateSystemPort();
729
+ await this.allocateMjpegServerPort();
342
730
  }
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;
731
+ proxyActive(sessionId) {
732
+ driver_1.BaseDriver.prototype.proxyActive.call(this, sessionId);
733
+ // we always have an active proxy to the UiAutomator2 server
734
+ return true;
352
735
  }
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;
736
+ canProxy(sessionId) {
737
+ driver_1.BaseDriver.prototype.canProxy.call(this, sessionId);
738
+ // we can always proxy to the uiautomator2 server
739
+ return true;
356
740
  }
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}`);
741
+ getProxyAvoidList() {
742
+ // we are maintaining two sets of NO_PROXY lists, one for chromedriver(CHROME_NO_PROXY)
743
+ // and one for uiautomator2(NO_PROXY), based on current context will return related NO_PROXY list
744
+ if (support_1.util.hasValue(this.chromedriver)) {
745
+ // if the current context is webview(chromedriver), then return CHROME_NO_PROXY list
746
+ this.jwpProxyAvoid = CHROME_NO_PROXY;
400
747
  }
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}`);
748
+ else {
749
+ this.jwpProxyAvoid = NO_PROXY;
466
750
  }
467
- }
468
- }
469
- if (this.mjpegStream) {
470
- this.log.info('Closing MJPEG stream');
471
- this.mjpegStream.stop();
751
+ if (this.opts.nativeWebScreenshot) {
752
+ this.jwpProxyAvoid = [
753
+ ...this.jwpProxyAvoid,
754
+ ['GET', new RegExp('^/session/[^/]+/screenshot')],
755
+ ];
756
+ }
757
+ return this.jwpProxyAvoid;
472
758
  }
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}'`);
759
+ get isChromeSession() {
760
+ return helpers.isChromeBrowser(this.opts.browserName);
479
761
  }
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;
762
+ async updateSettings(settings) {
763
+ await this.settings.update(settings);
764
+ await this.uiautomator2.jwproxy.command('/appium/settings', 'POST', { settings });
502
765
  }
503
- if (this.opts.nativeWebScreenshot) {
504
- this.jwpProxyAvoid = [...this.jwpProxyAvoid, ['GET', new RegExp('^/session/[^/]+/screenshot')]];
766
+ async getSettings() {
767
+ const driverSettings = this.settings.getSettings();
768
+ const serverSettings = (await this.uiautomator2.jwproxy.command('/appium/settings', 'GET'));
769
+ return { ...driverSettings, ...serverSettings };
505
770
  }
506
- return this.jwpProxyAvoid;
507
- }
508
- get isChromeSession() {
509
- return helpers.isChromeBrowser(this.opts.browserName);
510
- }
511
771
  }
512
772
  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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
773
+ AndroidUiautomator2Driver.newMethodMap = method_map_1.newMethodMap;
774
+ AndroidUiautomator2Driver.executeMethodMap = execute_method_map_1.executeMethodMap;
775
+ require("./commands");
776
+ //# sourceMappingURL=driver.js.map