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.
- package/CHANGELOG.md +7 -0
- package/build/index.d.ts +4 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +8 -15
- package/build/index.js.map +1 -0
- package/build/lib/commands/actions.d.ts +2 -0
- package/build/lib/commands/actions.d.ts.map +1 -0
- package/build/lib/commands/actions.js +67 -62
- package/build/lib/commands/actions.js.map +1 -1
- package/build/lib/commands/alert.d.ts +2 -0
- package/build/lib/commands/alert.d.ts.map +1 -0
- package/build/lib/commands/alert.js +28 -26
- package/build/lib/commands/alert.js.map +1 -1
- package/build/lib/commands/app-strings.d.ts +3 -0
- package/build/lib/commands/app-strings.d.ts.map +1 -0
- package/build/lib/commands/app-strings.js +86 -57
- package/build/lib/commands/app-strings.js.map +1 -1
- package/build/lib/commands/battery.d.ts +2 -0
- package/build/lib/commands/battery.d.ts.map +1 -0
- package/build/lib/commands/battery.js +26 -16
- package/build/lib/commands/battery.js.map +1 -1
- package/build/lib/commands/element.d.ts +2 -0
- package/build/lib/commands/element.d.ts.map +1 -0
- package/build/lib/commands/element.js +140 -159
- package/build/lib/commands/element.js.map +1 -1
- package/build/lib/commands/find.d.ts +2 -0
- package/build/lib/commands/find.d.ts.map +1 -0
- package/build/lib/commands/find.js +39 -25
- package/build/lib/commands/find.js.map +1 -1
- package/build/lib/commands/general.d.ts +4 -0
- package/build/lib/commands/general.d.ts.map +1 -0
- package/build/lib/commands/general.js +217 -215
- package/build/lib/commands/general.js.map +1 -1
- package/build/lib/commands/gestures.d.ts +2 -0
- package/build/lib/commands/gestures.d.ts.map +1 -0
- package/build/lib/commands/gestures.js +206 -193
- package/build/lib/commands/gestures.js.map +1 -1
- package/build/lib/commands/index.d.ts +2 -0
- package/build/lib/commands/index.d.ts.map +1 -0
- package/build/lib/commands/index.js +13 -22
- package/build/lib/commands/index.js.map +1 -1
- package/build/lib/commands/mixins.d.ts +84 -0
- package/build/lib/commands/mixins.d.ts.map +1 -0
- package/build/lib/commands/mixins.js +23 -0
- package/build/lib/commands/mixins.js.map +1 -0
- package/build/lib/commands/screenshot.d.ts +2 -0
- package/build/lib/commands/screenshot.d.ts.map +1 -0
- package/build/lib/commands/screenshot.js +77 -62
- package/build/lib/commands/screenshot.js.map +1 -1
- package/build/lib/commands/touch.d.ts +2 -0
- package/build/lib/commands/touch.d.ts.map +1 -0
- package/build/lib/commands/touch.js +48 -38
- package/build/lib/commands/touch.js.map +1 -1
- package/build/lib/commands/types.d.ts +452 -0
- package/build/lib/commands/types.d.ts.map +1 -0
- package/build/lib/commands/types.js +3 -0
- package/build/lib/commands/types.js.map +1 -0
- package/build/lib/commands/viewport.d.ts +2 -0
- package/build/lib/commands/viewport.d.ts.map +1 -0
- package/build/lib/commands/viewport.js +37 -35
- package/build/lib/commands/viewport.js.map +1 -1
- package/build/lib/constraints.d.ts +334 -0
- package/build/lib/constraints.d.ts.map +1 -0
- package/build/lib/constraints.js +51 -0
- package/build/lib/constraints.js.map +1 -0
- package/build/lib/css-converter.d.ts +45 -0
- package/build/lib/css-converter.d.ts.map +1 -0
- package/build/lib/css-converter.js +272 -175
- package/build/lib/css-converter.js.map +1 -1
- package/build/lib/driver.d.ts +912 -0
- package/build/lib/driver.d.ts.map +1 -0
- package/build/lib/driver.js +738 -482
- package/build/lib/driver.js.map +1 -1
- package/build/lib/execute-method-map.d.ts +477 -0
- package/build/lib/execute-method-map.d.ts.map +1 -0
- package/build/lib/execute-method-map.js +542 -0
- package/build/lib/execute-method-map.js.map +1 -0
- package/build/lib/extensions.d.ts +3 -0
- package/build/lib/extensions.d.ts.map +1 -0
- package/build/lib/extensions.js +7 -9
- package/build/lib/extensions.js.map +1 -1
- package/build/lib/helpers.d.ts +7 -0
- package/build/lib/helpers.d.ts.map +1 -0
- package/build/lib/helpers.js +36 -29
- package/build/lib/helpers.js.map +1 -1
- package/build/lib/logger.d.ts +3 -0
- package/build/lib/logger.d.ts.map +1 -0
- package/build/lib/logger.js +5 -10
- package/build/lib/logger.js.map +1 -1
- package/build/lib/method-map.d.ts +389 -0
- package/build/lib/method-map.d.ts.map +1 -0
- package/build/lib/method-map.js +11 -17
- package/build/lib/method-map.js.map +1 -1
- package/build/lib/types.d.ts +45 -0
- package/build/lib/types.d.ts.map +1 -0
- package/build/lib/types.js +3 -0
- package/build/lib/types.js.map +1 -0
- package/build/lib/uiautomator2.d.ts +45 -0
- package/build/lib/uiautomator2.d.ts.map +1 -0
- package/build/lib/uiautomator2.js +340 -299
- package/build/lib/uiautomator2.js.map +1 -1
- package/build/lib/utils.d.ts +10 -0
- package/build/lib/utils.d.ts.map +1 -0
- package/build/lib/utils.js +23 -16
- package/build/lib/utils.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -0
- package/index.js +5 -3
- package/lib/commands/actions.js +115 -101
- package/lib/commands/alert.js +36 -44
- package/lib/commands/app-strings.js +79 -58
- package/lib/commands/battery.js +27 -28
- package/lib/commands/element.js +231 -134
- package/lib/commands/find.js +40 -21
- package/lib/commands/general.js +271 -336
- package/lib/commands/gestures.js +252 -366
- package/lib/commands/index.js +11 -31
- package/lib/commands/mixins.ts +167 -0
- package/lib/commands/screenshot.js +80 -76
- package/lib/commands/touch.js +64 -31
- package/lib/commands/types.ts +473 -0
- package/lib/commands/viewport.js +43 -31
- package/lib/constraints.ts +53 -0
- package/lib/css-converter.js +9 -1
- package/lib/{driver.js → driver.ts} +383 -225
- package/lib/execute-method-map.ts +573 -0
- package/lib/method-map.ts +11 -0
- package/lib/types.ts +59 -0
- package/lib/uiautomator2.js +21 -2
- package/lib/utils.js +2 -2
- package/npm-shrinkwrap.json +363 -492
- package/package.json +95 -69
- package/build/lib/desired-caps.js +0 -71
- package/build/lib/desired-caps.js.map +0 -1
- package/lib/desired-caps.js +0 -70
- package/lib/method-map.js +0 -11
package/build/lib/driver.js
CHANGED
|
@@ -1,520 +1,776 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
Object.
|
|
5
|
-
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
var
|
|
10
|
-
var
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
var
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
35
|
-
|
|
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
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
-
|
|
59
|
-
|
|
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
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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
|
-
|
|
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
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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
|
-
|
|
235
|
-
|
|
236
|
-
|
|
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
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
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
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
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
|
-
|
|
251
|
-
|
|
252
|
-
|
|
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
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
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
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
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
|
-
|
|
307
|
-
|
|
308
|
-
|
|
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
|
-
|
|
311
|
-
|
|
312
|
-
|
|
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
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
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
|
-
|
|
345
|
-
|
|
346
|
-
|
|
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
|
-
|
|
354
|
-
|
|
355
|
-
|
|
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
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
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
|
-
|
|
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
|
-
|
|
470
|
-
|
|
471
|
-
|
|
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
|
-
|
|
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
|
-
|
|
482
|
-
|
|
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
|
-
|
|
504
|
-
|
|
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
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
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
|