barsa-novin-ray-core 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -0
- package/esm2020/barsa-novin-ray-core.mjs +5 -0
- package/esm2020/lib/abstract-classes/application-base.mjs +24 -0
- package/esm2020/lib/abstract-classes/barsa-api.mjs +40 -0
- package/esm2020/lib/abstract-classes/field-base.mjs +167 -0
- package/esm2020/lib/abstract-classes/files-validation-helper.mjs +71 -0
- package/esm2020/lib/abstract-classes/form-base.mjs +101 -0
- package/esm2020/lib/abstract-classes/form-props.base.mjs +79 -0
- package/esm2020/lib/abstract-classes/form-toolbar-base.mjs +45 -0
- package/esm2020/lib/abstract-classes/index.mjs +21 -0
- package/esm2020/lib/abstract-classes/layout-item-base.mjs +33 -0
- package/esm2020/lib/abstract-classes/layout-panel-base.mjs +80 -0
- package/esm2020/lib/abstract-classes/models.mjs +172 -0
- package/esm2020/lib/abstract-classes/module-with-dynamic-components.mjs +2 -0
- package/esm2020/lib/abstract-classes/number-base.mjs +117 -0
- package/esm2020/lib/abstract-classes/page-base.mjs +97 -0
- package/esm2020/lib/abstract-classes/report-base.mjs +231 -0
- package/esm2020/lib/abstract-classes/report-item-base.mjs +53 -0
- package/esm2020/lib/abstract-classes/report-view-base.component.mjs +262 -0
- package/esm2020/lib/abstract-classes/system-base.mjs +24 -0
- package/esm2020/lib/auth-guard.mjs +37 -0
- package/esm2020/lib/barsa-novin-ray-core-routing.module.mjs +18 -0
- package/esm2020/lib/barsa-novin-ray-core.module.mjs +271 -0
- package/esm2020/lib/base-ulv-setting.component.mjs +37 -0
- package/esm2020/lib/base.component.mjs +59 -0
- package/esm2020/lib/base.module.mjs +28 -0
- package/esm2020/lib/constants.mjs +441 -0
- package/esm2020/lib/container.component.mjs +76 -0
- package/esm2020/lib/custom-route-reuse-strategy.mjs +32 -0
- package/esm2020/lib/date-services/date-hijri.service.mjs +127 -0
- package/esm2020/lib/date-services/date-info.mjs +2 -0
- package/esm2020/lib/date-services/date-miladi.service.mjs +124 -0
- package/esm2020/lib/date-services/date-shamsi.service.mjs +129 -0
- package/esm2020/lib/date-services/date.service.mjs +139 -0
- package/esm2020/lib/date-services/index.mjs +6 -0
- package/esm2020/lib/device.mjs +663 -0
- package/esm2020/lib/directives/anchor-scroll.directive.mjs +24 -0
- package/esm2020/lib/directives/attr-rtl.directive.mjs +35 -0
- package/esm2020/lib/directives/base.directive.mjs +51 -0
- package/esm2020/lib/directives/column-resizer.directive.mjs +39 -0
- package/esm2020/lib/directives/dynamic-command.directive.mjs +43 -0
- package/esm2020/lib/directives/ellipsify.directive.mjs +72 -0
- package/esm2020/lib/directives/field-binding.directive.mjs +17 -0
- package/esm2020/lib/directives/img-lazy.directive.mjs +75 -0
- package/esm2020/lib/directives/index.mjs +19 -0
- package/esm2020/lib/directives/intersection-observer.directive.mjs +49 -0
- package/esm2020/lib/directives/items-renderer.directive.mjs +59 -0
- package/esm2020/lib/directives/numbers-only-input.directive.mjs +26 -0
- package/esm2020/lib/directives/placeHolder.directive.mjs +15 -0
- package/esm2020/lib/directives/render-ulv-paging.directive.mjs +58 -0
- package/esm2020/lib/directives/render-ulv-viewer.directive.mjs +60 -0
- package/esm2020/lib/directives/table-resizer.directive.mjs +235 -0
- package/esm2020/lib/directives/ulv-command.directive.mjs +41 -0
- package/esm2020/lib/directives/until-inview.directive.mjs +51 -0
- package/esm2020/lib/dynamic-component/base-dynamic.component.mjs +89 -0
- package/esm2020/lib/dynamic-component/base-form-toolbaritem-props.mjs +50 -0
- package/esm2020/lib/dynamic-component/base-item-content-props.mjs +70 -0
- package/esm2020/lib/dynamic-component/base-view-content-props.mjs +26 -0
- package/esm2020/lib/dynamic-component/base-view-item-props.mjs +374 -0
- package/esm2020/lib/dynamic-component/base-view-props.mjs +127 -0
- package/esm2020/lib/dynamic-component/dynamic-form-toolbar-item.component.mjs +36 -0
- package/esm2020/lib/dynamic-component/dynamic-form.component.mjs +62 -0
- package/esm2020/lib/dynamic-component/dynamic-item.component.mjs +60 -0
- package/esm2020/lib/dynamic-component/index.mjs +10 -0
- package/esm2020/lib/empty-page-with-router-and-router-outlet/empty-page-with-router-and-router-outlet.component.mjs +16 -0
- package/esm2020/lib/field-ui/field-ui.component.mjs +116 -0
- package/esm2020/lib/form/form.component.mjs +151 -0
- package/esm2020/lib/form-new/form-new.component.mjs +30 -0
- package/esm2020/lib/from-intersection-observer.mjs +53 -0
- package/esm2020/lib/global-error-handler.mjs +26 -0
- package/esm2020/lib/modal-root.component.mjs +31 -0
- package/esm2020/lib/not-found/not-found.component.mjs +16 -0
- package/esm2020/lib/pipes/barsa-icon-dict.pipe.mjs +18 -0
- package/esm2020/lib/pipes/bbb-translate.pipe.mjs +29 -0
- package/esm2020/lib/pipes/can-upload.pipe.mjs +30 -0
- package/esm2020/lib/pipes/context-menu.pipe.mjs +40 -0
- package/esm2020/lib/pipes/control-ui.pipe.mjs +31 -0
- package/esm2020/lib/pipes/convert-to-style.pipe.mjs +32 -0
- package/esm2020/lib/pipes/date-time-to-caption.pipe.mjs +34 -0
- package/esm2020/lib/pipes/fileinfo-count.pipe.mjs +20 -0
- package/esm2020/lib/pipes/filter-columns-by-details.pipe.mjs +20 -0
- package/esm2020/lib/pipes/filter-string.pipe.mjs +44 -0
- package/esm2020/lib/pipes/filter-tab.pipe.mjs +19 -0
- package/esm2020/lib/pipes/filter-toolbar-control.pipe.mjs +16 -0
- package/esm2020/lib/pipes/filter.pipe.mjs +33 -0
- package/esm2020/lib/pipes/find-column-by-db-name.pipe.mjs +17 -0
- package/esm2020/lib/pipes/fiori-icon.pipe.mjs +42 -0
- package/esm2020/lib/pipes/groupby.pipe.mjs +48 -0
- package/esm2020/lib/pipes/header-facet-value.pipe.mjs +22 -0
- package/esm2020/lib/pipes/index.mjs +33 -0
- package/esm2020/lib/pipes/list-count.pipe.mjs +17 -0
- package/esm2020/lib/pipes/merge-fields-to-columns.pipe.mjs +42 -0
- package/esm2020/lib/pipes/mo-info-ulv-data.pipe.mjs +24 -0
- package/esm2020/lib/pipes/mo-report-value-concat.pipe.mjs +35 -0
- package/esm2020/lib/pipes/mo-report-value.pipe.mjs +28 -0
- package/esm2020/lib/pipes/mo-value.pipe.mjs +31 -0
- package/esm2020/lib/pipes/multiple-groupby.pipe.mjs +97 -0
- package/esm2020/lib/pipes/numeral.pipe.mjs +40 -0
- package/esm2020/lib/pipes/picture-field-source.pipe.mjs +22 -0
- package/esm2020/lib/pipes/remove-newline.pipe.mjs +20 -0
- package/esm2020/lib/pipes/seperator-fix.pipe.mjs +23 -0
- package/esm2020/lib/pipes/sort.pipe.mjs +48 -0
- package/esm2020/lib/pipes/tlbButtons.pipe.mjs +58 -0
- package/esm2020/lib/pipes/total-summary.pipe.mjs +16 -0
- package/esm2020/lib/pipes/visible-value.pipe.mjs +24 -0
- package/esm2020/lib/portal-page/portal-page.component.mjs +13 -0
- package/esm2020/lib/redirect-home-guard.mjs +28 -0
- package/esm2020/lib/redirect-report-navigator-command/redirect-report-navigator-command.component.mjs +33 -0
- package/esm2020/lib/report-container/report-container.component.mjs +52 -0
- package/esm2020/lib/resolvers/index.mjs +5 -0
- package/esm2020/lib/resolvers/portal-dynamic-page.resolver.mjs +49 -0
- package/esm2020/lib/resolvers/portal-form-page.resolver.mjs +18 -0
- package/esm2020/lib/resolvers/portal-page.resolver.mjs +30 -0
- package/esm2020/lib/resolvers/portal-report-page.resolver.mjs +37 -0
- package/esm2020/lib/root-page/root-page.component.mjs +21 -0
- package/esm2020/lib/root-portal/root-portal.component.mjs +51 -0
- package/esm2020/lib/services/api.service.mjs +60 -0
- package/esm2020/lib/services/barsa-dialog.service.mjs +80 -0
- package/esm2020/lib/services/breadcrumb.service.mjs +60 -0
- package/esm2020/lib/services/container.service.mjs +36 -0
- package/esm2020/lib/services/dynamic-component.service.mjs +55 -0
- package/esm2020/lib/services/form-panel.service.mjs +235 -0
- package/esm2020/lib/services/form.service.mjs +14 -0
- package/esm2020/lib/services/horizontal-layout.service.mjs +16 -0
- package/esm2020/lib/services/index.mjs +16 -0
- package/esm2020/lib/services/layout.service.mjs +42 -0
- package/esm2020/lib/services/log.service.mjs +50 -0
- package/esm2020/lib/services/network-status.service.mjs +15 -0
- package/esm2020/lib/services/portal.service.mjs +638 -0
- package/esm2020/lib/services/ui.service.mjs +23 -0
- package/esm2020/lib/services/ulvmain.service.mjs +594 -0
- package/esm2020/lib/services/upload.service.mjs +75 -0
- package/esm2020/public-api.mjs +33 -0
- package/fesm2015/barsa-novin-ray-core.mjs +9047 -0
- package/fesm2015/barsa-novin-ray-core.mjs.map +1 -0
- package/fesm2020/barsa-novin-ray-core.mjs +8945 -0
- package/fesm2020/barsa-novin-ray-core.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/abstract-classes/application-base.d.ts +53 -0
- package/lib/abstract-classes/barsa-api.d.ts +28 -0
- package/lib/abstract-classes/field-base.d.ts +81 -0
- package/lib/abstract-classes/files-validation-helper.d.ts +15 -0
- package/lib/abstract-classes/form-base.d.ts +59 -0
- package/lib/abstract-classes/form-props.base.d.ts +45 -0
- package/lib/abstract-classes/form-toolbar-base.d.ts +17 -0
- package/lib/abstract-classes/index.d.ts +20 -0
- package/lib/abstract-classes/layout-item-base.d.ts +15 -0
- package/lib/abstract-classes/layout-panel-base.d.ts +24 -0
- package/lib/abstract-classes/models.d.ts +660 -0
- package/lib/abstract-classes/module-with-dynamic-components.d.ts +4 -0
- package/lib/abstract-classes/number-base.d.ts +20 -0
- package/lib/abstract-classes/page-base.d.ts +31 -0
- package/lib/abstract-classes/report-base.d.ts +97 -0
- package/lib/abstract-classes/report-item-base.d.ts +33 -0
- package/lib/abstract-classes/report-view-base.component.d.ts +130 -0
- package/lib/abstract-classes/system-base.d.ts +45 -0
- package/lib/auth-guard.d.ts +12 -0
- package/lib/barsa-novin-ray-core-routing.module.d.ts +7 -0
- package/lib/barsa-novin-ray-core.module.d.ts +88 -0
- package/lib/base-ulv-setting.component.d.ts +18 -0
- package/lib/base.component.d.ts +15 -0
- package/lib/base.module.d.ts +13 -0
- package/lib/constants.d.ts +89 -0
- package/lib/container.component.d.ts +33 -0
- package/lib/custom-route-reuse-strategy.d.ts +11 -0
- package/lib/date-services/date-hijri.service.d.ts +40 -0
- package/lib/date-services/date-info.d.ts +15 -0
- package/lib/date-services/date-miladi.service.d.ts +39 -0
- package/lib/date-services/date-shamsi.service.d.ts +40 -0
- package/lib/date-services/date.service.d.ts +54 -0
- package/lib/date-services/index.d.ts +5 -0
- package/lib/device.d.ts +15 -0
- package/lib/directives/anchor-scroll.directive.d.ts +7 -0
- package/lib/directives/attr-rtl.directive.d.ts +13 -0
- package/lib/directives/base.directive.d.ts +13 -0
- package/lib/directives/column-resizer.directive.d.ts +13 -0
- package/lib/directives/dynamic-command.directive.d.ts +12 -0
- package/lib/directives/ellipsify.directive.d.ts +17 -0
- package/lib/directives/field-binding.directive.d.ts +7 -0
- package/lib/directives/img-lazy.directive.d.ts +20 -0
- package/lib/directives/index.d.ts +18 -0
- package/lib/directives/intersection-observer.directive.d.ts +17 -0
- package/lib/directives/items-renderer.directive.d.ts +17 -0
- package/lib/directives/numbers-only-input.directive.d.ts +9 -0
- package/lib/directives/placeHolder.directive.d.ts +6 -0
- package/lib/directives/render-ulv-paging.directive.d.ts +19 -0
- package/lib/directives/render-ulv-viewer.directive.d.ts +19 -0
- package/lib/directives/table-resizer.directive.d.ts +47 -0
- package/lib/directives/ulv-command.directive.d.ts +11 -0
- package/lib/directives/until-inview.directive.d.ts +17 -0
- package/lib/dynamic-component/base-dynamic.component.d.ts +26 -0
- package/lib/dynamic-component/base-form-toolbaritem-props.d.ts +28 -0
- package/lib/dynamic-component/base-item-content-props.d.ts +40 -0
- package/lib/dynamic-component/base-view-content-props.d.ts +11 -0
- package/lib/dynamic-component/base-view-item-props.d.ts +95 -0
- package/lib/dynamic-component/base-view-props.d.ts +65 -0
- package/lib/dynamic-component/dynamic-form-toolbar-item.component.d.ts +18 -0
- package/lib/dynamic-component/dynamic-form.component.d.ts +33 -0
- package/lib/dynamic-component/dynamic-item.component.d.ts +30 -0
- package/lib/dynamic-component/index.d.ts +9 -0
- package/lib/empty-page-with-router-and-router-outlet/empty-page-with-router-and-router-outlet.component.d.ts +7 -0
- package/lib/field-ui/field-ui.component.d.ts +27 -0
- package/lib/form/form.component.d.ts +36 -0
- package/lib/form-new/form-new.component.d.ts +23 -0
- package/lib/from-intersection-observer.d.ts +7 -0
- package/lib/global-error-handler.d.ts +8 -0
- package/lib/modal-root.component.d.ts +15 -0
- package/lib/not-found/not-found.component.d.ts +8 -0
- package/lib/pipes/barsa-icon-dict.pipe.d.ts +9 -0
- package/lib/pipes/bbb-translate.pipe.d.ts +7 -0
- package/lib/pipes/can-upload.pipe.d.ts +8 -0
- package/lib/pipes/context-menu.pipe.d.ts +11 -0
- package/lib/pipes/control-ui.pipe.d.ts +9 -0
- package/lib/pipes/convert-to-style.pipe.d.ts +8 -0
- package/lib/pipes/date-time-to-caption.pipe.d.ts +9 -0
- package/lib/pipes/fileinfo-count.pipe.d.ts +10 -0
- package/lib/pipes/filter-columns-by-details.pipe.d.ts +8 -0
- package/lib/pipes/filter-string.pipe.d.ts +11 -0
- package/lib/pipes/filter-tab.pipe.d.ts +7 -0
- package/lib/pipes/filter-toolbar-control.pipe.d.ts +8 -0
- package/lib/pipes/filter.pipe.d.ts +10 -0
- package/lib/pipes/find-column-by-db-name.pipe.d.ts +8 -0
- package/lib/pipes/fiori-icon.pipe.d.ts +7 -0
- package/lib/pipes/groupby.pipe.d.ts +7 -0
- package/lib/pipes/header-facet-value.pipe.d.ts +8 -0
- package/lib/pipes/index.d.ts +32 -0
- package/lib/pipes/list-count.pipe.d.ts +8 -0
- package/lib/pipes/merge-fields-to-columns.pipe.d.ts +10 -0
- package/lib/pipes/mo-info-ulv-data.pipe.d.ts +7 -0
- package/lib/pipes/mo-report-value-concat.pipe.d.ts +9 -0
- package/lib/pipes/mo-report-value.pipe.d.ts +12 -0
- package/lib/pipes/mo-value.pipe.d.ts +9 -0
- package/lib/pipes/multiple-groupby.pipe.d.ts +23 -0
- package/lib/pipes/numeral.pipe.d.ts +9 -0
- package/lib/pipes/picture-field-source.pipe.d.ts +8 -0
- package/lib/pipes/remove-newline.pipe.d.ts +8 -0
- package/lib/pipes/seperator-fix.pipe.d.ts +7 -0
- package/lib/pipes/sort.pipe.d.ts +9 -0
- package/lib/pipes/tlbButtons.pipe.d.ts +9 -0
- package/lib/pipes/total-summary.pipe.d.ts +8 -0
- package/lib/pipes/visible-value.pipe.d.ts +8 -0
- package/lib/portal-page/portal-page.component.d.ts +6 -0
- package/lib/redirect-home-guard.d.ts +13 -0
- package/lib/redirect-report-navigator-command/redirect-report-navigator-command.component.d.ts +14 -0
- package/lib/report-container/report-container.component.d.ts +24 -0
- package/lib/resolvers/index.d.ts +4 -0
- package/lib/resolvers/portal-dynamic-page.resolver.d.ts +12 -0
- package/lib/resolvers/portal-form-page.resolver.d.ts +8 -0
- package/lib/resolvers/portal-page.resolver.d.ts +12 -0
- package/lib/resolvers/portal-report-page.resolver.d.ts +12 -0
- package/lib/root-page/root-page.component.d.ts +10 -0
- package/lib/root-portal/root-portal.component.d.ts +14 -0
- package/lib/services/api.service.d.ts +18 -0
- package/lib/services/barsa-dialog.service.d.ts +31 -0
- package/lib/services/breadcrumb.service.d.ts +14 -0
- package/lib/services/container.service.d.ts +14 -0
- package/lib/services/dynamic-component.service.d.ts +13 -0
- package/lib/services/form-panel.service.d.ts +83 -0
- package/lib/services/form.service.d.ts +8 -0
- package/lib/services/horizontal-layout.service.d.ts +7 -0
- package/lib/services/index.d.ts +15 -0
- package/lib/services/layout.service.d.ts +23 -0
- package/lib/services/log.service.d.ts +17 -0
- package/lib/services/network-status.service.d.ts +7 -0
- package/lib/services/portal.service.d.ts +130 -0
- package/lib/services/ui.service.d.ts +14 -0
- package/lib/services/ulvmain.service.d.ts +178 -0
- package/lib/services/upload.service.d.ts +18 -0
- package/package.json +38 -0
- package/public-api.d.ts +29 -0
|
@@ -0,0 +1,663 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
const Device = {};
|
|
3
|
+
// * ******* OS Detection ********
|
|
4
|
+
/**
|
|
5
|
+
* Contains information about the operating system of the Device.
|
|
6
|
+
* @name Device.os
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Enumeration containing the names of known operating systems.
|
|
10
|
+
* @name Device.os.OS
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* The name of the operating system.
|
|
14
|
+
* @name Device.os.name
|
|
15
|
+
* @type String
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* The version of the operating system as <code>string</code>. Might be empty if no version can be determined.
|
|
19
|
+
* @name Device.os.versionStr
|
|
20
|
+
* @type String
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* The version of the operating system as <code>float</code>. Might be <code>-1</code> if no version can be determined.
|
|
24
|
+
* @name Device.os.version
|
|
25
|
+
* @type float
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* If this flag is set to <code>true</code>, a Windows operating system is used.
|
|
29
|
+
* @name Device.os.windows
|
|
30
|
+
* @type boolean
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* If this flag is set to <code>true</code>, a Mac operating system is used.
|
|
34
|
+
* @name Device.os.macintosh
|
|
35
|
+
* @type boolean
|
|
36
|
+
*/
|
|
37
|
+
/*
|
|
38
|
+
* If this flag is set to <code>true</code>, an iOS operating system is used.
|
|
39
|
+
* @name Device.os.ios
|
|
40
|
+
* @type boolean
|
|
41
|
+
*/
|
|
42
|
+
/**
|
|
43
|
+
* If this flag is set to <code>true</code>, an Android operating system is used.
|
|
44
|
+
* @name Device.os.android
|
|
45
|
+
* @type boolean
|
|
46
|
+
*/
|
|
47
|
+
/*
|
|
48
|
+
* Windows operating system name.
|
|
49
|
+
* @see Device.os.name
|
|
50
|
+
* @name Device.os.OS.WINDOWS
|
|
51
|
+
*/
|
|
52
|
+
/**
|
|
53
|
+
* MAC operating system name.
|
|
54
|
+
* @see Device.os.name
|
|
55
|
+
* @name Device.os.OS.MACINTOSH
|
|
56
|
+
*/
|
|
57
|
+
/**
|
|
58
|
+
* iOS operating system name.
|
|
59
|
+
* @see Device.os.name
|
|
60
|
+
* @name Device.os.OS.IOS
|
|
61
|
+
*/
|
|
62
|
+
/**
|
|
63
|
+
* Android operating system name.
|
|
64
|
+
* @see Device.os.name
|
|
65
|
+
* @name Device.os.OS.ANDROID
|
|
66
|
+
*/
|
|
67
|
+
const OS = {
|
|
68
|
+
WINDOWS: 'win',
|
|
69
|
+
MACINTOSH: 'mac',
|
|
70
|
+
IOS: 'iOS',
|
|
71
|
+
ANDROID: 'Android'
|
|
72
|
+
};
|
|
73
|
+
const _getMobileOS = () => {
|
|
74
|
+
const userAgent = navigator.userAgent;
|
|
75
|
+
// iOS, Android
|
|
76
|
+
let rPlatform = /\(([a-zA-Z ]+);\s(?:[U]?[;]?)([\D]+)((?:[\d._]*))(?:.*[)][^\d]*)([\d.]*)\s/;
|
|
77
|
+
let aMatches = userAgent.match(rPlatform);
|
|
78
|
+
if (aMatches) {
|
|
79
|
+
const rAppleDevices = /iPhone|iPad|iPod/;
|
|
80
|
+
if (aMatches[0].match(rAppleDevices)) {
|
|
81
|
+
aMatches[3] = aMatches[3].replace(/_/g, '.');
|
|
82
|
+
return {
|
|
83
|
+
name: OS.IOS,
|
|
84
|
+
versionStr: aMatches[3]
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
if (aMatches[2].match(/Android/)) {
|
|
88
|
+
aMatches[2] = aMatches[2].replace(/\s/g, '');
|
|
89
|
+
return {
|
|
90
|
+
name: OS.ANDROID,
|
|
91
|
+
versionStr: aMatches[3]
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Firefox on Android
|
|
96
|
+
rPlatform = /\((Android)[\s]?([\d][.\d]*)?;.*Firefox\/[\d][.\d]*/;
|
|
97
|
+
aMatches = userAgent.match(rPlatform);
|
|
98
|
+
if (aMatches) {
|
|
99
|
+
return {
|
|
100
|
+
name: OS.ANDROID,
|
|
101
|
+
versionStr: aMatches.length === 3 ? aMatches[2] : ''
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
return {};
|
|
105
|
+
};
|
|
106
|
+
const _getDesktopOS = () => {
|
|
107
|
+
const sPlatform = navigator.platform;
|
|
108
|
+
if (sPlatform.indexOf('Win') !== -1) {
|
|
109
|
+
const rVersion = /Windows NT (\d+).(\d)/i; // userAgent since windows 10: Windows NT 10[...]
|
|
110
|
+
const uaResult = navigator.userAgent.match(rVersion);
|
|
111
|
+
return {
|
|
112
|
+
name: OS.WINDOWS,
|
|
113
|
+
versionStr: (uaResult && uaResult[1]) || ''
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
if (sPlatform.indexOf('Mac') !== -1) {
|
|
117
|
+
return {
|
|
118
|
+
name: OS.MACINTOSH,
|
|
119
|
+
versionStr: ''
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
};
|
|
124
|
+
const _getOS = () => _getMobileOS() || _getDesktopOS();
|
|
125
|
+
const _setOS = () => {
|
|
126
|
+
if (Device.os) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
Device.os = _getOS() || {};
|
|
130
|
+
Device.os.OS = OS;
|
|
131
|
+
Device.os.version = Device.os.versionStr ? parseFloat(Device.os.versionStr) : -1;
|
|
132
|
+
if (Device.os.name) {
|
|
133
|
+
Object.keys(OS).forEach((name) => {
|
|
134
|
+
if (OS[name] === Device.os.name) {
|
|
135
|
+
Device.os[name.toLowerCase()] = true;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
const getOS = () => {
|
|
141
|
+
if (!Device.os) {
|
|
142
|
+
_setOS();
|
|
143
|
+
}
|
|
144
|
+
return Device.os;
|
|
145
|
+
};
|
|
146
|
+
const isAndroid = () => {
|
|
147
|
+
if (!Device.os) {
|
|
148
|
+
_setOS();
|
|
149
|
+
}
|
|
150
|
+
return !!Device.os.android;
|
|
151
|
+
};
|
|
152
|
+
// * ******* Browser Detection ********
|
|
153
|
+
/**
|
|
154
|
+
* Contains information about the used browser.
|
|
155
|
+
* @name Device.browser
|
|
156
|
+
*/
|
|
157
|
+
/**
|
|
158
|
+
* Enumeration containing the names of known browsers.
|
|
159
|
+
* @name Device.browser.BROWSER
|
|
160
|
+
*
|
|
161
|
+
* The name of the browser.
|
|
162
|
+
* @name Device.browser.name
|
|
163
|
+
* @type String
|
|
164
|
+
*/
|
|
165
|
+
/**
|
|
166
|
+
* The version of the browser as <code>string</code>. Might be empty if no version can be determined.
|
|
167
|
+
* @name Device.browser.versionStr
|
|
168
|
+
* @type String
|
|
169
|
+
*/
|
|
170
|
+
/**
|
|
171
|
+
* The version of the browser as <code>float</code>. Might be <code>-1</code> if no version can be determined.
|
|
172
|
+
* @name Device.browser.version
|
|
173
|
+
* @type float
|
|
174
|
+
*/
|
|
175
|
+
/**
|
|
176
|
+
* If this flag is set to <code>true</code>, the mobile variant of the browser is used or
|
|
177
|
+
* a tablet or phone device is detected. This information might not be available for all browsers.
|
|
178
|
+
* @name Device.browser.mobile
|
|
179
|
+
* @type boolean
|
|
180
|
+
*/
|
|
181
|
+
/**
|
|
182
|
+
* If this flag is set to <code>true</code>, the Microsoft Internet Explorer browser is used.
|
|
183
|
+
* @name Device.browser.internet_explorer
|
|
184
|
+
* @type boolean
|
|
185
|
+
* @deprecated since 1.20, use {@link Device.browser.msie} instead.
|
|
186
|
+
*/
|
|
187
|
+
/**
|
|
188
|
+
* If this flag is set to <code>true</code>, the Microsoft Internet Explorer browser is used.
|
|
189
|
+
* @name Device.browser.msie
|
|
190
|
+
* @type boolean
|
|
191
|
+
*/
|
|
192
|
+
/**
|
|
193
|
+
* If this flag is set to <code>true</code>, the Microsoft Edge browser is used.
|
|
194
|
+
* @name Device.browser.edge
|
|
195
|
+
* @type boolean
|
|
196
|
+
*/
|
|
197
|
+
/**
|
|
198
|
+
* If this flag is set to <code>true</code>, the Mozilla Firefox browser is used.
|
|
199
|
+
* @name Device.browser.firefox
|
|
200
|
+
*/
|
|
201
|
+
/**
|
|
202
|
+
* If this flag is set to <code>true</code>, the Google Chrome browser is used.
|
|
203
|
+
* @name Device.browser.chrome
|
|
204
|
+
* @type boolean
|
|
205
|
+
*
|
|
206
|
+
* If this flag is set to <code>true</code>, the Apple Safari browser is used.
|
|
207
|
+
*
|
|
208
|
+
* <b>Note:</b>
|
|
209
|
+
* This flag is also <code>true</code> when the standalone (fullscreen) mode or webview is used on iOS devices.
|
|
210
|
+
* Please also note the flags {@link Device.browser.fullscreen} and {@link Device.browser.webview}.
|
|
211
|
+
*
|
|
212
|
+
* @name Device.browser.safari
|
|
213
|
+
* @type boolean
|
|
214
|
+
*/
|
|
215
|
+
/**
|
|
216
|
+
* If this flag is set to <code>true</code>, a browser featuring a Webkit engine is used.
|
|
217
|
+
*
|
|
218
|
+
* <b>Note:</b>
|
|
219
|
+
* This flag is also <code>true</code> when the used browser was based on the Webkit engine, but
|
|
220
|
+
* uses another rendering engine in the meantime. For example the Chrome browser started from version 28 and above
|
|
221
|
+
* uses the Blink rendering engine.
|
|
222
|
+
*
|
|
223
|
+
* @name Device.browser.webkit
|
|
224
|
+
* @type boolean
|
|
225
|
+
*/
|
|
226
|
+
/**
|
|
227
|
+
* If this flag is set to <code>true</code>, the Safari browser runs in standalone fullscreen mode on iOS.
|
|
228
|
+
*
|
|
229
|
+
* <b>Note:</b> This flag is only available if the Safari browser was detected. Furthermore, if this mode is detected,
|
|
230
|
+
* technically not a standard Safari is used. There might be slight differences in behavior and detection, e.g.
|
|
231
|
+
* the availability of {@link Device.browser.version}.
|
|
232
|
+
*
|
|
233
|
+
* @name Device.browser.fullscreen
|
|
234
|
+
* @type boolean
|
|
235
|
+
*/
|
|
236
|
+
/**
|
|
237
|
+
* If this flag is set to <code>true</code>, the Safari browser runs in webview mode on iOS.
|
|
238
|
+
*
|
|
239
|
+
* <b>Note:</b> This flag is only available if the Safari browser was detected. Furthermore, if this mode is detected,
|
|
240
|
+
* technically not a standard Safari is used. There might be slight differences in behavior and detection, e.g.
|
|
241
|
+
* the availability of {@link Device.browser.version}.
|
|
242
|
+
*
|
|
243
|
+
* @name Device.browser.webview
|
|
244
|
+
* @type boolean
|
|
245
|
+
*/
|
|
246
|
+
/**
|
|
247
|
+
* If this flag is set to <code>true</code>, the Phantom JS browser is used.
|
|
248
|
+
* @name Device.browser.phantomJS
|
|
249
|
+
* @type boolean
|
|
250
|
+
*/
|
|
251
|
+
/**
|
|
252
|
+
* The version of the used Webkit engine, if available.
|
|
253
|
+
* @name Device.browser.webkitVersion
|
|
254
|
+
* @type String
|
|
255
|
+
*/
|
|
256
|
+
/**
|
|
257
|
+
* If this flag is set to <code>true</code>, a browser featuring a Mozilla engine is used.
|
|
258
|
+
* @name Device.browser.mozilla
|
|
259
|
+
* @type boolean
|
|
260
|
+
*/
|
|
261
|
+
/**
|
|
262
|
+
* Internet Explorer browser name.
|
|
263
|
+
* @name Device.browser.BROWSER.INTERNET_EXPLORER
|
|
264
|
+
*/
|
|
265
|
+
/**
|
|
266
|
+
* Edge browser name.
|
|
267
|
+
* @name Device.browser.BROWSER.EDGE
|
|
268
|
+
*/
|
|
269
|
+
/**
|
|
270
|
+
* Firefox browser name.
|
|
271
|
+
* @name Device.browser.BROWSER.FIREFOX
|
|
272
|
+
*/
|
|
273
|
+
/**
|
|
274
|
+
* Chrome browser name.
|
|
275
|
+
* @name Device.browser.BROWSER.CHROME
|
|
276
|
+
*/
|
|
277
|
+
/**
|
|
278
|
+
* Safari browser name.
|
|
279
|
+
* @name Device.browser.BROWSER.SAFARI
|
|
280
|
+
*/
|
|
281
|
+
/**
|
|
282
|
+
* Android stock browser name.
|
|
283
|
+
* @name Device.browser.BROWSER.ANDROID
|
|
284
|
+
*/
|
|
285
|
+
const BROWSER = {
|
|
286
|
+
INTERNET_EXPLORER: 'ie',
|
|
287
|
+
EDGE: 'ed',
|
|
288
|
+
FIREFOX: 'ff',
|
|
289
|
+
CHROME: 'cr',
|
|
290
|
+
SAFARI: 'sf',
|
|
291
|
+
ANDROID: 'an'
|
|
292
|
+
};
|
|
293
|
+
/* !
|
|
294
|
+
* Taken from jQuery JavaScript Library v1.7.1
|
|
295
|
+
* http://jquery.com/
|
|
296
|
+
*
|
|
297
|
+
* Copyright 2011, John Resig
|
|
298
|
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
|
299
|
+
* http://jquery.org/license
|
|
300
|
+
*
|
|
301
|
+
* Includes Sizzle.js
|
|
302
|
+
* http://sizzlejs.com/
|
|
303
|
+
* Copyright 2011, The Dojo Foundation
|
|
304
|
+
* Released under the MIT, BSD, and GPL Licenses.
|
|
305
|
+
*
|
|
306
|
+
* Date: Mon Nov 21 21:11:03 2011 -0500
|
|
307
|
+
*/
|
|
308
|
+
const _calcBrowser = () => {
|
|
309
|
+
const sUserAgent = navigator.userAgent.toLowerCase();
|
|
310
|
+
const rwebkit = /(webkit)[ /]([\w.]+)/;
|
|
311
|
+
const rmsie = /(msie) ([\w.]+)/;
|
|
312
|
+
const rmsie11 = /(trident)\/[\w.]+;.*rv:([\w.]+)/;
|
|
313
|
+
const redge = /(edge)[ /]([\w.]+)/;
|
|
314
|
+
const rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/;
|
|
315
|
+
// WinPhone IE11 and MS Edge userAgents contain "WebKit" and "Mozilla" and therefore must be checked first
|
|
316
|
+
const browserMatch = redge.exec(sUserAgent) ||
|
|
317
|
+
rmsie11.exec(sUserAgent) ||
|
|
318
|
+
rwebkit.exec(sUserAgent) ||
|
|
319
|
+
rmsie.exec(sUserAgent) ||
|
|
320
|
+
(sUserAgent.indexOf('compatible') < 0 && rmozilla.exec(sUserAgent)) ||
|
|
321
|
+
[];
|
|
322
|
+
const oRes = {
|
|
323
|
+
browser: browserMatch[1] || '',
|
|
324
|
+
version: browserMatch[2] || '0'
|
|
325
|
+
};
|
|
326
|
+
oRes[oRes.browser] = true;
|
|
327
|
+
return oRes;
|
|
328
|
+
};
|
|
329
|
+
const _getBrowser = () => {
|
|
330
|
+
const oBrowser = _calcBrowser();
|
|
331
|
+
const sUserAgent = navigator.userAgent;
|
|
332
|
+
const oNavigator = window.navigator;
|
|
333
|
+
// jQuery checks for user agent strings. We differentiate between browsers
|
|
334
|
+
let oExpMobile;
|
|
335
|
+
let oResult;
|
|
336
|
+
let fVersion;
|
|
337
|
+
// Mozilla
|
|
338
|
+
if (oBrowser.mozilla) {
|
|
339
|
+
oExpMobile = /Mobile/;
|
|
340
|
+
if (sUserAgent.match(/Firefox\/(\d+\.\d+)/)) {
|
|
341
|
+
fVersion = parseFloat(RegExp.$1);
|
|
342
|
+
oResult = {
|
|
343
|
+
name: BROWSER.FIREFOX,
|
|
344
|
+
versionStr: `${fVersion}`,
|
|
345
|
+
version: fVersion,
|
|
346
|
+
mozilla: true,
|
|
347
|
+
mobile: oExpMobile.test(sUserAgent)
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
// unknown mozilla browser
|
|
352
|
+
oResult = {
|
|
353
|
+
mobile: oExpMobile.test(sUserAgent),
|
|
354
|
+
mozilla: true,
|
|
355
|
+
version: -1
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
else if (oBrowser.webkit) {
|
|
360
|
+
// webkit version is needed for calculation if the mobile android device is a tablet (calculation of other mobile devices work without)
|
|
361
|
+
const regExpWebkitVersion = sUserAgent.toLowerCase().match(/webkit[/]([\d.]+)/);
|
|
362
|
+
let webkitVersion;
|
|
363
|
+
if (regExpWebkitVersion) {
|
|
364
|
+
webkitVersion = regExpWebkitVersion[1];
|
|
365
|
+
}
|
|
366
|
+
oExpMobile = /Mobile/;
|
|
367
|
+
const aChromeMatch = sUserAgent.match(/(Chrome|CriOS)\/(\d+\.\d+).\d+/);
|
|
368
|
+
const aFirefoxMatch = sUserAgent.match(/FxiOS\/(\d+\.\d+)/);
|
|
369
|
+
const aAndroidMatch = sUserAgent.match(/Android .+ Version\/(\d+\.\d+)/);
|
|
370
|
+
if (aChromeMatch || aFirefoxMatch || aAndroidMatch) {
|
|
371
|
+
let sName;
|
|
372
|
+
let sVersion;
|
|
373
|
+
let bMobile;
|
|
374
|
+
if (aChromeMatch) {
|
|
375
|
+
sName = BROWSER.CHROME;
|
|
376
|
+
bMobile = oExpMobile.test(sUserAgent);
|
|
377
|
+
sVersion = parseFloat(aChromeMatch[2]);
|
|
378
|
+
}
|
|
379
|
+
else if (aFirefoxMatch) {
|
|
380
|
+
sName = BROWSER.FIREFOX;
|
|
381
|
+
bMobile = true;
|
|
382
|
+
sVersion = parseFloat(aFirefoxMatch[1]);
|
|
383
|
+
}
|
|
384
|
+
else if (aAndroidMatch) {
|
|
385
|
+
sName = BROWSER.ANDROID;
|
|
386
|
+
bMobile = oExpMobile.test(sUserAgent);
|
|
387
|
+
sVersion = parseFloat(aAndroidMatch[1]);
|
|
388
|
+
}
|
|
389
|
+
oResult = {
|
|
390
|
+
name: sName,
|
|
391
|
+
mobile: bMobile,
|
|
392
|
+
versionStr: `${sVersion}`,
|
|
393
|
+
version: sVersion,
|
|
394
|
+
webkit: true,
|
|
395
|
+
webkitVersion
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
// Safari might have an issue with sUserAgent.match(...); thus changing
|
|
400
|
+
const oExp = /(Version|PhantomJS)\/(\d+\.\d+).*Safari/;
|
|
401
|
+
const bStandalone = oNavigator.standalone;
|
|
402
|
+
if (oExp.test(sUserAgent)) {
|
|
403
|
+
const aParts = oExp.exec(sUserAgent);
|
|
404
|
+
fVersion = parseFloat(aParts[2]);
|
|
405
|
+
oResult = {
|
|
406
|
+
name: BROWSER.SAFARI,
|
|
407
|
+
versionStr: `${fVersion}`,
|
|
408
|
+
fullscreen: false,
|
|
409
|
+
webview: false,
|
|
410
|
+
version: fVersion,
|
|
411
|
+
mobile: oExpMobile.test(sUserAgent),
|
|
412
|
+
webkit: true,
|
|
413
|
+
webkitVersion,
|
|
414
|
+
phantomJS: aParts[1] === 'PhantomJS'
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
else if (/iPhone|iPad|iPod/.test(sUserAgent) &&
|
|
418
|
+
!/CriOS/.test(sUserAgent) &&
|
|
419
|
+
!/FxiOS/.test(sUserAgent) &&
|
|
420
|
+
(bStandalone === true || bStandalone === false)) {
|
|
421
|
+
// WebView or Standalone mode on iOS
|
|
422
|
+
oResult = {
|
|
423
|
+
name: BROWSER.SAFARI,
|
|
424
|
+
version: -1,
|
|
425
|
+
fullscreen: bStandalone,
|
|
426
|
+
webview: !bStandalone,
|
|
427
|
+
mobile: oExpMobile.test(sUserAgent),
|
|
428
|
+
webkit: true,
|
|
429
|
+
webkitVersion
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
// other webkit based browser
|
|
434
|
+
oResult = {
|
|
435
|
+
mobile: oExpMobile.test(sUserAgent),
|
|
436
|
+
webkit: true,
|
|
437
|
+
webkitVersion,
|
|
438
|
+
version: -1
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
else if (oBrowser.msie || oBrowser.trident) {
|
|
444
|
+
fVersion = parseFloat(oBrowser.version);
|
|
445
|
+
oResult = {
|
|
446
|
+
name: BROWSER.INTERNET_EXPLORER,
|
|
447
|
+
versionStr: `${fVersion}`,
|
|
448
|
+
version: fVersion,
|
|
449
|
+
msie: true,
|
|
450
|
+
mobile: false
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
else if (oBrowser.edge) {
|
|
454
|
+
fVersion = parseFloat(oBrowser.version);
|
|
455
|
+
oResult = {
|
|
456
|
+
name: BROWSER.EDGE,
|
|
457
|
+
versionStr: `${fVersion}`,
|
|
458
|
+
version: fVersion,
|
|
459
|
+
edge: true
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
else {
|
|
463
|
+
oResult = {
|
|
464
|
+
name: '',
|
|
465
|
+
versionStr: '',
|
|
466
|
+
version: -1,
|
|
467
|
+
mobile: false
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
return oResult;
|
|
471
|
+
};
|
|
472
|
+
const _setBrowser = () => {
|
|
473
|
+
Device.browser = _getBrowser();
|
|
474
|
+
Device.browser.BROWSER = BROWSER;
|
|
475
|
+
if (Device.browser.name) {
|
|
476
|
+
Object.keys(BROWSER).forEach((b) => {
|
|
477
|
+
if (BROWSER[b] === Device.browser.name) {
|
|
478
|
+
Device.browser[b.toLowerCase()] = true;
|
|
479
|
+
}
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
const getBrowser = () => {
|
|
484
|
+
if (!Device.browser) {
|
|
485
|
+
_setBrowser();
|
|
486
|
+
}
|
|
487
|
+
return Device.browser;
|
|
488
|
+
};
|
|
489
|
+
const isIE = () => {
|
|
490
|
+
if (!Device.browser) {
|
|
491
|
+
_setBrowser();
|
|
492
|
+
}
|
|
493
|
+
return !!Device.browser.msie;
|
|
494
|
+
};
|
|
495
|
+
const isEdge = () => {
|
|
496
|
+
if (!Device.browser) {
|
|
497
|
+
_setBrowser();
|
|
498
|
+
}
|
|
499
|
+
return !!Device.browser.edge;
|
|
500
|
+
};
|
|
501
|
+
const isChrome = () => {
|
|
502
|
+
if (!Device.browser) {
|
|
503
|
+
_setBrowser();
|
|
504
|
+
}
|
|
505
|
+
return !!Device.browser.chrome;
|
|
506
|
+
};
|
|
507
|
+
const isFF = () => {
|
|
508
|
+
if (!Device.browser) {
|
|
509
|
+
_setBrowser();
|
|
510
|
+
}
|
|
511
|
+
return !!Device.browser.firefox;
|
|
512
|
+
};
|
|
513
|
+
const isSafari = () => {
|
|
514
|
+
if (!Device.browser) {
|
|
515
|
+
_setBrowser();
|
|
516
|
+
}
|
|
517
|
+
return !!Device.browser.safari;
|
|
518
|
+
};
|
|
519
|
+
// * ******* Support Detection ********
|
|
520
|
+
const _setSupport = () => {
|
|
521
|
+
if (Device.support) {
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
if (!Device.browser) {
|
|
525
|
+
_setBrowser();
|
|
526
|
+
}
|
|
527
|
+
Device.support = {};
|
|
528
|
+
Device.support.touch = !!('ontouchstart' in window ||
|
|
529
|
+
navigator.maxTouchPoints > 0 ||
|
|
530
|
+
(window.DocumentTouch && document instanceof window.DocumentTouch));
|
|
531
|
+
};
|
|
532
|
+
const supportTouch = () => {
|
|
533
|
+
if (!Device.support) {
|
|
534
|
+
_setSupport();
|
|
535
|
+
}
|
|
536
|
+
return !!Device.support.touch;
|
|
537
|
+
};
|
|
538
|
+
// * ******* System Detection ********
|
|
539
|
+
/**
|
|
540
|
+
* Provides a basic categorization of the used device based on various indicators.
|
|
541
|
+
*
|
|
542
|
+
* <b>Note:</b> Depending on the capabilities of the device it is also possible that multiple flags are set to <code>true</code>.
|
|
543
|
+
*
|
|
544
|
+
* @namespace
|
|
545
|
+
* @name Device.system
|
|
546
|
+
*/
|
|
547
|
+
/**
|
|
548
|
+
* If this flag is set to <code>true</code>, the device is recognized as a phone.
|
|
549
|
+
*
|
|
550
|
+
* @name Device.system.phone
|
|
551
|
+
* @type boolean
|
|
552
|
+
*/
|
|
553
|
+
/**
|
|
554
|
+
* @name Device.system.SYSTEMTYPE
|
|
555
|
+
* Enumeration containing the names of known types of the devices.
|
|
556
|
+
*/
|
|
557
|
+
const SYSTEMTYPE = {
|
|
558
|
+
TABLET: 'tablet',
|
|
559
|
+
PHONE: 'phone',
|
|
560
|
+
DESKTOP: 'desktop',
|
|
561
|
+
COMBI: 'combi'
|
|
562
|
+
};
|
|
563
|
+
const _isTablet = () => {
|
|
564
|
+
const sUserAgent = navigator.userAgent;
|
|
565
|
+
if (Device.os.name === Device.os.OS.IOS) {
|
|
566
|
+
return /ipad/i.test(sUserAgent);
|
|
567
|
+
}
|
|
568
|
+
// in real mobile device
|
|
569
|
+
if (supportTouch()) {
|
|
570
|
+
if (Device.os.windows && Device.os.version >= 8) {
|
|
571
|
+
return true;
|
|
572
|
+
}
|
|
573
|
+
if (Device.browser.chrome && Device.os.android && Device.os.version >= 4.4) {
|
|
574
|
+
return !/Mobile Safari\/[.0-9]+/.test(sUserAgent);
|
|
575
|
+
}
|
|
576
|
+
let densityFactor = window.devicePixelRatio ? window.devicePixelRatio : 1; // may be undefined in Windows Phone devices
|
|
577
|
+
// On Android sometimes window.screen.width returns the logical CSS pixels, sometimes the physical device pixels;
|
|
578
|
+
// Tests on multiple devices suggest this depends on the Webkit version.
|
|
579
|
+
// The Webkit patch which changed the behavior was done here: https://bugs.webkit.org/show_bug.cgi?id=106460
|
|
580
|
+
// Chrome 27 with Webkit 537.36 returns the logical pixels,
|
|
581
|
+
// Chrome 18 with Webkit 535.19 returns the physical pixels.
|
|
582
|
+
// The BlackBerry 10 browser with Webkit 537.10+ returns the physical pixels.
|
|
583
|
+
// So it appears like somewhere above Webkit 537.10 we do not hve to divide by the devicePixelRatio anymore.
|
|
584
|
+
if (Device.os.android && Device.browser.webkit && parseFloat(Device.browser.webkitVersion) > 537.1) {
|
|
585
|
+
densityFactor = 1;
|
|
586
|
+
}
|
|
587
|
+
// this is how android distinguishes between tablet and phone
|
|
588
|
+
// http://android-developers.blogspot.de/2011/07/new-tools-for-managing-screen-sizes.html
|
|
589
|
+
const bTablet = Math.min(window.screen.width / densityFactor, window.screen.height / densityFactor) >= 600;
|
|
590
|
+
// special workaround for Nexus 7 where the window.screen.width is 600px or 601px in portrait mode (=> tablet)
|
|
591
|
+
// but window.screen.height 552px in landscape mode (=> phone), because the browser UI takes some space on top.
|
|
592
|
+
// So the detected device type depends on the orientation :-(
|
|
593
|
+
// actually this is a Chrome bug, as "width"/"height" should return the entire screen's dimensions and
|
|
594
|
+
// "availWidth"/"availHeight" should return the size available after subtracting the browser UI
|
|
595
|
+
/*
|
|
596
|
+
if (isLandscape() &&
|
|
597
|
+
(window.screen.height === 552 || window.screen.height === 553) // old/new Nexus 7
|
|
598
|
+
&&
|
|
599
|
+
(/Nexus 7/i.test(sUserAgent))) {
|
|
600
|
+
bTablet = true;
|
|
601
|
+
}
|
|
602
|
+
*/
|
|
603
|
+
return bTablet;
|
|
604
|
+
}
|
|
605
|
+
// This simple android phone detection can be used here because this is the mobile emulation mode in desktop browser
|
|
606
|
+
const bAndroidPhone = /(?=android)(?=.*mobile)/i.test(sUserAgent);
|
|
607
|
+
// in desktop browser, it's detected as tablet when
|
|
608
|
+
// 1. Windows 8 device with a touch screen where "Touch" is contained in the userAgent
|
|
609
|
+
// 2. Android emulation and it's not an Android phone
|
|
610
|
+
return (Device.browser.msie && sUserAgent.indexOf('Touch') !== -1) || (Device.os.android && !bAndroidPhone);
|
|
611
|
+
};
|
|
612
|
+
const _getSystem = () => {
|
|
613
|
+
const bTabletDetected = _isTablet();
|
|
614
|
+
const isWin8Upwards = Device.os.windows && Device.os.version >= 8;
|
|
615
|
+
const oSystem = {};
|
|
616
|
+
oSystem.tablet = !!((Device.support.touch || isWin8Upwards) && bTabletDetected);
|
|
617
|
+
oSystem.phone = !!((Device.os.windows_phone || Device.support.touch) && !bTabletDetected);
|
|
618
|
+
oSystem.desktop = !!((!oSystem.tablet && !oSystem.phone) || isWin8Upwards);
|
|
619
|
+
oSystem.combi = oSystem.desktop && oSystem.tablet;
|
|
620
|
+
oSystem.SYSTEMTYPE = SYSTEMTYPE;
|
|
621
|
+
return oSystem;
|
|
622
|
+
};
|
|
623
|
+
const _setSystem = () => {
|
|
624
|
+
_setSupport();
|
|
625
|
+
_setOS();
|
|
626
|
+
Device.system = {};
|
|
627
|
+
Device.system = _getSystem();
|
|
628
|
+
if (Device.system.tablet || Device.system.phone) {
|
|
629
|
+
Device.browser.mobile = true;
|
|
630
|
+
}
|
|
631
|
+
};
|
|
632
|
+
const getSystem = () => {
|
|
633
|
+
if (!Device.system) {
|
|
634
|
+
_setSystem();
|
|
635
|
+
}
|
|
636
|
+
return Device.system;
|
|
637
|
+
};
|
|
638
|
+
const isDesktop = () => {
|
|
639
|
+
if (!Device.system) {
|
|
640
|
+
_setSystem();
|
|
641
|
+
}
|
|
642
|
+
return Device.system.desktop;
|
|
643
|
+
};
|
|
644
|
+
const isTablet = () => {
|
|
645
|
+
if (!Device.system) {
|
|
646
|
+
_setSystem();
|
|
647
|
+
}
|
|
648
|
+
return Device.system.tablet;
|
|
649
|
+
};
|
|
650
|
+
const isPhone = () => {
|
|
651
|
+
if (!Device.system) {
|
|
652
|
+
_setSystem();
|
|
653
|
+
}
|
|
654
|
+
return Device.system.phone;
|
|
655
|
+
};
|
|
656
|
+
const isMobile = () => {
|
|
657
|
+
if (!Device.system) {
|
|
658
|
+
_setSystem();
|
|
659
|
+
}
|
|
660
|
+
return Device.browser.mobile;
|
|
661
|
+
};
|
|
662
|
+
export { isIE, isEdge, isChrome, isFF, isSafari, isMobile, isDesktop, isTablet, isPhone, isAndroid, getOS, getSystem, getBrowser, supportTouch };
|
|
663
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGV2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvYmFyc2Etbm92aW4tcmF5LWNvcmUvc3JjL2xpYi9kZXZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsb0JBQW9CO0FBRXBCLE1BQU0sTUFBTSxHQUEyQixFQUFFLENBQUM7QUFFMUMsa0NBQWtDO0FBRWxDOzs7R0FHRztBQUVIOzs7R0FHRztBQUVIOzs7O0dBSUc7QUFFSDs7OztHQUlHO0FBRUg7Ozs7R0FJRztBQUVIOzs7O0dBSUc7QUFFSDs7OztHQUlHO0FBRUg7Ozs7R0FJRztBQUVIOzs7O0dBSUc7QUFFSDs7OztHQUlHO0FBRUg7Ozs7R0FJRztBQUVIOzs7O0dBSUc7QUFFSDs7OztHQUlHO0FBRUgsTUFBTSxFQUFFLEdBQUc7SUFDUCxPQUFPLEVBQUUsS0FBSztJQUNkLFNBQVMsRUFBRSxLQUFLO0lBQ2hCLEdBQUcsRUFBRSxLQUFLO0lBQ1YsT0FBTyxFQUFFLFNBQVM7Q0FDckIsQ0FBQztBQUVGLE1BQU0sWUFBWSxHQUFHLEdBQUcsRUFBRTtJQUN0QixNQUFNLFNBQVMsR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDO0lBRXRDLGVBQWU7SUFDZixJQUFJLFNBQVMsR0FBRyw0RUFBNEUsQ0FBQztJQUM3RixJQUFJLFFBQVEsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBRTFDLElBQUksUUFBUSxFQUFFO1FBQ1YsTUFBTSxhQUFhLEdBQUcsa0JBQWtCLENBQUM7UUFFekMsSUFBSSxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxFQUFFO1lBQ2xDLFFBQVEsQ0FBQyxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztZQUU3QyxPQUFPO2dCQUNILElBQUksRUFBRSxFQUFFLENBQUMsR0FBRztn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QUFFRixNQUFNLFFBQVEsR0FBRyxHQUFHLEVBQUU7SUFDbEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUU7UUFDaEIsVUFBVSxFQUFFLENBQUM7S0FDaEI7SUFFRCxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDO0FBQ2hDLENBQUMsQ0FBQztBQUVGLE1BQU0sT0FBTyxHQUFHLEdBQUcsRUFBRTtJQUNqQixJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRTtRQUNoQixVQUFVLEVBQUUsQ0FBQztLQUNoQjtJQUVELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUM7QUFDL0IsQ0FBQyxDQUFDO0FBRUYsTUFBTSxRQUFRLEdBQUcsR0FBRyxFQUFFO0lBQ2xCLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFO1FBQ2hCLFVBQVUsRUFBRSxDQUFDO0tBQ2hCO0lBRUQsT0FBTyxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQztBQUNqQyxDQUFDLENBQUM7QUFFRixPQUFPLEVBQ0gsSUFBSSxFQUNKLE1BQU0sRUFDTixRQUFRLEVBQ1IsSUFBSSxFQUNKLFFBQVEsRUFDUixRQUFRLEVBQ1IsU0FBUyxFQUNULFFBQVEsRUFDUixPQUFPLEVBQ1AsU0FBUyxFQUNULEtBQUssRUFDTCxTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDZixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgKi9cclxuXHJcbmNvbnN0IERldmljZTogeyBba2V5OiBzdHJpbmddOiBhbnkgfSA9IHt9O1xyXG5cclxuLy8gKiAqKioqKioqIE9TIERldGVjdGlvbiAqKioqKioqKlxyXG5cclxuLyoqXHJcbiAqIENvbnRhaW5zIGluZm9ybWF0aW9uIGFib3V0IHRoZSBvcGVyYXRpbmcgc3lzdGVtIG9mIHRoZSBEZXZpY2UuXHJcbiAqIEBuYW1lIERldmljZS5vc1xyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBFbnVtZXJhdGlvbiBjb250YWluaW5nIHRoZSBuYW1lcyBvZiBrbm93biBvcGVyYXRpbmcgc3lzdGVtcy5cclxuICogQG5hbWUgRGV2aWNlLm9zLk9TXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIFRoZSBuYW1lIG9mIHRoZSBvcGVyYXRpbmcgc3lzdGVtLlxyXG4gKiBAbmFtZSBEZXZpY2Uub3MubmFtZVxyXG4gKiBAdHlwZSBTdHJpbmdcclxuICovXHJcblxyXG4vKipcclxuICogVGhlIHZlcnNpb24gb2YgdGhlIG9wZXJhdGluZyBzeXN0ZW0gYXMgPGNvZGU+c3RyaW5nPC9jb2RlPi4gTWlnaHQgYmUgZW1wdHkgaWYgbm8gdmVyc2lvbiBjYW4gYmUgZGV0ZXJtaW5lZC5cclxuICogQG5hbWUgRGV2aWNlLm9zLnZlcnNpb25TdHJcclxuICogQHR5cGUgU3RyaW5nXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIFRoZSB2ZXJzaW9uIG9mIHRoZSBvcGVyYXRpbmcgc3lzdGVtIGFzIDxjb2RlPmZsb2F0PC9jb2RlPi4gTWlnaHQgYmUgPGNvZGU+LTE8L2NvZGU+IGlmIG5vIHZlcnNpb24gY2FuIGJlIGRldGVybWluZWQuXHJcbiAqIEBuYW1lIERldmljZS5vcy52ZXJzaW9uXHJcbiAqIEB0eXBlIGZsb2F0XHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIElmIHRoaXMgZmxhZyBpcyBzZXQgdG8gPGNvZGU+dHJ1ZTwvY29kZT4sIGEgV2luZG93cyBvcGVyYXRpbmcgc3lzdGVtIGlzIHVzZWQuXHJcbiAqIEBuYW1lIERldmljZS5vcy53aW5kb3dzXHJcbiAqIEB0eXBlIGJvb2xlYW5cclxuICovXHJcblxyXG4vKipcclxuICogSWYgdGhpcyBmbGFnIGlzIHNldCB0byA8Y29kZT50cnVlPC9jb2RlPiwgYSBNYWMgb3BlcmF0aW5nIHN5c3RlbSBpcyB1c2VkLlxyXG4gKiBAbmFtZSBEZXZpY2Uub3MubWFjaW50b3NoXHJcbiAqIEB0eXBlIGJvb2xlYW5cclxuICovXHJcblxyXG4vKlxyXG4gKiBJZiB0aGlzIGZsYWcgaXMgc2V0IHRvIDxjb2RlPnRydWU8L2NvZGU+LCBhbiBpT1Mgb3BlcmF0aW5nIHN5c3RlbSBpcyB1c2VkLlxyXG4gKiBAbmFtZSBEZXZpY2Uub3MuaW9zXHJcbiAqIEB0eXBlIGJvb2xlYW5cclxuICovXHJcblxyXG4vKipcclxuICogSWYgdGhpcyBmbGFnIGlzIHNldCB0byA8Y29kZT50cnVlPC9jb2RlPiwgYW4gQW5kcm9pZCBvcGVyYXRpbmcgc3lzdGVtIGlzIHVzZWQuXHJcbiAqIEBuYW1lIERldmljZS5vcy5hbmRyb2lkXHJcbiAqIEB0eXBlIGJvb2xlYW5cclxuICovXHJcblxyXG4vKlxyXG4gKiBXaW5kb3dzIG9wZXJhdGluZyBzeXN0ZW0gbmFtZS5cclxuICogQHNlZSBEZXZpY2Uub3MubmFtZVxyXG4gKiBAbmFtZSBEZXZpY2Uub3MuT1MuV0lORE9XU1xyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBNQUMgb3BlcmF0aW5nIHN5c3RlbSBuYW1lLlxyXG4gKiBAc2VlIERldmljZS5vcy5uYW1lXHJcbiAqIEBuYW1lIERldmljZS5vcy5PUy5NQUNJTlRPU0hcclxuICovXHJcblxyXG4vKipcclxuICogaU9TIG9wZXJhdGluZyBzeXN0ZW0gbmFtZS5cclxuICogQHNlZSBEZXZpY2Uub3MubmFtZVxyXG4gKiBAbmFtZSBEZXZpY2Uub3MuT1MuSU9TXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIEFuZHJvaWQgb3BlcmF0aW5nIHN5c3RlbSBuYW1lLlxyXG4gKiBAc2VlIERldmljZS5vcy5uYW1lXHJcbiAqIEBuYW1lIERldmljZS5vcy5PUy5BTkRST0lEXHJcbiAqL1xyXG5cclxuY29uc3QgT1MgPSB7XHJcbiAgICBXSU5ET1dTOiAnd2luJyxcclxuICAgIE1BQ0lOVE9TSDogJ21hYycsXHJcbiAgICBJT1M6ICdpT1MnLFxyXG4gICAgQU5EUk9JRDogJ0FuZHJvaWQnXHJcbn07XHJcblxyXG5jb25zdCBfZ2V0TW9iaWxlT1MgPSAoKSA9PiB7XHJcbiAgICBjb25zdCB1c2VyQWdlbnQgPSBuYXZpZ2F0b3IudXNlckFnZW50O1xyXG5cclxuICAgIC8vIGlPUywgQW5kcm9pZFxyXG4gICAgbGV0IHJQbGF0Zm9ybSA9IC9cXCgoW2EtekEtWiBdKyk7XFxzKD86W1VdP1s7XT8pKFtcXERdKykoKD86W1xcZC5fXSopKSg/Oi4qWyldW15cXGRdKikoW1xcZC5dKilcXHMvO1xyXG4gICAgbGV0IGFNYXRjaGVzID0gdXNlckFnZW50Lm1hdGNoKHJQbGF0Zm9ybSk7XHJcblxyXG4gICAgaWYgKGFNYXRjaGVzKSB7XHJcbiAgICAgICAgY29uc3QgckFwcGxlRGV2aWNlcyA9IC9pUGhvbmV8aVBhZHxpUG9kLztcclxuXHJcbiAgICAgICAgaWYgKGFNYXRjaGVzWzBdLm1hdGNoKHJBcHBsZURldmljZXMpKSB7XHJcbiAgICAgICAgICAgIGFNYXRjaGVzWzNdID0gYU1hdGNoZXNbM10ucmVwbGFjZSgvXy9nLCAnLicpO1xyXG5cclxuICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgIG5hbWU6IE9TLklPUyxcclxuICAgICAgICAgICAgICAgIHZlcnNpb25TdHI6IGFNYXRjaGVzWzNdXHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoYU1hdGNoZXNbMl0ubWF0Y2goL0FuZHJvaWQvKSkge1xyXG4gICAgICAgICAgICBhTWF0Y2hlc1syXSA9IGFNYXRjaGVzWzJdLnJlcGxhY2UoL1xccy9nLCAnJyk7XHJcbiAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICBuYW1lOiBPUy5BTkRST0lELFxyXG4gICAgICAgICAgICAgICAgdmVyc2lvblN0cjogYU1hdGNoZXNbM11cclxuICAgICAgICAgICAgfTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gRmlyZWZveCBvbiBBbmRyb2lkXHJcbiAgICByUGxhdGZvcm0gPSAvXFwoKEFuZHJvaWQpW1xcc10/KFtcXGRdWy5cXGRdKik/Oy4qRmlyZWZveFxcL1tcXGRdWy5cXGRdKi87XHJcbiAgICBhTWF0Y2hlcyA9IHVzZXJBZ2VudC5tYXRjaChyUGxhdGZvcm0pO1xyXG4gICAgaWYgKGFNYXRjaGVzKSB7XHJcbiAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgbmFtZTogT1MuQU5EUk9JRCxcclxuICAgICAgICAgICAgdmVyc2lvblN0cjogYU1hdGNoZXMubGVuZ3RoID09PSAzID8gYU1hdGNoZXNbMl0gOiAnJ1xyXG4gICAgICAgIH07XHJcbiAgICB9XHJcbiAgICByZXR1cm4ge307XHJcbn07XHJcblxyXG5jb25zdCBfZ2V0RGVza3RvcE9TID0gKCkgPT4ge1xyXG4gICAgY29uc3Qgc1BsYXRmb3JtID0gbmF2aWdhdG9yLnBsYXRmb3JtO1xyXG4gICAgaWYgKHNQbGF0Zm9ybS5pbmRleE9mKCdXaW4nKSAhPT0gLTEpIHtcclxuICAgICAgICBjb25zdCByVmVyc2lvbiA9IC9XaW5kb3dzIE5UIChcXGQrKS4oXFxkKS9pOyAvLyB1c2VyQWdlbnQgc2luY2Ugd2luZG93cyAxMDogV2luZG93cyBOVCAxMFsuLi5dXHJcbiAgICAgICAgY29uc3QgdWFSZXN1bHQgPSBuYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKHJWZXJzaW9uKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgbmFtZTogT1MuV0lORE9XUyxcclxuICAgICAgICAgICAgdmVyc2lvblN0cjogKHVhUmVzdWx0ICYmIHVhUmVzdWx0WzFdKSB8fCAnJ1xyXG4gICAgICAgIH07XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHNQbGF0Zm9ybS5pbmRleE9mKCdNYWMnKSAhPT0gLTEpIHtcclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICBuYW1lOiBPUy5NQUNJTlRPU0gsXHJcbiAgICAgICAgICAgIHZlcnNpb25TdHI6ICcnXHJcbiAgICAgICAgfTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gbnVsbDtcclxufTtcclxuXHJcbmNvbnN0IF9nZXRPUyA9ICgpID0+IF9nZXRNb2JpbGVPUygpIHx8IF9nZXREZXNrdG9wT1MoKTtcclxuXHJcbmNvbnN0IF9zZXRPUyA9ICgpID0+IHtcclxuICAgIGlmIChEZXZpY2Uub3MpIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgRGV2aWNlLm9zID0gX2dldE9TKCkgfHwge307XHJcbiAgICBEZXZpY2Uub3MuT1MgPSBPUztcclxuICAgIERldmljZS5vcy52ZXJzaW9uID0gRGV2aWNlLm9zLnZlcnNpb25TdHIgPyBwYXJzZUZsb2F0KERldmljZS5vcy52ZXJzaW9uU3RyKSA6IC0xO1xyXG5cclxuICAgIGlmIChEZXZpY2Uub3MubmFtZSkge1xyXG4gICAgICAgIE9iamVjdC5rZXlzKE9TKS5mb3JFYWNoKChuYW1lKSA9PiB7XHJcbiAgICAgICAgICAgIGlmIChPU1tuYW1lXSA9PT0gRGV2aWNlLm9zLm5hbWUpIHtcclxuICAgICAgICAgICAgICAgIERldmljZS5vc1tuYW1lLnRvTG93ZXJDYXNlKCldID0gdHJ1ZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG59O1xyXG5cclxuY29uc3QgZ2V0T1MgPSAoKSA9PiB7XHJcbiAgICBpZiAoIURldmljZS5vcykge1xyXG4gICAgICAgIF9zZXRPUygpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBEZXZpY2Uub3M7XHJcbn07XHJcblxyXG5jb25zdCBpc0FuZHJvaWQgPSAoKSA9PiB7XHJcbiAgICBpZiAoIURldmljZS5vcykge1xyXG4gICAgICAgIF9zZXRPUygpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiAhIURldmljZS5vcy5hbmRyb2lkO1xyXG59O1xyXG5cclxuLy8gKiAqKioqKioqIEJyb3dzZXIgRGV0ZWN0aW9uICoqKioqKioqXHJcblxyXG4vKipcclxuICogQ29udGFpbnMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHVzZWQgYnJvd3Nlci5cclxuICogQG5hbWUgRGV2aWNlLmJyb3dzZXJcclxuICovXHJcblxyXG4vKipcclxuICogRW51bWVyYXRpb24gY29udGFpbmluZyB0aGUgbmFtZXMgb2Yga25vd24gYnJvd3NlcnMuXHJcbiAqIEBuYW1lIERldmljZS5icm93c2VyLkJST1dTRVJcclxuICpcclxuICogVGhlIG5hbWUgb2YgdGhlIGJyb3dzZXIuXHJcbiAqIEBuYW1lIERldmljZS5icm93c2VyLm5hbWVcclxuICogQHR5cGUgU3RyaW5nXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIFRoZSB2ZXJzaW9uIG9mIHRoZSBicm93c2VyIGFzIDxjb2RlPnN0cmluZzwvY29kZT4uIE1pZ2h0IGJlIGVtcHR5IGlmIG5vIHZlcnNpb24gY2FuIGJlIGRldGVybWluZWQuXHJcbiAqIEBuYW1lIERldmljZS5icm93c2VyLnZlcnNpb25TdHJcclxuICogQHR5cGUgU3RyaW5nXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIFRoZSB2ZXJzaW9uIG9mIHRoZSBicm93c2VyIGFzIDxjb2RlPmZsb2F0PC9jb2RlPi4gTWlnaHQgYmUgPGNvZGU+LTE8L2NvZGU+IGlmIG5vIHZlcnNpb24gY2FuIGJlIGRldGVybWluZWQuXHJcbiAqIEBuYW1lIERldmljZS5icm93c2VyLnZlcnNpb25cclxuICogQHR5cGUgZmxvYXRcclxuICovXHJcblxyXG4vKipcclxuICogSWYgdGhpcyBmbGFnIGlzIHNldCB0byA8Y29kZT50cnVlPC9jb2RlPiwgdGhlIG1vYmlsZSB2YXJpYW50IG9mIHRoZSBicm93c2VyIGlzIHVzZWQgb3JcclxuICogYSB0YWJsZXQgb3IgcGhvbmUgZGV2aWNlIGlzIGRldGVjdGVkLiBUaGlzIGluZm9ybWF0aW9uIG1pZ2h0IG5vdCBiZSBhdmFpbGFibGUgZm9yIGFsbCBicm93c2Vycy5cclxuICogQG5hbWUgRGV2aWNlLmJyb3dzZXIubW9iaWxlXHJcbiAqIEB0eXBlIGJvb2xlYW5cclxuICovXHJcblxyXG4vKipcclxuICogSWYgdGhpcyBmbGFnIGlzIHNldCB0byA8Y29kZT50cnVlPC9jb2RlPiwgdGhlIE1pY3Jvc29mdCBJbnRlcm5ldCBFeHBsb3JlciBicm93c2VyIGlzIHVzZWQuXHJcbiAqIEBuYW1lIERldmljZS5icm93c2VyLmludGVybmV0X2V4cGxvcmVyXHJcbiAqIEB0eXBlIGJvb2xlYW5cclxuICogQGRlcHJlY2F0ZWQgc2luY2UgMS4yMCwgdXNlIHtAbGluayBEZXZpY2UuYnJvd3Nlci5tc2llfSBpbnN0ZWFkLlxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBJZiB0aGlzIGZsYWcgaXMgc2V0IHRvIDxjb2RlPnRydWU8L2NvZGU+LCB0aGUgTWljcm9zb2Z0IEludGVybmV0IEV4cGxvcmVyIGJyb3dzZXIgaXMgdXNlZC5cclxuICogQG5hbWUgRGV2aWNlLmJyb3dzZXIubXNpZVxyXG4gKiBAdHlwZSBib29sZWFuXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIElmIHRoaXMgZmxhZyBpcyBzZXQgdG8gPGNvZGU+dHJ1ZTwvY29kZT4sIHRoZSBNaWNyb3NvZnQgRWRnZSBicm93c2VyIGlzIHVzZWQuXHJcbiAqIEBuYW1lIERldmljZS5icm93c2VyLmVkZ2VcclxuICogQHR5cGUgYm9vbGVhblxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBJZiB0aGlzIGZsYWcgaXMgc2V0IHRvIDxjb2RlPnRydWU8L2NvZGU+LCB0aGUgTW96aWxsYSBGaXJlZm94IGJyb3dzZXIgaXMgdXNlZC5cclxuICogQG5hbWUgRGV2aWNlLmJyb3dzZXIuZmlyZWZveFxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBJZiB0aGlzIGZsYWcgaXMgc2V0IHRvIDxjb2RlPnRydWU8L2NvZGU+LCB0aGUgR29vZ2xlIENocm9tZSBicm93c2VyIGlzIHVzZWQuXHJcbiAqIEBuYW1lIERldmljZS5icm93c2VyLmNocm9tZVxyXG4gKiBAdHlwZSBib29sZWFuXHJcbiAqXHJcbiAqIElmIHRoaXMgZmxhZyBpcyBzZXQgdG8gPGNvZGU+dHJ1ZTwvY29kZT4sIHRoZSBBcHBsZSBTYWZhcmkgYnJvd3NlciBpcyB1c2VkLlxyXG4gKlxyXG4gKiA8Yj5Ob3RlOjwvYj5cclxuICogVGhpcyBmbGFnIGlzIGFsc28gPGNvZGU+dHJ1ZTwvY29kZT4gd2hlbiB0aGUgc3RhbmRhbG9uZSAoZnVsbHNjcmVlbikgbW9kZSBvciB3ZWJ2aWV3IGlzIHVzZWQgb24gaU9TIGRldmljZXMuXHJcbiAqIFBsZWFzZSBhbHNvIG5vdGUgdGhlIGZsYWdzIHtAbGluayBEZXZpY2UuYnJvd3Nlci5mdWxsc2NyZWVufSBhbmQge0BsaW5rIERldmljZS5icm93c2VyLndlYnZpZXd9LlxyXG4gKlxyXG4gKiBAbmFtZSBEZXZpY2UuYnJvd3Nlci5zYWZhcmlcclxuICogQHR5cGUgYm9vbGVhblxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBJZiB0aGlzIGZsYWcgaXMgc2V0IHRvIDxjb2RlPnRydWU8L2NvZGU+LCBhIGJyb3dzZXIgZmVhdHVyaW5nIGEgV2Via2l0IGVuZ2luZSBpcyB1c2VkLlxyXG4gKlxyXG4gKiA8Yj5Ob3RlOjwvYj5cclxuICogVGhpcyBmbGFnIGlzIGFsc28gPGNvZGU+dHJ1ZTwvY29kZT4gd2hlbiB0aGUgdXNlZCBicm93c2VyIHdhcyBiYXNlZCBvbiB0aGUgV2Via2l0IGVuZ2luZSwgYnV0XHJcbiAqIHVzZXMgYW5vdGhlciByZW5kZXJpbmcgZW5naW5lIGluIHRoZSBtZWFudGltZS4gRm9yIGV4YW1wbGUgdGhlIENocm9tZSBicm93c2VyIHN0YXJ0ZWQgZnJvbSB2ZXJzaW9uIDI4IGFuZCBhYm92ZVxyXG4gKiB1c2VzIHRoZSBCbGluayByZW5kZXJpbmcgZW5naW5lLlxyXG4gKlxyXG4gKiBAbmFtZSBEZXZpY2UuYnJvd3Nlci53ZWJraXRcclxuICogQHR5cGUgYm9vbGVhblxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBJZiB0aGlzIGZsYWcgaXMgc2V0IHRvIDxjb2RlPnRydWU8L2NvZGU+LCB0aGUgU2FmYXJpIGJyb3dzZXIgcnVucyBpbiBzdGFuZGFsb25lIGZ1bGxzY3JlZW4gbW9kZSBvbiBpT1MuXHJcbiAqXHJcbiAqIDxiPk5vdGU6PC9iPiBUaGlzIGZsYWcgaXMgb25seSBhdmFpbGFibGUgaWYgdGhlIFNhZmFyaSBicm93c2VyIHdhcyBkZXRlY3RlZC4gRnVydGhlcm1vcmUsIGlmIHRoaXMgbW9kZSBpcyBkZXRlY3RlZCxcclxuICogdGVjaG5pY2FsbHkgbm90IGEgc3RhbmRhcmQgU2FmYXJpIGlzIHVzZWQuIFRoZXJlIG1pZ2h0IGJlIHNsaWdodCBkaWZmZXJlbmNlcyBpbiBiZWhhdmlvciBhbmQgZGV0ZWN0aW9uLCBlLmcuXHJcbiAqIHRoZSBhdmFpbGFiaWxpdHkgb2Yge0BsaW5rIERldmljZS5icm93c2VyLnZlcnNpb259LlxyXG4gKlxyXG4gKiBAbmFtZSBEZXZpY2UuYnJvd3Nlci5mdWxsc2NyZWVuXHJcbiAqIEB0eXBlIGJvb2xlYW5cclxuICovXHJcblxyXG4vKipcclxuICogSWYgdGhpcyBmbGFnIGlzIHNldCB0byA8Y29kZT50cnVlPC9jb2RlPiwgdGhlIFNhZmFyaSBicm93c2VyIHJ1bnMgaW4gd2VidmlldyBtb2RlIG9uIGlPUy5cclxuICpcclxuICogPGI+Tm90ZTo8L2I+IFRoaXMgZmxhZyBpcyBvbmx5IGF2YWlsYWJsZSBpZiB0aGUgU2FmYXJpIGJyb3dzZXIgd2FzIGRldGVjdGVkLiBGdXJ0aGVybW9yZSwgaWYgdGhpcyBtb2RlIGlzIGRldGVjdGVkLFxyXG4gKiB0ZWNobmljYWxseSBub3QgYSBzdGFuZGFyZCBTYWZhcmkgaXMgdXNlZC4gVGhlcmUgbWlnaHQgYmUgc2xpZ2h0IGRpZmZlcmVuY2VzIGluIGJlaGF2aW9yIGFuZCBkZXRlY3Rpb24sIGUuZy5cclxuICogdGhlIGF2YWlsYWJpbGl0eSBvZiB7QGxpbmsgRGV2aWNlLmJyb3dzZXIudmVyc2lvbn0uXHJcbiAqXHJcbiAqIEBuYW1lIERldmljZS5icm93c2VyLndlYnZpZXdcclxuICogQHR5cGUgYm9vbGVhblxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBJZiB0aGlzIGZsYWcgaXMgc2V0IHRvIDxjb2RlPnRydWU8L2NvZGU+LCB0aGUgUGhhbnRvbSBKUyBicm93c2VyIGlzIHVzZWQuXHJcbiAqIEBuYW1lIERldmljZS5icm93c2VyLnBoYW50b21KU1xyXG4gKiBAdHlwZSBib29sZWFuXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIFRoZSB2ZXJzaW9uIG9mIHRoZSB1c2VkIFdlYmtpdCBlbmdpbmUsIGlmIGF2YWlsYWJsZS5cclxuICogQG5hbWUgRGV2aWNlLmJyb3dzZXIud2Via2l0VmVyc2lvblxyXG4gKiBAdHlwZSBTdHJpbmdcclxuICovXHJcblxyXG4vKipcclxuICogSWYgdGhpcyBmbGFnIGlzIHNldCB0byA8Y29kZT50cnVlPC9jb2RlPiwgYSBicm93c2VyIGZlYXR1cmluZyBhIE1vemlsbGEgZW5naW5lIGlzIHVzZWQuXHJcbiAqIEBuYW1lIERldmljZS5icm93c2VyLm1vemlsbGFcclxuICogQHR5cGUgYm9vbGVhblxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBJbnRlcm5ldCBFeHBsb3JlciBicm93c2VyIG5hbWUuXHJcbiAqIEBuYW1lIERldmljZS5icm93c2VyLkJST1dTRVIuSU5URVJORVRfRVhQTE9SRVJcclxuICovXHJcblxyXG4vKipcclxuICogRWRnZSBicm93c2VyIG5hbWUuXHJcbiAqIEBuYW1lIERldmljZS5icm93c2VyLkJST1dTRVIuRURHRVxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBGaXJlZm94IGJyb3dzZXIgbmFtZS5cclxuICogQG5hbWUgRGV2aWNlLmJyb3dzZXIuQlJPV1NFUi5GSVJFRk9YXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIENocm9tZSBicm93c2VyIG5hbWUuXHJcbiAqIEBuYW1lIERldmljZS5icm93c2VyLkJST1dTRVIuQ0hST01FXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIFNhZmFyaSBicm93c2VyIG5hbWUuXHJcbiAqIEBuYW1lIERldmljZS5icm93c2VyLkJST1dTRVIuU0FGQVJJXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIEFuZHJvaWQgc3RvY2sgYnJvd3NlciBuYW1lLlxyXG4gKiBAbmFtZSBEZXZpY2UuYnJvd3Nlci5CUk9XU0VSLkFORFJPSURcclxuICovXHJcblxyXG5jb25zdCBCUk9XU0VSID0ge1xyXG4gICAgSU5URVJORVRfRVhQTE9SRVI6ICdpZScsXHJcbiAgICBFREdFOiAnZWQnLFxyXG4gICAgRklSRUZPWDogJ2ZmJyxcclxuICAgIENIUk9NRTogJ2NyJyxcclxuICAgIFNBRkFSSTogJ3NmJyxcclxuICAgIEFORFJPSUQ6ICdhbidcclxufTtcclxuXHJcbi8qICFcclxuICogVGFrZW4gZnJvbSBqUXVlcnkgSmF2YVNjcmlwdCBMaWJyYXJ5IHYxLjcuMVxyXG4gKiBodHRwOi8vanF1ZXJ5LmNvbS9cclxuICpcclxuICogQ29weXJpZ2h0IDIwMTEsIEpvaG4gUmVzaWdcclxuICogRHVhbCBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIG9yIEdQTCBWZXJzaW9uIDIgbGljZW5zZXMuXHJcbiAqIGh0dHA6Ly9qcXVlcnkub3JnL2xpY2Vuc2VcclxuICpcclxuICogSW5jbHVkZXMgU2l6emxlLmpzXHJcbiAqIGh0dHA6Ly9zaXp6bGVqcy5jb20vXHJcbiAqIENvcHlyaWdodCAyMDExLCBUaGUgRG9qbyBGb3VuZGF0aW9uXHJcbiAqIFJlbGVhc2VkIHVuZGVyIHRoZSBNSVQsIEJTRCwgYW5kIEdQTCBMaWNlbnNlcy5cclxuICpcclxuICogRGF0ZTogTW9uIE5vdiAyMSAyMToxMTowMyAyMDExIC0wNTAwXHJcbiAqL1xyXG5jb25zdCBfY2FsY0Jyb3dzZXIgPSAoKSA9PiB7XHJcbiAgICBjb25zdCBzVXNlckFnZW50ID0gbmF2aWdhdG9yLnVzZXJBZ2VudC50b0xvd2VyQ2FzZSgpO1xyXG5cclxuICAgIGNvbnN0IHJ3ZWJraXQgPSAvKHdlYmtpdClbIC9dKFtcXHcuXSspLztcclxuICAgIGNvbnN0IHJtc2llID0gLyhtc2llKSAoW1xcdy5dKykvO1xyXG4gICAgY29uc3Qgcm1zaWUxMSA9IC8odHJpZGVudClcXC9bXFx3Ll0rOy4qcnY6KFtcXHcuXSspLztcclxuICAgIGNvbnN0IHJlZGdlID0gLyhlZGdlKVsgL10oW1xcdy5dKykvO1xyXG4gICAgY29uc3Qgcm1vemlsbGEgPSAvKG1vemlsbGEpKD86Lio/IHJ2OihbXFx3Ll0rKSk/LztcclxuXHJcbiAgICAvLyBXaW5QaG9uZSBJRTExIGFuZCBNUyBFZGdlIHVzZXJBZ2VudHMgY29udGFpbiBcIldlYktpdFwiIGFuZCBcIk1vemlsbGFcIiBhbmQgdGhlcmVmb3JlIG11c3QgYmUgY2hlY2tlZCBmaXJzdFxyXG4gICAgY29uc3QgYnJvd3Nlck1hdGNoID1cclxuICAgICAgICByZWRnZS5leGVjKHNVc2VyQWdlbnQpIHx8XHJcbiAgICAgICAgcm1zaWUxMS5leGVjKHNVc2VyQWdlbnQpIHx8XHJcbiAgICAgICAgcndlYmtpdC5leGVjKHNVc2VyQWdlbnQpIHx8XHJcbiAgICAgICAgcm1zaWUuZXhlYyhzVXNlckFnZW50KSB8fFxyXG4gICAgICAgIChzVXNlckFnZW50LmluZGV4T2YoJ2NvbXBhdGlibGUnKSA8IDAgJiYgcm1vemlsbGEuZXhlYyhzVXNlckFnZW50KSkgfHxcclxuICAgICAgICBbXTtcclxuXHJcbiAgICBjb25zdCBvUmVzID0ge1xyXG4gICAgICAgIGJyb3dzZXI6IGJyb3dzZXJNYXRjaFsxXSB8fCAnJyxcclxuICAgICAgICB2ZXJzaW9uOiBicm93c2VyTWF0Y2hbMl0gfHwgJzAnXHJcbiAgICB9O1xyXG4gICAgb1Jlc1tvUmVzLmJyb3dzZXJdID0gdHJ1ZTtcclxuICAgIHJldHVybiBvUmVzO1xyXG59O1xyXG5cclxuY29uc3QgX2dldEJyb3dzZXIgPSAoKSA9PiB7XHJcbiAgICBjb25zdCBvQnJvd3NlcjogeyBba2V5OiBzdHJpbmddOiBhbnkgfSA9IF9jYWxjQnJvd3NlcigpO1xyXG4gICAgY29uc3Qgc1VzZXJBZ2VudCA9IG5hdmlnYXRvci51c2VyQWdlbnQ7XHJcbiAgICBjb25zdCBvTmF2aWdhdG9yOiB7IFtrZXk6IHN0cmluZ106IGFueSB9ID0gd2luZG93Lm5hdmlnYXRvcjtcclxuXHJcbiAgICAvLyBqUXVlcnkgY2hlY2tzIGZvciB1c2VyIGFnZW50IHN0cmluZ3MuIFdlIGRpZmZlcmVudGlhdGUgYmV0d2VlbiBicm93c2Vyc1xyXG4gICAgbGV0IG9FeHBNb2JpbGU7XHJcbiAgICBsZXQgb1Jlc3VsdDtcclxuICAgIGxldCBmVmVyc2lvbjtcclxuXHJcbiAgICAvLyBNb3ppbGxhXHJcbiAgICBpZiAob0Jyb3dzZXIubW96aWxsYSkge1xyXG4gICAgICAgIG9FeHBNb2JpbGUgPSAvTW9iaWxlLztcclxuICAgICAgICBpZiAoc1VzZXJBZ2VudC5tYXRjaCgvRmlyZWZveFxcLyhcXGQrXFwuXFxkKykvKSkge1xyXG4gICAgICAgICAgICBmVmVyc2lvbiA9IHBhcnNlRmxvYXQoUmVnRXhwLiQxKTtcclxuICAgICAgICAgICAgb1Jlc3VsdCA9IHtcclxuICAgICAgICAgICAgICAgIG5hbWU6IEJST1dTRVIuRklSRUZPWCxcclxuICAgICAgICAgICAgICAgIHZlcnNpb25TdHI6IGAke2ZWZXJzaW9ufWAsXHJcbiAgICAgICAgICAgICAgICB2ZXJzaW9uOiBmVmVyc2lvbixcclxuICAgICAgICAgICAgICAgIG1vemlsbGE6IHRydWUsXHJcbiAgICAgICAgICAgICAgICBtb2JpbGU6IG9FeHBNb2JpbGUudGVzdChzVXNlckFnZW50KVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIC8vIHVua25vd24gbW96aWxsYSBicm93c2VyXHJcbiAgICAgICAgICAgIG9SZXN1bHQgPSB7XHJcbiAgICAgICAgICAgICAgICBtb2JpbGU6IG9FeHBNb2JpbGUudGVzdChzVXNlckFnZW50KSxcclxuICAgICAgICAgICAgICAgIG1vemlsbGE6IHRydWUsXHJcbiAgICAgICAgICAgICAgICB2ZXJzaW9uOiAtMVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuICAgIH0gZWxzZSBpZiAob0Jyb3dzZXIud2Via2l0KSB7XHJcbiAgICAgICAgLy8gd2Via2l0IHZlcnNpb24gaXMgbmVlZGVkIGZvciBjYWxjdWxhdGlvbiBpZiB0aGUgbW9iaWxlIGFuZHJvaWQgZGV2aWNlIGlzIGEgdGFibGV0IChjYWxjdWxhdGlvbiBvZiBvdGhlciBtb2JpbGUgZGV2aWNlcyB3b3JrIHdpdGhvdXQpXHJcbiAgICAgICAgY29uc3QgcmVnRXhwV2Via2l0VmVyc2lvbiA9IHNVc2VyQWdlbnQudG9Mb3dlckNhc2UoKS5tYXRjaCgvd2Via2l0Wy9dKFtcXGQuXSspLyk7XHJcbiAgICAgICAgbGV0IHdlYmtpdFZlcnNpb247XHJcbiAgICAgICAgaWYgKHJlZ0V4cFdlYmtpdFZlcnNpb24pIHtcclxuICAgICAgICAgICAgd2Via2l0VmVyc2lvbiA9IHJlZ0V4cFdlYmtpdFZlcnNpb25bMV07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIG9FeHBNb2JpbGUgPSAvTW9iaWxlLztcclxuICAgICAgICBjb25zdCBhQ2hyb21lTWF0Y2ggPSBzVXNlckFnZW50Lm1hdGNoKC8oQ2hyb21lfENyaU9TKVxcLyhcXGQrXFwuXFxkKykuXFxkKy8pO1xyXG4gICAgICAgIGNvbnN0IGFGaXJlZm94TWF0Y2ggPSBzVXNlckFnZW50Lm1hdGNoKC9GeGlPU1xcLyhcXGQrXFwuXFxkKykvKTtcclxuICAgICAgICBjb25zdCBhQW5kcm9pZE1hdGNoID0gc1VzZXJBZ2VudC5tYXRjaCgvQW5kcm9pZCAuKyBWZXJzaW9uXFwvKFxcZCtcXC5cXGQrKS8pO1xyXG5cclxuICAgICAgICBpZiAoYUNocm9tZU1hdGNoIHx8IGFGaXJlZm94TWF0Y2ggfHwgYUFuZHJvaWRNYXRjaCkge1xyXG4gICAgICAgICAgICBsZXQgc05hbWU7XHJcbiAgICAgICAgICAgIGxldCBzVmVyc2lvbjtcclxuICAgICAgICAgICAgbGV0IGJNb2JpbGU7XHJcblxyXG4gICAgICAgICAgICBpZiAoYUNocm9tZU1hdGNoKSB7XHJcbiAgICAgICAgICAgICAgICBzTmFtZSA9IEJST1dTRVIuQ0hST01FO1xyXG4gICAgICAgICAgICAgICAgYk1vYmlsZSA9IG9FeHBNb2JpbGUudGVzdChzVXNlckFnZW50KTtcclxuICAgICAgICAgICAgICAgIHNWZXJzaW9uID0gcGFyc2VGbG9hdChhQ2hyb21lTWF0Y2hbMl0pO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGFGaXJlZm94TWF0Y2gpIHtcclxuICAgICAgICAgICAgICAgIHNOYW1lID0gQlJPV1NFUi5GSVJFRk9YO1xyXG4gICAgICAgICAgICAgICAgYk1vYmlsZSA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICBzVmVyc2lvbiA9IHBhcnNlRmxvYXQoYUZpcmVmb3hNYXRjaFsxXSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoYUFuZHJvaWRNYXRjaCkge1xyXG4gICAgICAgICAgICAgICAgc05hbWUgPSBCUk9XU0VSLkFORFJPSUQ7XHJcbiAgICAgICAgICAgICAgICBiTW9iaWxlID0gb0V4cE1vYmlsZS50ZXN0KHNVc2VyQWdlbnQpO1xyXG4gICAgICAgICAgICAgICAgc1ZlcnNpb24gPSBwYXJzZUZsb2F0KGFBbmRyb2lkTWF0Y2hbMV0pO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBvUmVzdWx0ID0ge1xyXG4gICAgICAgICAgICAgICAgbmFtZTogc05hbWUsXHJcbiAgICAgICAgICAgICAgICBtb2JpbGU6IGJNb2JpbGUsXHJcbiAgICAgICAgICAgICAgICB2ZXJzaW9uU3RyOiBgJHtzVmVyc2lvbn1gLFxyXG4gICAgICAgICAgICAgICAgdmVyc2lvbjogc1ZlcnNpb24sXHJcbiAgICAgICAgICAgICAgICB3ZWJraXQ6IHRydWUsXHJcbiAgICAgICAgICAgICAgICB3ZWJraXRWZXJzaW9uXHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgLy8gU2FmYXJpIG1pZ2h0IGhhdmUgYW4gaXNzdWUgd2l0aCBzVXNlckFnZW50Lm1hdGNoKC4uLik7IHRodXMgY2hhbmdpbmdcclxuICAgICAgICAgICAgY29uc3Qgb0V4cCA9IC8oVmVyc2lvbnxQaGFudG9tSlMpXFwvKFxcZCtcXC5cXGQrKS4qU2FmYXJpLztcclxuICAgICAgICAgICAgY29uc3QgYlN0YW5kYWxvbmU6IGFueSA9IG9OYXZpZ2F0b3Iuc3RhbmRhbG9uZTtcclxuICAgICAgICAgICAgaWYgKG9FeHAudGVzdChzVXNlckFnZW50KSkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgYVBhcnRzOiBhbnkgPSBvRXhwLmV4ZWMoc1VzZXJBZ2VudCk7XHJcbiAgICAgICAgICAgICAgICBmVmVyc2lvbiA9IHBhcnNlRmxvYXQoYVBhcnRzWzJdKTtcclxuICAgICAgICAgICAgICAgIG9SZXN1bHQgPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogQlJPV1NFUi5TQUZBUkksXHJcbiAgICAgICAgICAgICAgICAgICAgdmVyc2lvblN0cjogYCR7ZlZlcnNpb259YCxcclxuICAgICAgICAgICAgICAgICAgICBmdWxsc2NyZWVuOiBmYWxzZSxcclxuICAgICAgICAgICAgICAgICAgICB3ZWJ2aWV3OiBmYWxzZSxcclxuICAgICAgICAgICAgICAgICAgICB2ZXJzaW9uOiBmVmVyc2lvbixcclxuICAgICAgICAgICAgICAgICAgICBtb2JpbGU6IG9FeHBNb2JpbGUudGVzdChzVXNlckFnZW50KSxcclxuICAgICAgICAgICAgICAgICAgICB3ZWJraXQ6IHRydWUsXHJcbiAgICAgICAgICAgICAgICAgICAgd2Via2l0VmVyc2lvbixcclxuICAgICAgICAgICAgICAgICAgICBwaGFudG9tSlM6IGFQYXJ0c1sxXSA9PT0gJ1BoYW50b21KUydcclxuICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoXHJcbiAgICAgICAgICAgICAgICAvaVBob25lfGlQYWR8aVBvZC8udGVzdChzVXNlckFnZW50KSAmJlxyXG4gICAgICAgICAgICAgICAgIS9DcmlPUy8udGVzdChzVXNlckFnZW50KSAmJlxyXG4gICAgICAgICAgICAgICAgIS9GeGlPUy8udGVzdChzVXNlckFnZW50KSAmJlxyXG4gICAgICAgICAgICAgICAgKGJTdGFuZGFsb25lID09PSB0cnVlIHx8IGJTdGFuZGFsb25lID09PSBmYWxzZSlcclxuICAgICAgICAgICAgKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBXZWJWaWV3IG9yIFN0YW5kYWxvbmUgbW9kZSBvbiBpT1NcclxuICAgICAgICAgICAgICAgIG9SZXN1bHQgPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogQlJPV1NFUi5TQUZBUkksXHJcbiAgICAgICAgICAgICAgICAgICAgdmVyc2lvbjogLTEsXHJcbiAgICAgICAgICAgICAgICAgICAgZnVsbHNjcmVlbjogYlN0YW5kYWxvbmUsXHJcbiAgICAgICAgICAgICAgICAgICAgd2VidmlldzogIWJTdGFuZGFsb25lLFxyXG4gICAgICAgICAgICAgICAgICAgIG1vYmlsZTogb0V4cE1vYmlsZS50ZXN0KHNVc2VyQWdlbnQpLFxyXG4gICAgICAgICAgICAgICAgICAgIHdlYmtpdDogdHJ1ZSxcclxuICAgICAgICAgICAgICAgICAgICB3ZWJraXRWZXJzaW9uXHJcbiAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgLy8gb3RoZXIgd2Via2l0IGJhc2VkIGJyb3dzZXJcclxuICAgICAgICAgICAgICAgIG9SZXN1bHQgPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbW9iaWxlOiBvRXhwTW9iaWxlLnRlc3Qoc1VzZXJBZ2VudCksXHJcbiAgICAgICAgICAgICAgICAgICAgd2Via2l0OiB0cnVlLFxyXG4gICAgICAgICAgICAgICAgICAgIHdlYmtpdFZlcnNpb24sXHJcbiAgICAgICAgICAgICAgICAgICAgdmVyc2lvbjogLTFcclxuICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9IGVsc2UgaWYgKG9Ccm93c2VyLm1zaWUgfHwgb0Jyb3dzZXIudHJpZGVudCkge1xyXG4gICAgICAgIGZWZXJzaW9uID0gcGFyc2VGbG9hdChvQnJvd3Nlci52ZXJzaW9uKTtcclxuXHJcbiAgICAgICAgb1Jlc3VsdCA9IHtcclxuICAgICAgICAgICAgbmFtZTogQlJPV1NFUi5JTlRFUk5FVF9FWFBMT1JFUixcclxuICAgICAgICAgICAgdmVyc2lvblN0cjogYCR7ZlZlcnNpb259YCxcclxuICAgICAgICAgICAgdmVyc2lvbjogZlZlcnNpb24sXHJcbiAgICAgICAgICAgIG1zaWU6IHRydWUsXHJcbiAgICAgICAgICAgIG1vYmlsZTogZmFsc2VcclxuICAgICAgICB9O1xyXG4gICAgfSBlbHNlIGlmIChvQnJvd3Nlci5lZGdlKSB7XHJcbiAgICAgICAgZlZlcnNpb24gPSBwYXJzZUZsb2F0KG9Ccm93c2VyLnZlcnNpb24pO1xyXG4gICAgICAgIG9SZXN1bHQgPSB7XHJcbiAgICAgICAgICAgIG5hbWU6IEJST1dTRVIuRURHRSxcclxuICAgICAgICAgICAgdmVyc2lvblN0cjogYCR7ZlZlcnNpb259YCxcclxuICAgICAgICAgICAgdmVyc2lvbjogZlZlcnNpb24sXHJcbiAgICAgICAgICAgIGVkZ2U6IHRydWVcclxuICAgICAgICB9O1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgICBvUmVzdWx0ID0ge1xyXG4gICAgICAgICAgICBuYW1lOiAnJyxcclxuICAgICAgICAgICAgdmVyc2lvblN0cjogJycsXHJcbiAgICAgICAgICAgIHZlcnNpb246IC0xLFxyXG4gICAgICAgICAgICBtb2JpbGU6IGZhbHNlXHJcbiAgICAgICAgfTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gb1Jlc3VsdDtcclxufTtcclxuXHJcbmNvbnN0IF9zZXRCcm93c2VyID0gKCkgPT4ge1xyXG4gICAgRGV2aWNlLmJyb3dzZXIgPSBfZ2V0QnJvd3NlcigpO1xyXG4gICAgRGV2aWNlLmJyb3dzZXIuQlJPV1NFUiA9IEJST1dTRVI7XHJcblxyXG4gICAgaWYgKERldmljZS5icm93c2VyLm5hbWUpIHtcclxuICAgICAgICBPYmplY3Qua2V5cyhCUk9XU0VSKS5mb3JFYWNoKChiKSA9PiB7XHJcbiAgICAgICAgICAgIGlmIChCUk9XU0VSW2JdID09PSBEZXZpY2UuYnJvd3Nlci5uYW1lKSB7XHJcbiAgICAgICAgICAgICAgICBEZXZpY2UuYnJvd3NlcltiLnRvTG93ZXJDYXNlKCldID0gdHJ1ZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG59O1xyXG5cclxuY29uc3QgZ2V0QnJvd3NlciA9ICgpID0+IHtcclxuICAgIGlmICghRGV2aWNlLmJyb3dzZXIpIHtcclxuICAgICAgICBfc2V0QnJvd3NlcigpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIERldmljZS5icm93c2VyO1xyXG59O1xyXG5cclxuY29uc3QgaXNJRSA9ICgpID0+IHtcclxuICAgIGlmICghRGV2aWNlLmJyb3dzZXIpIHtcclxuICAgICAgICBfc2V0QnJvd3NlcigpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuICEhRGV2aWNlLmJyb3dzZXIubXNpZTtcclxufTtcclxuXHJcbmNvbnN0IGlzRWRnZSA9ICgpID0+IHtcclxuICAgIGlmICghRGV2aWNlLmJyb3dzZXIpIHtcclxuICAgICAgICBfc2V0QnJvd3NlcigpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuICEhRGV2aWNlLmJyb3dzZXIuZWRnZTtcclxufTtcclxuXHJcbmNvbnN0IGlzQ2hyb21lID0gKCkgPT4ge1xyXG4gICAgaWYgKCFEZXZpY2UuYnJvd3Nlcikge1xyXG4gICAgICAgIF9zZXRCcm93c2VyKCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gISFEZXZpY2UuYnJvd3Nlci5jaHJvbWU7XHJcbn07XHJcblxyXG5jb25zdCBpc0ZGID0gKCkgPT4ge1xyXG4gICAgaWYgKCFEZXZpY2UuYnJvd3Nlcikge1xyXG4gICAgICAgIF9zZXRCcm93c2VyKCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gISFEZXZpY2UuYnJvd3Nlci5maXJlZm94O1xyXG59O1xyXG5cclxuY29uc3QgaXNTYWZhcmkgPSAoKSA9PiB7XHJcbiAgICBpZiAoIURldmljZS5icm93c2VyKSB7XHJcbiAgICAgICAgX3NldEJyb3dzZXIoKTtcclxuICAgIH1cclxuICAgIHJldHVybiAhIURldmljZS5icm93c2VyLnNhZmFyaTtcclxufTtcclxuXHJcbi8vICogKioqKioqKiBTdXBwb3J0IERldGVjdGlvbiAqKioqKioqKlxyXG5cclxuY29uc3QgX3NldFN1cHBvcnQgPSAoKSA9PiB7XHJcbiAgICBpZiAoRGV2aWNlLnN1cHBvcnQpIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCFEZXZpY2UuYnJvd3Nlcikge1xyXG4gICAgICAgIF9zZXRCcm93c2VyKCk7XHJcbiAgICB9XHJcblxyXG4gICAgRGV2aWNlLnN1cHBvcnQgPSB7fTtcclxuICAgIERldmljZS5zdXBwb3J0LnRvdWNoID0gISEoXHJcbiAgICAgICAgJ29udG91Y2hzdGFydCcgaW4gd2luZG93IHx8XHJcbiAgICAgICAgbmF2aWdhdG9yLm1heFRvdWNoUG9pbnRzID4gMCB8fFxyXG4gICAgICAgICgod2luZG93IGFzIGFueSkuRG9jdW1lbnRUb3VjaCAmJiBkb2N1bWVudCBpbnN0YW5jZW9mICh3aW5kb3cgYXMgYW55KS5Eb2N1bWVudFRvdWNoKVxyXG4gICAgKTtcclxufTtcclxuXHJcbmNvbnN0IHN1cHBvcnRUb3VjaCA9ICgpID0+IHtcclxuICAgIGlmICghRGV2aWNlLnN1cHBvcnQpIHtcclxuICAgICAgICBfc2V0U3VwcG9ydCgpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiAhIURldmljZS5zdXBwb3J0LnRvdWNoO1xyXG59O1xyXG5cclxuLy8gKiAqKioqKioqIFN5c3RlbSBEZXRlY3Rpb24gKioqKioqKipcclxuXHJcbi8qKlxyXG4gKiBQcm92aWRlcyBhIGJhc2ljIGNhdGVnb3JpemF0aW9uIG9mIHRoZSB1c2VkIGRldmljZSBiYXNlZCBvbiB2YXJpb3VzIGluZGljYXRvcnMuXHJcbiAqXHJcbiAqIDxiPk5vdGU6PC9iPiBEZXBlbmRpbmcgb24gdGhlIGNhcGFiaWxpdGllcyBvZiB0aGUgZGV2aWNlIGl0IGlzIGFsc28gcG9zc2libGUgdGhhdCBtdWx0aXBsZSBmbGFncyBhcmUgc2V0IHRvIDxjb2RlPnRydWU8L2NvZGU+LlxyXG4gKlxyXG4gKiBAbmFtZXNwYWNlXHJcbiAqIEBuYW1lIERldmljZS5zeXN0ZW1cclxuICovXHJcblxyXG4vKipcclxuICogSWYgdGhpcyBmbGFnIGlzIHNldCB0byA8Y29kZT50cnVlPC9jb2RlPiwgdGhlIGRldmljZSBpcyByZWNvZ25pemVkIGFzIGEgcGhvbmUuXHJcbiAqXHJcbiAqIEBuYW1lIERldmljZS5zeXN0ZW0ucGhvbmVcclxuICogQHR5cGUgYm9vbGVhblxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBAbmFtZSBEZXZpY2Uuc3lzdGVtLlNZU1RFTVRZUEVcclxuICogRW51bWVyYXRpb24gY29udGFpbmluZyB0aGUgbmFtZXMgb2Yga25vd24gdHlwZXMgb2YgdGhlIGRldmljZXMuXHJcbiAqL1xyXG5cclxuY29uc3QgU1lTVEVNVFlQRSA9IHtcclxuICAgIFRBQkxFVDogJ3RhYmxldCcsXHJcbiAgICBQSE9ORTogJ3Bob25lJyxcclxuICAgIERFU0tUT1A6ICdkZXNrdG9wJyxcclxuICAgIENPTUJJOiAnY29tYmknXHJcbn07XHJcblxyXG5jb25zdCBfaXNUYWJsZXQgPSAoKSA9PiB7XHJcbiAgICBjb25zdCBzVXNlckFnZW50ID0gbmF2aWdhdG9yLnVzZXJBZ2VudDtcclxuICAgIGlmIChEZXZpY2Uub3MubmFtZSA9PT0gRGV2aWNlLm9zLk9TLklPUykge1xyXG4gICAgICAgIHJldHVybiAvaXBhZC9pLnRlc3Qoc1VzZXJBZ2VudCk7XHJcbiAgICB9XHJcbiAgICAvLyBpbiByZWFsIG1vYmlsZSBkZXZpY2VcclxuICAgIGlmIChzdXBwb3J0VG91Y2goKSkge1xyXG4gICAgICAgIGlmIChEZXZpY2Uub3Mud2luZG93cyAmJiBEZXZpY2Uub3MudmVyc2lvbiA+PSA4KSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKERldmljZS5icm93c2VyLmNocm9tZSAmJiBEZXZpY2Uub3MuYW5kcm9pZCAmJiBEZXZpY2Uub3MudmVyc2lvbiA+PSA0LjQpIHtcclxuICAgICAgICAgICAgcmV0dXJuICEvTW9iaWxlIFNhZmFyaVxcL1suMC05XSsvLnRlc3Qoc1VzZXJBZ2VudCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGxldCBkZW5zaXR5RmFjdG9yID0gd2luZG93LmRldmljZVBpeGVsUmF0aW8gPyB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyA6IDE7IC8vIG1heSBiZSB1bmRlZmluZWQgaW4gV2luZG93cyBQaG9uZSBkZXZpY2VzXHJcbiAgICAgICAgLy8gT24gQW5kcm9pZCBzb21ldGltZXMgd2luZG93LnNjcmVlbi53aWR0aCByZXR1cm5zIHRoZSBsb2dpY2FsIENTUyBwaXhlbHMsIHNvbWV0aW1lcyB0aGUgcGh5c2ljYWwgZGV2aWNlIHBpeGVscztcclxuICAgICAgICAvLyBUZXN0cyBvbiBtdWx0aXBsZSBkZXZpY2VzIHN1Z2dlc3QgdGhpcyBkZXBlbmRzIG9uIHRoZSBXZWJraXQgdmVyc2lvbi5cclxuICAgICAgICAvLyBUaGUgV2Via2l0IHBhdGNoIHdoaWNoIGNoYW5nZWQgdGhlIGJlaGF2aW9yIHdhcyBkb25lIGhlcmU6IGh0dHBzOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0xMDY0NjBcclxuICAgICAgICAvLyBDaHJvbWUgMjcgd2l0aCBXZWJraXQgNTM3LjM2IHJldHVybnMgdGhlIGxvZ2ljYWwgcGl4ZWxzLFxyXG4gICAgICAgIC8vIENocm9tZSAxOCB3aXRoIFdlYmtpdCA1MzUuMTkgcmV0dXJucyB0aGUgcGh5c2ljYWwgcGl4ZWxzLlxyXG4gICAgICAgIC8vIFRoZSBCbGFja0JlcnJ5IDEwIGJyb3dzZXIgd2l0aCBXZWJraXQgNTM3LjEwKyByZXR1cm5zIHRoZSBwaHlzaWNhbCBwaXhlbHMuXHJcbiAgICAgICAgLy8gU28gaXQgYXBwZWFycyBsaWtlIHNvbWV3aGVyZSBhYm92ZSBXZWJraXQgNTM3LjEwIHdlIGRvIG5vdCBodmUgdG8gZGl2aWRlIGJ5IHRoZSBkZXZpY2VQaXhlbFJhdGlvIGFueW1vcmUuXHJcbiAgICAgICAgaWYgKERldmljZS5vcy5hbmRyb2lkICYmIERldmljZS5icm93c2VyLndlYmtpdCAmJiBwYXJzZUZsb2F0KERldmljZS5icm93c2VyLndlYmtpdFZlcnNpb24pID4gNTM3LjEpIHtcclxuICAgICAgICAgICAgZGVuc2l0eUZhY3RvciA9IDE7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyB0aGlzIGlzIGhvdyBhbmRyb2lkIGRpc3Rpbmd1aXNoZXMgYmV0d2VlbiB0YWJsZXQgYW5kIHBob25lXHJcbiAgICAgICAgLy8gaHR0cDovL2FuZHJvaWQtZGV2ZWxvcGVycy5ibG9nc3BvdC5kZS8yMDExLzA3L25ldy10b29scy1mb3ItbWFuYWdpbmctc2NyZWVuLXNpemVzLmh0bWxcclxuICAgICAgICBjb25zdCBiVGFibGV0ID0gTWF0aC5taW4od2luZG93LnNjcmVlbi53aWR0aCAvIGRlbnNpdHlGYWN0b3IsIHdpbmRvdy5zY3JlZW4uaGVpZ2h0IC8gZGVuc2l0eUZhY3RvcikgPj0gNjAwO1xyXG5cclxuICAgICAgICAvLyBzcGVjaWFsIHdvcmthcm91bmQgZm9yIE5leHVzIDcgd2hlcmUgdGhlIHdpbmRvdy5zY3JlZW4ud2lkdGggaXMgNjAwcHggb3IgNjAxcHggaW4gcG9ydHJhaXQgbW9kZSAoPT4gdGFibGV0KVxyXG4gICAgICAgIC8vIGJ1dCB3aW5kb3cuc2NyZWVuLmhlaWdodCA1NTJweCBpbiBsYW5kc2NhcGUgbW9kZSAoPT4gcGhvbmUpLCBiZWNhdXNlIHRoZSBicm93c2VyIFVJIHRha2VzIHNvbWUgc3BhY2Ugb24gdG9wLlxyXG4gICAgICAgIC8vIFNvIHRoZSBkZXRlY3RlZCBkZXZpY2UgdHlwZSBkZXBlbmRzIG9uIHRoZSBvcmllbnRhdGlvbiA6LShcclxuICAgICAgICAvLyBhY3R1YWxseSB0aGlzIGlzIGEgQ2hyb21lIGJ1ZywgYXMgXCJ3aWR0aFwiL1wiaGVpZ2h0XCIgc2hvdWxkIHJldHVybiB0aGUgZW50aXJlIHNjcmVlbidzIGRpbWVuc2lvbnMgYW5kXHJcbiAgICAgICAgLy8gXCJhdmFpbFdpZHRoXCIvXCJhdmFpbEhlaWdodFwiIHNob3VsZCByZXR1cm4gdGhlIHNpemUgYXZhaWxhYmxlIGFmdGVyIHN1YnRyYWN0aW5nIHRoZSBicm93c2VyIFVJXHJcblxyXG4gICAgICAgIC8qXHJcbiAgICAgICAgICAgICAgICAgaWYgKGlzTGFuZHNjYXBlKCkgJiZcclxuICAgICAgICAgICAgICAgICAgICAgKHdpbmRvdy5zY3JlZW4uaGVpZ2h0ID09PSA1NTIgfHwgd2luZG93LnNjcmVlbi5oZWlnaHQgPT09IDU1MykgLy8gb2xkL25ldyBOZXh1cyA3XHJcbiAgICAgICAgICAgICAgICAgICAgICYmXHJcbiAgICAgICAgICAgICAgICAgICAgICgvTmV4dXMgNy9pLnRlc3Qoc1VzZXJBZ2VudCkpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgIGJUYWJsZXQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAqL1xyXG5cclxuICAgICAgICByZXR1cm4gYlRhYmxldDtcclxuICAgIH1cclxuICAgIC8vIFRoaXMgc2ltcGxlIGFuZHJvaWQgcGhvbmUgZGV0ZWN0aW9uIGNhbiBiZSB1c2VkIGhlcmUgYmVjYXVzZSB0aGlzIGlzIHRoZSBtb2JpbGUgZW11bGF0aW9uIG1vZGUgaW4gZGVza3RvcCBicm93c2VyXHJcbiAgICBjb25zdCBiQW5kcm9pZFBob25lID0gLyg/PWFuZHJvaWQpKD89Liptb2JpbGUpL2kudGVzdChzVXNlckFnZW50KTtcclxuICAgIC8vIGluIGRlc2t0b3AgYnJvd3NlciwgaXQncyBkZXRlY3RlZCBhcyB0YWJsZXQgd2hlblxyXG4gICAgLy8gMS4gV2luZG93cyA4IGRldmljZSB3aXRoIGEgdG91Y2ggc2NyZWVuIHdoZXJlIFwiVG91Y2hcIiBpcyBjb250YWluZWQgaW4gdGhlIHVzZXJBZ2VudFxyXG4gICAgLy8gMi4gQW5kcm9pZCBlbXVsYXRpb24gYW5kIGl0J3Mgbm90IGFuIEFuZHJvaWQgcGhvbmVcclxuICAgIHJldHVybiAoRGV2aWNlLmJyb3dzZXIubXNpZSAmJiBzVXNlckFnZW50LmluZGV4T2YoJ1RvdWNoJykgIT09IC0xKSB8fCAoRGV2aWNlLm9zLmFuZHJvaWQgJiYgIWJBbmRyb2lkUGhvbmUpO1xyXG59O1xyXG5cclxuY29uc3QgX2dldFN5c3RlbSA9ICgpID0+IHtcclxuICAgIGNvbnN0IGJUYWJsZXREZXRlY3RlZCA9IF9pc1RhYmxldCgpO1xyXG4gICAgY29uc3QgaXNXaW44VXB3YXJkcyA9IERldmljZS5vcy53aW5kb3dzICYmIERldmljZS5vcy52ZXJzaW9uID49IDg7XHJcblxyXG4gICAgY29uc3Qgb1N5c3RlbTogeyBba2V5OiBzdHJpbmddOiBhbnkgfSA9IHt9O1xyXG4gICAgb1N5c3RlbS50YWJsZXQgPSAhISgoRGV2aWNlLnN1cHBvcnQudG91Y2ggfHwgaXNXaW44VXB3YXJkcykgJiYgYlRhYmxldERldGVjdGVkKTtcclxuICAgIG9TeXN0ZW0ucGhvbmUgPSAhISgoRGV2aWNlLm9zLndpbmRvd3NfcGhvbmUgfHwgRGV2aWNlLnN1cHBvcnQudG91Y2gpICYmICFiVGFibGV0RGV0ZWN0ZWQpO1xyXG4gICAgb1N5c3RlbS5kZXNrdG9wID0gISEoKCFvU3lzdGVtLnRhYmxldCAmJiAhb1N5c3RlbS5waG9uZSkgfHwgaXNXaW44VXB3YXJkcyk7XHJcbiAgICBvU3lzdGVtLmNvbWJpID0gb1N5c3RlbS5kZXNrdG9wICYmIG9TeXN0ZW0udGFibGV0O1xyXG4gICAgb1N5c3RlbS5TWVNURU1UWVBFID0gU1lTVEVNVFlQRTtcclxuXHJcbiAgICByZXR1cm4gb1N5c3RlbTtcclxufTtcclxuXHJcbmNvbnN0IF9zZXRTeXN0ZW0gPSAoKSA9PiB7XHJcbiAgICBfc2V0U3VwcG9ydCgpO1xyXG4gICAgX3NldE9TKCk7XHJcblxyXG4gICAgRGV2aWNlLnN5c3RlbSA9IHt9O1xyXG4gICAgRGV2aWNlLnN5c3RlbSA9IF9nZXRTeXN0ZW0oKTtcclxuICAgIGlmIChEZXZpY2Uuc3lzdGVtLnRhYmxldCB8fCBEZXZpY2Uuc3lzdGVtLnBob25lKSB7XHJcbiAgICAgICAgRGV2aWNlLmJyb3dzZXIubW9iaWxlID0gdHJ1ZTtcclxuICAgIH1cclxufTtcclxuXHJcbmNvbnN0IGdldFN5c3RlbSA9ICgpID0+IHtcclxuICAgIGlmICghRGV2aWNlLnN5c3RlbSkge1xyXG4gICAgICAgIF9zZXRTeXN0ZW0oKTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gRGV2aWNlLnN5c3RlbTtcclxufTtcclxuXHJcbmNvbnN0IGlzRGVza3RvcCA9ICgpID0+IHtcclxuICAgIGlmICghRGV2aWNlLnN5c3RlbSkge1xyXG4gICAgICAgIF9zZXRTeXN0ZW0oKTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gRGV2aWNlLnN5c3RlbS5kZXNrdG9wO1xyXG59O1xyXG5cclxuY29uc3QgaXNUYWJsZXQgPSAoKSA9PiB7XHJcbiAgICBpZiAoIURldmljZS5zeXN0ZW0pIHtcclxuICAgICAgICBfc2V0U3lzdGVtKCk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIERldmljZS5zeXN0ZW0udGFibGV0O1xyXG59O1xyXG5cclxuY29uc3QgaXNQaG9uZSA9ICgpID0+IHtcclxuICAgIGlmICghRGV2aWNlLnN5c3RlbSkge1xyXG4gICAgICAgIF9zZXRTeXN0ZW0oKTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gRGV2aWNlLnN5c3RlbS5waG9uZTtcclxufTtcclxuXHJcbmNvbnN0IGlzTW9iaWxlID0gKCkgPT4ge1xyXG4gICAgaWYgKCFEZXZpY2Uuc3lzdGVtKSB7XHJcbiAgICAgICAgX3NldFN5c3RlbSgpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBEZXZpY2UuYnJvd3Nlci5tb2JpbGU7XHJcbn07XHJcblxyXG5leHBvcnQge1xyXG4gICAgaXNJRSxcclxuICAgIGlzRWRnZSxcclxuICAgIGlzQ2hyb21lLFxyXG4gICAgaXNGRixcclxuICAgIGlzU2FmYXJpLFxyXG4gICAgaXNNb2JpbGUsXHJcbiAgICBpc0Rlc2t0b3AsXHJcbiAgICBpc1RhYmxldCxcclxuICAgIGlzUGhvbmUsXHJcbiAgICBpc0FuZHJvaWQsXHJcbiAgICBnZXRPUyxcclxuICAgIGdldFN5c3RlbSxcclxuICAgIGdldEJyb3dzZXIsXHJcbiAgICBzdXBwb3J0VG91Y2hcclxufTtcclxuIl19
|