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.
Files changed (270) hide show
  1. package/README.md +25 -0
  2. package/esm2020/barsa-novin-ray-core.mjs +5 -0
  3. package/esm2020/lib/abstract-classes/application-base.mjs +24 -0
  4. package/esm2020/lib/abstract-classes/barsa-api.mjs +40 -0
  5. package/esm2020/lib/abstract-classes/field-base.mjs +167 -0
  6. package/esm2020/lib/abstract-classes/files-validation-helper.mjs +71 -0
  7. package/esm2020/lib/abstract-classes/form-base.mjs +101 -0
  8. package/esm2020/lib/abstract-classes/form-props.base.mjs +79 -0
  9. package/esm2020/lib/abstract-classes/form-toolbar-base.mjs +45 -0
  10. package/esm2020/lib/abstract-classes/index.mjs +21 -0
  11. package/esm2020/lib/abstract-classes/layout-item-base.mjs +33 -0
  12. package/esm2020/lib/abstract-classes/layout-panel-base.mjs +80 -0
  13. package/esm2020/lib/abstract-classes/models.mjs +172 -0
  14. package/esm2020/lib/abstract-classes/module-with-dynamic-components.mjs +2 -0
  15. package/esm2020/lib/abstract-classes/number-base.mjs +117 -0
  16. package/esm2020/lib/abstract-classes/page-base.mjs +97 -0
  17. package/esm2020/lib/abstract-classes/report-base.mjs +231 -0
  18. package/esm2020/lib/abstract-classes/report-item-base.mjs +53 -0
  19. package/esm2020/lib/abstract-classes/report-view-base.component.mjs +262 -0
  20. package/esm2020/lib/abstract-classes/system-base.mjs +24 -0
  21. package/esm2020/lib/auth-guard.mjs +37 -0
  22. package/esm2020/lib/barsa-novin-ray-core-routing.module.mjs +18 -0
  23. package/esm2020/lib/barsa-novin-ray-core.module.mjs +271 -0
  24. package/esm2020/lib/base-ulv-setting.component.mjs +37 -0
  25. package/esm2020/lib/base.component.mjs +59 -0
  26. package/esm2020/lib/base.module.mjs +28 -0
  27. package/esm2020/lib/constants.mjs +441 -0
  28. package/esm2020/lib/container.component.mjs +76 -0
  29. package/esm2020/lib/custom-route-reuse-strategy.mjs +32 -0
  30. package/esm2020/lib/date-services/date-hijri.service.mjs +127 -0
  31. package/esm2020/lib/date-services/date-info.mjs +2 -0
  32. package/esm2020/lib/date-services/date-miladi.service.mjs +124 -0
  33. package/esm2020/lib/date-services/date-shamsi.service.mjs +129 -0
  34. package/esm2020/lib/date-services/date.service.mjs +139 -0
  35. package/esm2020/lib/date-services/index.mjs +6 -0
  36. package/esm2020/lib/device.mjs +663 -0
  37. package/esm2020/lib/directives/anchor-scroll.directive.mjs +24 -0
  38. package/esm2020/lib/directives/attr-rtl.directive.mjs +35 -0
  39. package/esm2020/lib/directives/base.directive.mjs +51 -0
  40. package/esm2020/lib/directives/column-resizer.directive.mjs +39 -0
  41. package/esm2020/lib/directives/dynamic-command.directive.mjs +43 -0
  42. package/esm2020/lib/directives/ellipsify.directive.mjs +72 -0
  43. package/esm2020/lib/directives/field-binding.directive.mjs +17 -0
  44. package/esm2020/lib/directives/img-lazy.directive.mjs +75 -0
  45. package/esm2020/lib/directives/index.mjs +19 -0
  46. package/esm2020/lib/directives/intersection-observer.directive.mjs +49 -0
  47. package/esm2020/lib/directives/items-renderer.directive.mjs +59 -0
  48. package/esm2020/lib/directives/numbers-only-input.directive.mjs +26 -0
  49. package/esm2020/lib/directives/placeHolder.directive.mjs +15 -0
  50. package/esm2020/lib/directives/render-ulv-paging.directive.mjs +58 -0
  51. package/esm2020/lib/directives/render-ulv-viewer.directive.mjs +60 -0
  52. package/esm2020/lib/directives/table-resizer.directive.mjs +235 -0
  53. package/esm2020/lib/directives/ulv-command.directive.mjs +41 -0
  54. package/esm2020/lib/directives/until-inview.directive.mjs +51 -0
  55. package/esm2020/lib/dynamic-component/base-dynamic.component.mjs +89 -0
  56. package/esm2020/lib/dynamic-component/base-form-toolbaritem-props.mjs +50 -0
  57. package/esm2020/lib/dynamic-component/base-item-content-props.mjs +70 -0
  58. package/esm2020/lib/dynamic-component/base-view-content-props.mjs +26 -0
  59. package/esm2020/lib/dynamic-component/base-view-item-props.mjs +374 -0
  60. package/esm2020/lib/dynamic-component/base-view-props.mjs +127 -0
  61. package/esm2020/lib/dynamic-component/dynamic-form-toolbar-item.component.mjs +36 -0
  62. package/esm2020/lib/dynamic-component/dynamic-form.component.mjs +62 -0
  63. package/esm2020/lib/dynamic-component/dynamic-item.component.mjs +60 -0
  64. package/esm2020/lib/dynamic-component/index.mjs +10 -0
  65. package/esm2020/lib/empty-page-with-router-and-router-outlet/empty-page-with-router-and-router-outlet.component.mjs +16 -0
  66. package/esm2020/lib/field-ui/field-ui.component.mjs +116 -0
  67. package/esm2020/lib/form/form.component.mjs +151 -0
  68. package/esm2020/lib/form-new/form-new.component.mjs +30 -0
  69. package/esm2020/lib/from-intersection-observer.mjs +53 -0
  70. package/esm2020/lib/global-error-handler.mjs +26 -0
  71. package/esm2020/lib/modal-root.component.mjs +31 -0
  72. package/esm2020/lib/not-found/not-found.component.mjs +16 -0
  73. package/esm2020/lib/pipes/barsa-icon-dict.pipe.mjs +18 -0
  74. package/esm2020/lib/pipes/bbb-translate.pipe.mjs +29 -0
  75. package/esm2020/lib/pipes/can-upload.pipe.mjs +30 -0
  76. package/esm2020/lib/pipes/context-menu.pipe.mjs +40 -0
  77. package/esm2020/lib/pipes/control-ui.pipe.mjs +31 -0
  78. package/esm2020/lib/pipes/convert-to-style.pipe.mjs +32 -0
  79. package/esm2020/lib/pipes/date-time-to-caption.pipe.mjs +34 -0
  80. package/esm2020/lib/pipes/fileinfo-count.pipe.mjs +20 -0
  81. package/esm2020/lib/pipes/filter-columns-by-details.pipe.mjs +20 -0
  82. package/esm2020/lib/pipes/filter-string.pipe.mjs +44 -0
  83. package/esm2020/lib/pipes/filter-tab.pipe.mjs +19 -0
  84. package/esm2020/lib/pipes/filter-toolbar-control.pipe.mjs +16 -0
  85. package/esm2020/lib/pipes/filter.pipe.mjs +33 -0
  86. package/esm2020/lib/pipes/find-column-by-db-name.pipe.mjs +17 -0
  87. package/esm2020/lib/pipes/fiori-icon.pipe.mjs +42 -0
  88. package/esm2020/lib/pipes/groupby.pipe.mjs +48 -0
  89. package/esm2020/lib/pipes/header-facet-value.pipe.mjs +22 -0
  90. package/esm2020/lib/pipes/index.mjs +33 -0
  91. package/esm2020/lib/pipes/list-count.pipe.mjs +17 -0
  92. package/esm2020/lib/pipes/merge-fields-to-columns.pipe.mjs +42 -0
  93. package/esm2020/lib/pipes/mo-info-ulv-data.pipe.mjs +24 -0
  94. package/esm2020/lib/pipes/mo-report-value-concat.pipe.mjs +35 -0
  95. package/esm2020/lib/pipes/mo-report-value.pipe.mjs +28 -0
  96. package/esm2020/lib/pipes/mo-value.pipe.mjs +31 -0
  97. package/esm2020/lib/pipes/multiple-groupby.pipe.mjs +97 -0
  98. package/esm2020/lib/pipes/numeral.pipe.mjs +40 -0
  99. package/esm2020/lib/pipes/picture-field-source.pipe.mjs +22 -0
  100. package/esm2020/lib/pipes/remove-newline.pipe.mjs +20 -0
  101. package/esm2020/lib/pipes/seperator-fix.pipe.mjs +23 -0
  102. package/esm2020/lib/pipes/sort.pipe.mjs +48 -0
  103. package/esm2020/lib/pipes/tlbButtons.pipe.mjs +58 -0
  104. package/esm2020/lib/pipes/total-summary.pipe.mjs +16 -0
  105. package/esm2020/lib/pipes/visible-value.pipe.mjs +24 -0
  106. package/esm2020/lib/portal-page/portal-page.component.mjs +13 -0
  107. package/esm2020/lib/redirect-home-guard.mjs +28 -0
  108. package/esm2020/lib/redirect-report-navigator-command/redirect-report-navigator-command.component.mjs +33 -0
  109. package/esm2020/lib/report-container/report-container.component.mjs +52 -0
  110. package/esm2020/lib/resolvers/index.mjs +5 -0
  111. package/esm2020/lib/resolvers/portal-dynamic-page.resolver.mjs +49 -0
  112. package/esm2020/lib/resolvers/portal-form-page.resolver.mjs +18 -0
  113. package/esm2020/lib/resolvers/portal-page.resolver.mjs +30 -0
  114. package/esm2020/lib/resolvers/portal-report-page.resolver.mjs +37 -0
  115. package/esm2020/lib/root-page/root-page.component.mjs +21 -0
  116. package/esm2020/lib/root-portal/root-portal.component.mjs +51 -0
  117. package/esm2020/lib/services/api.service.mjs +60 -0
  118. package/esm2020/lib/services/barsa-dialog.service.mjs +80 -0
  119. package/esm2020/lib/services/breadcrumb.service.mjs +60 -0
  120. package/esm2020/lib/services/container.service.mjs +36 -0
  121. package/esm2020/lib/services/dynamic-component.service.mjs +55 -0
  122. package/esm2020/lib/services/form-panel.service.mjs +235 -0
  123. package/esm2020/lib/services/form.service.mjs +14 -0
  124. package/esm2020/lib/services/horizontal-layout.service.mjs +16 -0
  125. package/esm2020/lib/services/index.mjs +16 -0
  126. package/esm2020/lib/services/layout.service.mjs +42 -0
  127. package/esm2020/lib/services/log.service.mjs +50 -0
  128. package/esm2020/lib/services/network-status.service.mjs +15 -0
  129. package/esm2020/lib/services/portal.service.mjs +638 -0
  130. package/esm2020/lib/services/ui.service.mjs +23 -0
  131. package/esm2020/lib/services/ulvmain.service.mjs +594 -0
  132. package/esm2020/lib/services/upload.service.mjs +75 -0
  133. package/esm2020/public-api.mjs +33 -0
  134. package/fesm2015/barsa-novin-ray-core.mjs +9047 -0
  135. package/fesm2015/barsa-novin-ray-core.mjs.map +1 -0
  136. package/fesm2020/barsa-novin-ray-core.mjs +8945 -0
  137. package/fesm2020/barsa-novin-ray-core.mjs.map +1 -0
  138. package/index.d.ts +5 -0
  139. package/lib/abstract-classes/application-base.d.ts +53 -0
  140. package/lib/abstract-classes/barsa-api.d.ts +28 -0
  141. package/lib/abstract-classes/field-base.d.ts +81 -0
  142. package/lib/abstract-classes/files-validation-helper.d.ts +15 -0
  143. package/lib/abstract-classes/form-base.d.ts +59 -0
  144. package/lib/abstract-classes/form-props.base.d.ts +45 -0
  145. package/lib/abstract-classes/form-toolbar-base.d.ts +17 -0
  146. package/lib/abstract-classes/index.d.ts +20 -0
  147. package/lib/abstract-classes/layout-item-base.d.ts +15 -0
  148. package/lib/abstract-classes/layout-panel-base.d.ts +24 -0
  149. package/lib/abstract-classes/models.d.ts +660 -0
  150. package/lib/abstract-classes/module-with-dynamic-components.d.ts +4 -0
  151. package/lib/abstract-classes/number-base.d.ts +20 -0
  152. package/lib/abstract-classes/page-base.d.ts +31 -0
  153. package/lib/abstract-classes/report-base.d.ts +97 -0
  154. package/lib/abstract-classes/report-item-base.d.ts +33 -0
  155. package/lib/abstract-classes/report-view-base.component.d.ts +130 -0
  156. package/lib/abstract-classes/system-base.d.ts +45 -0
  157. package/lib/auth-guard.d.ts +12 -0
  158. package/lib/barsa-novin-ray-core-routing.module.d.ts +7 -0
  159. package/lib/barsa-novin-ray-core.module.d.ts +88 -0
  160. package/lib/base-ulv-setting.component.d.ts +18 -0
  161. package/lib/base.component.d.ts +15 -0
  162. package/lib/base.module.d.ts +13 -0
  163. package/lib/constants.d.ts +89 -0
  164. package/lib/container.component.d.ts +33 -0
  165. package/lib/custom-route-reuse-strategy.d.ts +11 -0
  166. package/lib/date-services/date-hijri.service.d.ts +40 -0
  167. package/lib/date-services/date-info.d.ts +15 -0
  168. package/lib/date-services/date-miladi.service.d.ts +39 -0
  169. package/lib/date-services/date-shamsi.service.d.ts +40 -0
  170. package/lib/date-services/date.service.d.ts +54 -0
  171. package/lib/date-services/index.d.ts +5 -0
  172. package/lib/device.d.ts +15 -0
  173. package/lib/directives/anchor-scroll.directive.d.ts +7 -0
  174. package/lib/directives/attr-rtl.directive.d.ts +13 -0
  175. package/lib/directives/base.directive.d.ts +13 -0
  176. package/lib/directives/column-resizer.directive.d.ts +13 -0
  177. package/lib/directives/dynamic-command.directive.d.ts +12 -0
  178. package/lib/directives/ellipsify.directive.d.ts +17 -0
  179. package/lib/directives/field-binding.directive.d.ts +7 -0
  180. package/lib/directives/img-lazy.directive.d.ts +20 -0
  181. package/lib/directives/index.d.ts +18 -0
  182. package/lib/directives/intersection-observer.directive.d.ts +17 -0
  183. package/lib/directives/items-renderer.directive.d.ts +17 -0
  184. package/lib/directives/numbers-only-input.directive.d.ts +9 -0
  185. package/lib/directives/placeHolder.directive.d.ts +6 -0
  186. package/lib/directives/render-ulv-paging.directive.d.ts +19 -0
  187. package/lib/directives/render-ulv-viewer.directive.d.ts +19 -0
  188. package/lib/directives/table-resizer.directive.d.ts +47 -0
  189. package/lib/directives/ulv-command.directive.d.ts +11 -0
  190. package/lib/directives/until-inview.directive.d.ts +17 -0
  191. package/lib/dynamic-component/base-dynamic.component.d.ts +26 -0
  192. package/lib/dynamic-component/base-form-toolbaritem-props.d.ts +28 -0
  193. package/lib/dynamic-component/base-item-content-props.d.ts +40 -0
  194. package/lib/dynamic-component/base-view-content-props.d.ts +11 -0
  195. package/lib/dynamic-component/base-view-item-props.d.ts +95 -0
  196. package/lib/dynamic-component/base-view-props.d.ts +65 -0
  197. package/lib/dynamic-component/dynamic-form-toolbar-item.component.d.ts +18 -0
  198. package/lib/dynamic-component/dynamic-form.component.d.ts +33 -0
  199. package/lib/dynamic-component/dynamic-item.component.d.ts +30 -0
  200. package/lib/dynamic-component/index.d.ts +9 -0
  201. package/lib/empty-page-with-router-and-router-outlet/empty-page-with-router-and-router-outlet.component.d.ts +7 -0
  202. package/lib/field-ui/field-ui.component.d.ts +27 -0
  203. package/lib/form/form.component.d.ts +36 -0
  204. package/lib/form-new/form-new.component.d.ts +23 -0
  205. package/lib/from-intersection-observer.d.ts +7 -0
  206. package/lib/global-error-handler.d.ts +8 -0
  207. package/lib/modal-root.component.d.ts +15 -0
  208. package/lib/not-found/not-found.component.d.ts +8 -0
  209. package/lib/pipes/barsa-icon-dict.pipe.d.ts +9 -0
  210. package/lib/pipes/bbb-translate.pipe.d.ts +7 -0
  211. package/lib/pipes/can-upload.pipe.d.ts +8 -0
  212. package/lib/pipes/context-menu.pipe.d.ts +11 -0
  213. package/lib/pipes/control-ui.pipe.d.ts +9 -0
  214. package/lib/pipes/convert-to-style.pipe.d.ts +8 -0
  215. package/lib/pipes/date-time-to-caption.pipe.d.ts +9 -0
  216. package/lib/pipes/fileinfo-count.pipe.d.ts +10 -0
  217. package/lib/pipes/filter-columns-by-details.pipe.d.ts +8 -0
  218. package/lib/pipes/filter-string.pipe.d.ts +11 -0
  219. package/lib/pipes/filter-tab.pipe.d.ts +7 -0
  220. package/lib/pipes/filter-toolbar-control.pipe.d.ts +8 -0
  221. package/lib/pipes/filter.pipe.d.ts +10 -0
  222. package/lib/pipes/find-column-by-db-name.pipe.d.ts +8 -0
  223. package/lib/pipes/fiori-icon.pipe.d.ts +7 -0
  224. package/lib/pipes/groupby.pipe.d.ts +7 -0
  225. package/lib/pipes/header-facet-value.pipe.d.ts +8 -0
  226. package/lib/pipes/index.d.ts +32 -0
  227. package/lib/pipes/list-count.pipe.d.ts +8 -0
  228. package/lib/pipes/merge-fields-to-columns.pipe.d.ts +10 -0
  229. package/lib/pipes/mo-info-ulv-data.pipe.d.ts +7 -0
  230. package/lib/pipes/mo-report-value-concat.pipe.d.ts +9 -0
  231. package/lib/pipes/mo-report-value.pipe.d.ts +12 -0
  232. package/lib/pipes/mo-value.pipe.d.ts +9 -0
  233. package/lib/pipes/multiple-groupby.pipe.d.ts +23 -0
  234. package/lib/pipes/numeral.pipe.d.ts +9 -0
  235. package/lib/pipes/picture-field-source.pipe.d.ts +8 -0
  236. package/lib/pipes/remove-newline.pipe.d.ts +8 -0
  237. package/lib/pipes/seperator-fix.pipe.d.ts +7 -0
  238. package/lib/pipes/sort.pipe.d.ts +9 -0
  239. package/lib/pipes/tlbButtons.pipe.d.ts +9 -0
  240. package/lib/pipes/total-summary.pipe.d.ts +8 -0
  241. package/lib/pipes/visible-value.pipe.d.ts +8 -0
  242. package/lib/portal-page/portal-page.component.d.ts +6 -0
  243. package/lib/redirect-home-guard.d.ts +13 -0
  244. package/lib/redirect-report-navigator-command/redirect-report-navigator-command.component.d.ts +14 -0
  245. package/lib/report-container/report-container.component.d.ts +24 -0
  246. package/lib/resolvers/index.d.ts +4 -0
  247. package/lib/resolvers/portal-dynamic-page.resolver.d.ts +12 -0
  248. package/lib/resolvers/portal-form-page.resolver.d.ts +8 -0
  249. package/lib/resolvers/portal-page.resolver.d.ts +12 -0
  250. package/lib/resolvers/portal-report-page.resolver.d.ts +12 -0
  251. package/lib/root-page/root-page.component.d.ts +10 -0
  252. package/lib/root-portal/root-portal.component.d.ts +14 -0
  253. package/lib/services/api.service.d.ts +18 -0
  254. package/lib/services/barsa-dialog.service.d.ts +31 -0
  255. package/lib/services/breadcrumb.service.d.ts +14 -0
  256. package/lib/services/container.service.d.ts +14 -0
  257. package/lib/services/dynamic-component.service.d.ts +13 -0
  258. package/lib/services/form-panel.service.d.ts +83 -0
  259. package/lib/services/form.service.d.ts +8 -0
  260. package/lib/services/horizontal-layout.service.d.ts +7 -0
  261. package/lib/services/index.d.ts +15 -0
  262. package/lib/services/layout.service.d.ts +23 -0
  263. package/lib/services/log.service.d.ts +17 -0
  264. package/lib/services/network-status.service.d.ts +7 -0
  265. package/lib/services/portal.service.d.ts +130 -0
  266. package/lib/services/ui.service.d.ts +14 -0
  267. package/lib/services/ulvmain.service.d.ts +178 -0
  268. package/lib/services/upload.service.d.ts +18 -0
  269. package/package.json +38 -0
  270. 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