From rob.aerogear at robertwillett.com Sun Dec 20 14:52:30 2015 Content-Type: multipart/mixed; boundary="===============3356764396286687352==" MIME-Version: 1.0 From: Rob Willett To: aerogear-users at lists.jboss.org Subject: Re: [Aerogear-users] Possible bug in Aerogear Push Cordova/iOS implementation but not in the Cordova/Android version Date: Sun, 20 Dec 2015 19:52:29 +0000 Message-ID: <572042FF-7B4C-4CD0-BC4D-A7057A39A191@robertwillett.com> In-Reply-To: E9382606-BFC9-4788-BC60-B9527010D405@robertwillett.com --===============3356764396286687352== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Dear all, We *think* we can now reproduce the problem. Clearly writing the last = e-mail has focussed our attention :) Summary. We have a simple Ionic app that would call the Aerogear notification = handler when notifications were receive in the foreground and when the = app was in the background. The Aerogear notification handler would = sometimes be called and sometimes NOT be called when a notification was = received when the app was not started. See our long previous e-mails = detailing the problem. We think we can now reproduce the problem as follows: 1. Kill the app. 2. Send a notification down to the app. 3. It appears in the iOS notification drawer 4. Click on the notification. if the Aerogear handler has worked then go = to 1 and repeat. We want a failure :) 5. If the Aerogear handler is NOT called, then put the app into the = background using the Home button and then click on the app icon to = resume. 6. The notification is now processed by the Aerogear handler. We can now = see it. We are at a loss to explain this, we found it by accident, but we think = it shows some sort of timing issue somewhere because if we pull out the = various Javascript files the Aerogear plugin seems to work consistently = at startup. We have checked and checked the JavaScript files and cannot = see any error with them at all at load time. All suggestions welcome now. Rob On 20 Dec 2015, at 19:26, Rob Willett wrote: > Erik, Sebastien, > > We=E2=80=99ve spent a significant part of the weekend looking into this = > issue and we have still not got to the bottom of it. > > We have built a very simple Ionic test app that works in isolation. We = > have used the default Ionic tabs at > > http://ionicframework.com/getting-started/ > > We then add in our Javascript files as > > > > > > > > > > > > > > > > ``` > > We do NOT call any functions within any of these files, indeed we make = > no reference to these files beyond including them in the index.html = > file. Our dummy html templates make no reference to them. We simply = > load the javascript files in. We get no errors from including the = > files. We have used the controllers and services as provided by the = > dummy sample Ionic app. > > If we then send foreground notifications, the notifications are always = > handled by the Aerogear notification handler. > > If we send notifications to the app when it is in the background, the = > notifications are always handled by the Aerogear notification handler. > > If we kill by swiping up the app, we get the notifications but when we = > click on the notification from the main IOS screen it is arbitrary as = > to whether the notification is handled by the Aerogear handler when = > the app starts up. Sometimes the handler is called, but once the = > handler is not called, the Aerogear notification handler never appears = > to be called again. If we reinstall the app it sometimes works again = > and sometimes it fails. > > We can reinstall the app and the Aerogear notification handler might = > be called or it might not. We just ran the app with 20 tests to the = > app, each time killing the app and then sending down a a notification = > and it started the Aerogear notification handler each time. We then = > reinstall the app again, no changes in the code and it simply = > doesn=E2=80=99t process any notification when the app is closed. The = > notification turns up, but no event is called to the Aerogear event = > handler. > > Given that we are getting arbitrary results from the same codebase, = > clearly something is remiss. Sometimes it works and sometimes it = > doesn=E2=80=99t. There is no logic that we can see. We=E2=80=99ve closed = down = > Xcode after installing, we=E2=80=99ve started and stopped our sample app = a = > few times to try and make sure its closed down, ew are sending exactly = > the same payload each time. > > We feel that there is some sort of timing or race condition, or if = > this was a piece of C code, that we are overwriting somewhere we = > shouldn=E2=80=99t be. It has that sort of feeling of a pointer going bad = but = > we cannot see where the issue is at all. The fact that we get = > different results from doing the same install is very worrying but we = > can=E2=80=99t say whether its the Aerogear plugin, Ionic or our code. > > Thanks, > > Rob > > > On 18 Dec 2015, at 17:26, Rob Willett wrote: > >> Erok, >> >> We=E2=80=99ve not forgotten the notification issue, we=E2=80=99re still = working = >> on it to try and get to the bottom of it. The problem for us is that = >> its not so simple to cut code out and try and reduce the problem = >> down. Our code is quite interlinked, for good or for worse. >> >> We=E2=80=99ve added some simple sound debugging to the Objective C sourc= e = >> for the Aerogear plugin. This means that we can hear where things are = >> when the plugin starts up from a cold start after receiving a = >> notification. This works quite well. >> >> We initially added a beep to here >> >> ``` >> - (void)notificationReceived { >> NSLog(@"Notification received"); >> >> AudioServicesPlaySystemSound(1005); >> >> >> if (notificationMessage && self.callbackId) { >> ``` >> >> and this works whenever we get a notification in the foreground and = >> when the app is in the background. We then started tracing backwards = >> in the source code to see what called notificationReceived >> >> We can see it here >> >> ``` >> - (void)register:(CDVInvokedUrlCommand *)command; { >> NSLog(@"register"); >> self.callbackId =3D command.callbackId; >> >> AudioServicesPlaySystemSound(1007); >> >> isInline =3D NO; >> >> [self.commandDelegate runInBackground:^{ >> NSMutableDictionary *options =3D [self parseOptions:command]; >> [self saveConfig:options]; >> >> // when running under iOS 8 we will use the new API for APNS = >> registration >> #if __IPHONE_OS_VERSION_MAX_ALLOWED >=3D 80000 >> if ([[UIApplication sharedApplication] = >> respondsToSelector:@selector(registerUserNotificationSettings:)]) { >> UIUserNotificationSettings* notificationSettings =3D = >> [UIUserNotificationSettings = >> settingsForTypes:UIUserNotificationTypeAlert | = >> UIUserNotificationTypeBadge | UIUserNotificationTypeSound = >> categories:nil]; >> [[UIApplication sharedApplication] = >> registerUserNotificationSettings:notificationSettings]; >> [[UIApplication sharedApplication] = >> registerForRemoteNotifications]; >> } else { >> [[UIApplication sharedApplication] = >> registerForRemoteNotificationTypes: (UIRemoteNotificationTypeBadge | = >> UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]; >> } >> >> #else >> [[UIApplication sharedApplication] = >> registerForRemoteNotificationTypes: (UIRemoteNotificationTypeBadge | = >> UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]; >> #endif >> >> CDVPluginResult* pluginResult =3D [CDVPluginResult = >> resultWithStatus:CDVCommandStatus_NO_RESULT]; >> [pluginResult setKeepCallback:@YES]; >> [self.commandDelegate sendPluginResult:pluginResult = >> callbackId:command.callbackId]; >> }]; >> >> if (notificationMessage) // if there is a pending startup = >> notification >> { >> AudioServicesPlaySystemSound(1024); >> >> [self notificationReceived]; // go ahead and process it >> } >> } >> ```` >> >> So we add some more beeps in to track down whats going on. We add = >> AudioServicesPlaySystemSound(1007) at the beginning of the function = >> and add AudioServicesPlaySystemSound(1024) just before we call the = >> notificationReceived method. >> >> We get the first sounds on startup but do NOT get the second set of = >> sounds. It looks like notificationMessage is not being set at = >> application startup. >> >> Our problem now is that we are not Objective-C developers so we are = >> struggling to debug much further. So trying to understand how = >> notificationMessage is set and defined as its declared as @synthesis = >> is unclear. We=E2=80=99ll start reading and learning quickly but as this= is = >> new for us, so we will be slow. >> >> Any suggestions welcomed, >> >> Rob >> >> On 16 Dec 2015, at 16:54, Erik Jan de Wit wrote: >> >>> Hi Rob, >>> >>> What you could try is to debug this in xcode, when the notification = >>> is >>> touched it should launch the app and that will in turn call the JS >>> callback. Would be good to see if this code is called 100% of the = >>> time. >>> >>> You can put a breakpoint here: >>> https://github.com/aerogear/aerogear-cordova-push/blob/master/src/ios/A= ppDelegate%2Bnotification.m#L56 >>> >>> That code will execute on cold start and here: >>> https://github.com/aerogear/aerogear-cordova-push/blob/master/src/ios/A= GPushPlugin.m#L102 >>> >>> That is where the onNotification callback gets invoked. >>> >>> Hope this helps, >>> >>> On Wed, Dec 16, 2015 at 5:14 PM, Rob Willett = >>> >>> wrote: >>> >>>> Sebastien >>>> >>>> Yes, we do it at that point, $ionicPlatform.ready. I include the = >>>> whole of >>>> that area of code for reference but we=E2=80=99re not expecting you to = >>>> debug it for >>>> us. Merely to demonstrate its there. >>>> >>>> At the moment all we want the code to do is put an alert up. >>>> >>>> .run(function($ionicPlatform , CordovaService) { >>>> $ionicPlatform.ready(function() { >>>> if (window.StatusBar) { >>>> // org.apache.cordova.statusbar required >>>> StatusBar.styleDefault(); >>>> } >>>> >>>> ConsoleLog('<<< Cordova ready >>>'); >>>> >>>> /* This seems to remove an annoying page flicker on iOS when the = >>>> keyboard is displayed */ >>>> cordova.plugins.Keyboard.disableScroll(true); >>>> >>>> isDeviceReady =3D true; >>>> >>>> var uuid =3D "D26FBAF1-2EF2-4614-875F-4497EC4212D5/JFL1-0/ios_app"; >>>> >>>> var aeroGearPushConfig =3D { >>>> pushServerURL: "https://push-jambuster.rhcloud.com/ag-push/", >>>> ios: { >>>> variantID: =E2=80=9CXXXXX=E2=80=9D, >>>> variantSecret: =E2=80=9CYYYYYYY=E2=80=9D >>>> } , >>>> // sendMetricInfo: true, >>>> alias: uuid >>>> }; >>>> >>>> push.register(function (event) { >>>> alert("EVENT =3D " + JSON.stringify(event)); >>>> >>>> } , function () { >>>> if (1) >>>> { >>>> // alert("AeroGearSuccessHandler: OK " + JSON.stringify(uuid)); >>>> // ConsoleLog("UUID =3D " + uuid); >>>> } >>>> } , function () { >>>> } , aeroGearPushConfig); >>>> >>>> We were still loading up another 18,000 lines of code so we need to = >>>> start >>>> pruning that back until we have something that works. >>>> >>>> Rob >>>> >>>> On 16 Dec 2015, at 16:04, Sebastien Blanc wrote: >>>> >>>> In the ionic app when do you do the registration of UPS ? on the >>>> platformReady event ? >>>> >>>> On Wed, Dec 16, 2015 at 4:54 PM, Rob Willett < >>>> rob.aerogear(a)robertwillett.com >>>> >>>> wrote: >>>> >>>> Erik, >>>> >>>> We have built the simplest possible app we can that uses the = >>>> Aerogear >>>> push plugin but using the ionic tabs starter kit. >>>> >>>> http://ionicframework.com/getting-started/ >>>> >>>> We have taken the code directly from the Cordova simple app that we = >>>> have >>>> got working and put it into the Ionic app. >>>> >>>> if we follow your tests as below: >>>> >>>> 1. >>>> >>>> IOS App in foreground, we send a simple push notification from the >>>> Aerogear console - Works OK, We can see the event. Good >>>> 2. >>>> >>>> IOS App in background, we send a simple push notification from the >>>> Aerogear console - Works OK, We can see the event. Good >>>> 3. >>>> >>>> IOS App killed, we send a simple push notification from the = >>>> Aerogear >>>> >>>> console and some of the time when we click on the notification in = >>>> the >>>> notification drawer we do NOT get the notification handler called. = >>>> Not >>>> so good >>>> >>>> >>>> However it does appear to work most of the time with our minimal = >>>> Ionic >>>> app, but some of the time it fails. We had a run of 1 in 2 failures = >>>> when >>>> we click on the notification. Now we have just done 20 runs in a = >>>> row, >>>> each time killing the app after receiving the notification and not = >>>> a >>>> single failure. Nothing changed. >>>> >>>> We cannot find any obvious reason for this so we are still >>>> investigating. >>>> >>>> We have reconfigured our main app to work the same way as the = >>>> minimal >>>> app but we are still getting the same issues as before, we can see = >>>> the >>>> notification in the drawer but clicking on it does NOT call the = >>>> same >>>> handler with the same code as the minimal app. We get zero calls to = >>>> the >>>> notification event handler. >>>> >>>> We are wondering if there is a timing issue somewhere in our code, = >>>> but >>>> we can=E2=80=99t see it. We also wondered if the size of the code we a= re >>>> loading is the cause of a timing issue as well. >>>> >>>> Is there any way of adding more debugging into the Aerogear push = >>>> plugin >>>> to see if we can track things down that way? >>>> >>>> Its very frustrating, but thanks for your help to date. It does = >>>> look >>>> like its an interaction with our code, Ionic and the Aerogear = >>>> plugin. My >>>> money is on our code though. We=E2=80=99ll now start pulling working c= ode = >>>> out >>>> of our app until we get back to the minimal app. Only 18,604 lines = >>>> to go >>>> :) >>>> >>>> Rob >>>> >>>> On 15 Dec 2015, at 10:36, Erik Jan de Wit wrote: >>>> >>>> Hi Rob, >>>> >>>> That would be a bug, although I can not reproduce it, to test it = >>>> this >>>> is >>>> what I've done to test it: >>>> $ > cordova create push-test >>>> $ > cordova platform add ios >>>> $ > cordova plugin add aerogear-cordova-push >>>> >>>> copy paste your js code into www/js/index.js onDeviceReady, changed >>>> pushServerUrl and variant info and changed quotes to " (this is = >>>> your >>>> email >>>> client no doubt) and changed : into ; after console.log("Success") >>>> >>>> Attach Safari debugger and send a message when the app is in the >>>> foreground >>>> and get in the console: >>>> >>>> HandleAeroGearNotification: event =3D> >>>> >>>> >>>> {"alert":"test","foreground":true,"coldstart":false,"sound":"default",= "badge":-1,"payload":{}} >>>> >>>> I press the home button and send the app to the background send >>>> another >>>> message and 'touch' the message to launch the app: >>>> >>>> HandleAeroGearNotification: event =3D> >>>> >>>> >>>> {"alert":"background","foreground":false,"coldstart":false,"sound":"de= fault","badge":-1,"payload":{}} >>>> >>>> The I kill the app by pressing home twice and swiping over the app = >>>> to >>>> remove it send another message and 'touch' it to launch the app. = >>>> This >>>> kills >>>> my safari debugger so no way to see the console log, but in this = >>>> case >>>> coldstart should be true. To test this better changed the code to >>>> alert >>>> instead of console: >>>> >>>> function HandleAeroGearNotification(event) { >>>> alert("HandleAeroGearNotification: event =3D> " + event.coldstart); >>>> >>>> // Stuff cut for clarity >>>> } >>>> >>>> I send another notification 'touch' it to launch the app and see = >>>> the >>>> alert >>>> box display the text: >>>> >>>> HandleAeroGearNotification: event =3D> true >>>> >>>> Hope this helps >>>> >>>> On Mon, Dec 14, 2015 at 10:20 PM, Rob Willett < >>>> rob.aerogear(a)robertwillett.com> wrote: >>>> >>>> Hi, >>>> >>>> We think we have found a possible bug in the Aerogear Cordova 2.0.4 >>>> push >>>> plugin specifically on the iOS side. >>>> Summary >>>> >>>> We have two versions of our app, an Android and an IOS version. = >>>> Both >>>> use >>>> the latest Cordova push plugin 2.0.4. They also both have the = >>>> latest >>>> Cordova platforms, android 4.1.1, ios 3.9.2. Both the iOS and = >>>> Android >>>> versions are compiled at the same time. We are running cordova = >>>> 5.3.3 >>>> with >>>> Ionic 1.7.8 (?). >>>> >>>> 1. >>>> >>>> We make sure that both apps are NOT started up on each device. We >>>> also >>>> check they are NOT in the background. >>>> 2. >>>> >>>> We send the same simple notification to each device. This >>>> notification >>>> config is as below, we have anonymised the variants and alias in = >>>> this >>>> JSON >>>> structure, though we can report that the UPS server sends the data >>>> correctly. We use the additionalData flag to provide the = >>>> information >>>> necessary to decide which notification has been clicked in the >>>> notification >>>> drawer. >>>> >>>> 'variants' =3D> [=E2=80=98variant1=E2=80=99,=E2=80=99variant2=E2=80=99= ], >>>> 'message' =3D> { >>>> 'additionalData' =3D> { 'Disruption_Id' =3D> '107546', >>>> 'EpochTime' =3D> '1450125268' >>>> }, >>>> 'alert' =3D> 'Cannon Street (EC4N) (All Directions) at the junction = >>>> of >>>> King William Street - To facilitate a heavy lift in Cannon Street, >>>> Cannon Street will be closed. Traffic is slow moving on diversion.' >>>> }, >>>> 'alias' =3D> [ =E2=80=98alias1=E2=80=99 ], >>>> 'ttl' =3D> 600 >>>> }; >>>> >>>> 1. >>>> >>>> Both devices show the message, the Android device stacks the = >>>> message >>>> and the iOS device display an individual message. This looks = >>>> correct. >>>> 2. >>>> >>>> Clicking on the Android stacked message starts up the app and the >>>> Javascript notification handler we have defined, >>>> HandleAeroGearNotification >>>> is called >>>> >>>> HandleAeroGearNotification: event =3D> {"alert":"Cannon Street (EC4N) >>>> (All Directions) at the junction of King William Street - To >>>> facilitate a heavy lift in Cannon Street, Cannon Street will be >>>> closed. Traffic is slow moving on >>>> >>>> diversion.","coldstart":true,"foreground":true,"payload":{"alert":"Can= non >>>> >>>> Street (EC4N) (All Directions) at the junction of King William = >>>> Street >>>> - To facilitate a heavy lift in Cannon Street, Cannon Street will = >>>> be >>>> closed. Traffic is slow moving on diversion.","badge":"-1"}} >>>> >>>> 1. >>>> >>>> Clicking on the notification in the notification drawer on the iOS >>>> device also starts our app up correctly but the notification = >>>> handler, >>>> HandleAeroGearNotification(), is NOT called. The app starts up as >>>> normal as >>>> if the notification had not been clicked. We would expect the >>>> notification >>>> handler to be called in iOS as it is in Android. >>>> 2. >>>> >>>> All notifications are cleared on both Android and iOS correctly = >>>> when >>>> the app is started up. >>>> 3. >>>> >>>> We define HandleAeroGearNotification as >>>> >>>> var aeroGearPushConfig =3D { >>>> pushServerURL: "https://push-jambuster.rhcloud.com/ag-push/", >>>> ios: { >>>> variantID: =E2=80=9Cvariantid_obscured=E2=80=9D, >>>> variantSecret: =E2=80=9Cvariant_secret_obscured=E2=80=9D >>>> } , >>>> android: { >>>> senderID: "variantid_obscured" , >>>> variantID: "variant_id_obscured" , >>>> variantSecret: "variant_secret_obscured" >>>> } , >>>> sendMetricInfo: true, >>>> alias: alias1 >>>> }; >>>> >>>> function HandleAeroGearNotification(event) { >>>> console.log(=E2=80=9CHandleAeroGearNotification: event =3D> =E2=80=9C + >>>> JSON.stringify(event)); >>>> >>>> // Stuff cut for clarity >>>> } >>>> >>>> // Slightly simplified registration event. >>>> push.register(HandleAeroGearNotification , function () { >>>> console.log(=E2=80=9CSuccess=E2=80=9D): >>>> } , function () { >>>> console.log(=E2=80=9CFailure=E2=80=9D); >>>> } , aeroGearPushConfig); >>>> >>>> We cannot see any reference to this issue in the JIRA database and >>>> wondered if it is a bug or not. >>>> >>>> If its a bug we are happy to raise it accordingly. >>>> >>>> Please let us know, >>>> >>>> Thanks >>>> >>>> Rob >>>> ------------------------------ >>>> >>>> Aerogear-users mailing list >>>> Aerogear-users(a)lists.jboss.org >>>> https://lists.jboss.org/mailman/listinfo/aerogear-users >>>> >>>> -- >>>> Cheers, >>>> Erik Jan >>>> ------------------------------ >>>> >>>> Aerogear-users mailing list >>>> Aerogear-users(a)lists.jboss.org >>>> https://lists.jboss.org/mailman/listinfo/aerogear-users >>>> >>>> ------------------------------ >>>> >>>> Aerogear-users mailing list >>>> Aerogear-users(a)lists.jboss.org >>>> https://lists.jboss.org/mailman/listinfo/aerogear-users >>>> >>>> ------------------------------ >>>> >>>> Aerogear-users mailing list >>>> Aerogear-users(a)lists.jboss.org >>>> https://lists.jboss.org/mailman/listinfo/aerogear-users >>>> >>>> >>>> _______________________________________________ >>>> Aerogear-users mailing list >>>> Aerogear-users(a)lists.jboss.org >>>> https://lists.jboss.org/mailman/listinfo/aerogear-users >>>> >>>> >>> >>> >>> -- = >>> Cheers, >>> Erik Jan >>> _______________________________________________ >>> Aerogear-users mailing list >>> Aerogear-users(a)lists.jboss.org >>> https://lists.jboss.org/mailman/listinfo/aerogear-users >> _______________________________________________ >> Aerogear-users mailing list >> Aerogear-users(a)lists.jboss.org >> https://lists.jboss.org/mailman/listinfo/aerogear-users > _______________________________________________ > Aerogear-users mailing list > Aerogear-users(a)lists.jboss.org > https://lists.jboss.org/mailman/listinfo/aerogear-users --===============3356764396286687352== Content-Type: text/html MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="attachment.html" PGRpdiBjbGFzcz0ibWFya2Rvd24iPgo8cCBkaXI9ImF1dG8iPkRlYXIgYWxsLDwvcD4KCjxwIGRp cj0iYXV0byI+V2UgPGVtPnRoaW5rPC9lbT4gd2UgY2FuIG5vdyByZXByb2R1Y2UgdGhlIHByb2Js ZW0uIENsZWFybHkgd3JpdGluZyB0aGUgbGFzdCBlLW1haWwgaGFzIGZvY3Vzc2VkIG91ciBhdHRl bnRpb24gOik8L3A+Cgo8cCBkaXI9ImF1dG8iPlN1bW1hcnkuPC9wPgoKPHAgZGlyPSJhdXRvIj5X ZSBoYXZlIGEgc2ltcGxlIElvbmljIGFwcCB0aGF0IHdvdWxkIGNhbGwgdGhlIEFlcm9nZWFyIG5v dGlmaWNhdGlvbiBoYW5kbGVyIHdoZW4gbm90aWZpY2F0aW9ucyB3ZXJlIHJlY2VpdmUgaW4gdGhl IGZvcmVncm91bmQgYW5kIHdoZW4gdGhlIGFwcCB3YXMgaW4gdGhlIGJhY2tncm91bmQuIFRoZSBB ZXJvZ2VhciBub3RpZmljYXRpb24gaGFuZGxlciB3b3VsZCBzb21ldGltZXMgYmUgY2FsbGVkIGFu ZCBzb21ldGltZXMgTk9UIGJlIGNhbGxlZCB3aGVuIGEgbm90aWZpY2F0aW9uIHdhcyByZWNlaXZl ZCB3aGVuIHRoZSBhcHAgd2FzIG5vdCBzdGFydGVkLiBTZWUgb3VyIGxvbmcgcHJldmlvdXMgZS1t YWlscyBkZXRhaWxpbmcgdGhlIHByb2JsZW0uPC9wPgoKPHAgZGlyPSJhdXRvIj5XZSB0aGluayB3 ZSBjYW4gbm93IHJlcHJvZHVjZSB0aGUgcHJvYmxlbSBhcyBmb2xsb3dzOjwvcD4KCjxvbD4KPGxp IHZhbHVlPTE+PHAgZGlyPSJhdXRvIj5LaWxsIHRoZSBhcHAuPC9wPjwvbGk+CjxsaSB2YWx1ZT0y PjxwIGRpcj0iYXV0byI+U2VuZCBhIG5vdGlmaWNhdGlvbiBkb3duIHRvIHRoZSBhcHAuPC9wPjwv bGk+CjxsaSB2YWx1ZT0zPjxwIGRpcj0iYXV0byI+SXQgYXBwZWFycyBpbiB0aGUgaU9TIG5vdGlm aWNhdGlvbiBkcmF3ZXI8L3A+PC9saT4KPGxpIHZhbHVlPTQ+PHAgZGlyPSJhdXRvIj5DbGljayBv biB0aGUgbm90aWZpY2F0aW9uLiBpZiB0aGUgQWVyb2dlYXIgaGFuZGxlciBoYXMgd29ya2VkIHRo ZW4gZ28gdG8gMSBhbmQgcmVwZWF0LiBXZSB3YW50IGEgZmFpbHVyZSA6KTwvcD48L2xpPgo8bGkg dmFsdWU9NT48cCBkaXI9ImF1dG8iPklmIHRoZSBBZXJvZ2VhciBoYW5kbGVyIGlzIE5PVCBjYWxs ZWQsIHRoZW4gcHV0IHRoZSBhcHAgaW50byB0aGUgYmFja2dyb3VuZCB1c2luZyB0aGUgSG9tZSBi dXR0b24gYW5kIHRoZW4gY2xpY2sgb24gdGhlIGFwcCBpY29uIHRvIHJlc3VtZS4gPC9wPjwvbGk+ CjxsaSB2YWx1ZT02PjxwIGRpcj0iYXV0byI+VGhlIG5vdGlmaWNhdGlvbiBpcyBub3cgcHJvY2Vz c2VkIGJ5IHRoZSBBZXJvZ2VhciBoYW5kbGVyLiBXZSBjYW4gbm93IHNlZSBpdC48L3A+PC9saT4K PC9vbD4KCjxwIGRpcj0iYXV0byI+V2UgYXJlIGF0IGEgbG9zcyB0byBleHBsYWluIHRoaXMsIHdl IGZvdW5kIGl0IGJ5IGFjY2lkZW50LCBidXQgd2UgdGhpbmsgaXQgc2hvd3Mgc29tZSBzb3J0IG9m IHRpbWluZyBpc3N1ZSBzb21ld2hlcmUgYmVjYXVzZSBpZiB3ZSBwdWxsIG91dCB0aGUgdmFyaW91 cyBKYXZhc2NyaXB0IGZpbGVzIHRoZSBBZXJvZ2VhciBwbHVnaW4gc2VlbXMgdG8gd29yayBjb25z aXN0ZW50bHkgYXQgc3RhcnR1cC4gV2UgaGF2ZSBjaGVja2VkIGFuZCBjaGVja2VkIHRoZSBKYXZh U2NyaXB0IGZpbGVzIGFuZCBjYW5ub3Qgc2VlIGFueSBlcnJvciB3aXRoIHRoZW0gYXQgYWxsIGF0 IGxvYWQgdGltZS48L3A+Cgo8cCBkaXI9ImF1dG8iPkFsbCBzdWdnZXN0aW9ucyB3ZWxjb21lIG5v dy48L3A+Cgo8cCBkaXI9ImF1dG8iPlJvYjwvcD4KCjxwIGRpcj0iYXV0byI+T24gMjAgRGVjIDIw MTUsIGF0IDE5OjI2LCBSb2IgV2lsbGV0dCB3cm90ZTo8L3A+Cgo8YmxvY2txdW90ZT4KPHAgZGly PSJhdXRvIj5FcmlrLCBTZWJhc3RpZW4sPC9wPgoKPHAgZGlyPSJhdXRvIj5XZeKAmXZlIHNwZW50 IGEgc2lnbmlmaWNhbnQgcGFydCBvZiB0aGUgd2Vla2VuZCBsb29raW5nIGludG8gdGhpcyBpc3N1 ZSBhbmQgd2UgaGF2ZSBzdGlsbCBub3QgZ290IHRvIHRoZSBib3R0b20gb2YgaXQuPC9wPgoKPHAg ZGlyPSJhdXRvIj5XZSBoYXZlIGJ1aWx0IGEgdmVyeSBzaW1wbGUgSW9uaWMgdGVzdCBhcHAgdGhh dCB3b3JrcyBpbiBpc29sYXRpb24uIFdlIGhhdmUgdXNlZCB0aGUgZGVmYXVsdCBJb25pYyB0YWJz IGF0PC9wPgoKPHAgZGlyPSJhdXRvIj48YSBocmVmPSJodHRwOi8vaW9uaWNmcmFtZXdvcmsuY29t L2dldHRpbmctc3RhcnRlZC8iPmh0dHA6Ly9pb25pY2ZyYW1ld29yay5jb20vZ2V0dGluZy1zdGFy dGVkLzwvYT48L3A+Cgo8cCBkaXI9ImF1dG8iPldlIHRoZW4gYWRkIGluIG91ciBKYXZhc2NyaXB0 IGZpbGVzIGFzICZsdDtzY3JpcHQmZ3Q7IGVudHJpZXMgaW4gdGhlIGluZGV4Lmh0bWwgZmlsZSAo c2hvd24gZm9yIGV4YW1wbGUpPC9wPgoKPHByZT48Y29kZT4gJmx0O3NjcmlwdCBzcmM9ImpzL3Bv bHlnb24uanMiJmd0OyZsdDsvc2NyaXB0Jmd0OwogJmx0O3NjcmlwdCBzcmM9ImpzL3VybHMuanMi Jmd0OyZsdDsvc2NyaXB0Jmd0OwogJmx0O3NjcmlwdCBzcmM9ImpzL3V0aWxpdGllcy5qcyImZ3Q7 Jmx0Oy9zY3JpcHQmZ3Q7CgogJmx0O3NjcmlwdCBzcmM9ImpzL21vbWVudC5qcyImZ3Q7Jmx0Oy9z Y3JpcHQmZ3Q7CiAmbHQ7c2NyaXB0IHNyYz0ianMvcGVyaW1ldGVyLmpzIiZndDsmbHQ7L3Njcmlw dCZndDsKICZsdDtzY3JpcHQgc3JjPSJqcy9sZWFmbGV0Lm1hcmtlcmNsdXN0ZXItc3JjLmpzIiZn dDsmbHQ7L3NjcmlwdCZndDsKICZsdDtzY3JpcHQgc3JjPSJqcy9jeWNsZS5qcyImZ3Q7Jmx0Oy9z Y3JpcHQmZ3Q7CiAmbHQ7c2NyaXB0IHNyYz0ianMvY2xpcHBlci5qcyImZ3Q7Jmx0Oy9zY3JpcHQm Z3Q7CiAmbHQ7c2NyaXB0IHNyYz0ianMvZWFzeV9idXR0b24uanMiJmd0OyZsdDsvc2NyaXB0Jmd0 OwogJmx0O3NjcmlwdCBzcmM9ImpzL2dyYWhhbV9zY2FuLmpzIiZndDsmbHQ7L3NjcmlwdCZndDsK ICZsdDtzY3JpcHQgc3JjPSJqcy9zaGEuanMiJmd0OyZsdDsvc2NyaXB0Jmd0OwogJmx0O3Njcmlw dCBzcmM9ImpzL3ItdHJlZS5qcyImZ3Q7Jmx0Oy9zY3JpcHQmZ3Q7CiAmbHQ7c2NyaXB0IHNyYz0i anMvYW5ndWxhci1sZWFmbGV0LWRpcmVjdGl2ZS5taW4uanMiJmd0OyZsdDsvc2NyaXB0Jmd0Owog Jmx0O3NjcmlwdCBzcmM9InBvdWNoZGIvTC5UaWxlTGF5ZXIuUG91Y2hEQkNhY2hlZC5qcyImZ3Q7 Jmx0Oy9zY3JpcHQmZ3Q7CiAmbHQ7c2NyaXB0IHNyYz0icG91Y2hkYi9wb3VjaGRiLTUuMS4wLm1p bi5qcyImZ3Q7Jmx0Oy9zY3JpcHQmZ3Q7CjwvY29kZT48L3ByZT4KCjxwIGRpcj0iYXV0byI+V2Ug ZG8gTk9UIGNhbGwgYW55IGZ1bmN0aW9ucyB3aXRoaW4gYW55IG9mIHRoZXNlIGZpbGVzLCBpbmRl ZWQgd2UgbWFrZSBubyByZWZlcmVuY2UgdG8gdGhlc2UgZmlsZXMgYmV5b25kIGluY2x1ZGluZyB0 aGVtIGluIHRoZSBpbmRleC5odG1sIGZpbGUuIE91ciBkdW1teSBodG1sIHRlbXBsYXRlcyBtYWtl IG5vIHJlZmVyZW5jZSB0byB0aGVtLiBXZSBzaW1wbHkgbG9hZCB0aGUgamF2YXNjcmlwdCBmaWxl cyBpbi4gV2UgZ2V0IG5vIGVycm9ycyBmcm9tIGluY2x1ZGluZyB0aGUgZmlsZXMuIFdlIGhhdmUg dXNlZCB0aGUgY29udHJvbGxlcnMgYW5kIHNlcnZpY2VzIGFzIHByb3ZpZGVkIGJ5IHRoZSBkdW1t eSBzYW1wbGUgSW9uaWMgYXBwLjwvcD4KCjxwIGRpcj0iYXV0byI+SWYgd2UgdGhlbiBzZW5kIGZv cmVncm91bmQgbm90aWZpY2F0aW9ucywgdGhlIG5vdGlmaWNhdGlvbnMgYXJlIGFsd2F5cyBoYW5k bGVkIGJ5IHRoZSBBZXJvZ2VhciBub3RpZmljYXRpb24gaGFuZGxlci48L3A+Cgo8cCBkaXI9ImF1 dG8iPklmIHdlIHNlbmQgbm90aWZpY2F0aW9ucyB0byB0aGUgYXBwIHdoZW4gaXQgaXMgaW4gdGhl IGJhY2tncm91bmQsIHRoZSBub3RpZmljYXRpb25zIGFyZSBhbHdheXMgaGFuZGxlZCBieSB0aGUg QWVyb2dlYXIgbm90aWZpY2F0aW9uIGhhbmRsZXIuPC9wPgoKPHAgZGlyPSJhdXRvIj5JZiB3ZSBr aWxsIGJ5IHN3aXBpbmcgdXAgdGhlIGFwcCwgd2UgZ2V0IHRoZSBub3RpZmljYXRpb25zIGJ1dCB3 aGVuIHdlIGNsaWNrIG9uIHRoZSBub3RpZmljYXRpb24gZnJvbSB0aGUgbWFpbiBJT1Mgc2NyZWVu IGl0IGlzIGFyYml0cmFyeSBhcyB0byB3aGV0aGVyIHRoZSBub3RpZmljYXRpb24gaXMgaGFuZGxl ZCBieSB0aGUgQWVyb2dlYXIgaGFuZGxlciB3aGVuIHRoZSBhcHAgc3RhcnRzIHVwLiBTb21ldGlt ZXMgdGhlIGhhbmRsZXIgaXMgY2FsbGVkLCBidXQgb25jZSB0aGUgaGFuZGxlciBpcyBub3QgY2Fs bGVkLCB0aGUgQWVyb2dlYXIgbm90aWZpY2F0aW9uIGhhbmRsZXIgbmV2ZXIgYXBwZWFycyB0byBi ZSBjYWxsZWQgYWdhaW4uIElmIHdlIHJlaW5zdGFsbCB0aGUgYXBwIGl0IHNvbWV0aW1lcyB3b3Jr cyBhZ2FpbiBhbmQgc29tZXRpbWVzIGl0IGZhaWxzLjwvcD4KCjxwIGRpcj0iYXV0byI+V2UgY2Fu IHJlaW5zdGFsbCB0aGUgYXBwIGFuZCB0aGUgQWVyb2dlYXIgbm90aWZpY2F0aW9uIGhhbmRsZXIg bWlnaHQgYmUgY2FsbGVkIG9yIGl0IG1pZ2h0IG5vdC4gV2UganVzdCByYW4gdGhlIGFwcCB3aXRo IDIwIHRlc3RzIHRvIHRoZSBhcHAsIGVhY2ggdGltZSBraWxsaW5nIHRoZSBhcHAgYW5kIHRoZW4g c2VuZGluZyBkb3duIGEgYSBub3RpZmljYXRpb24gYW5kIGl0IHN0YXJ0ZWQgdGhlIEFlcm9nZWFy IG5vdGlmaWNhdGlvbiBoYW5kbGVyIGVhY2ggdGltZS4gV2UgdGhlbiByZWluc3RhbGwgdGhlIGFw cCBhZ2Fpbiwgbm8gY2hhbmdlcyBpbiB0aGUgY29kZSBhbmQgaXQgc2ltcGx5IGRvZXNu4oCZdCBw cm9jZXNzIGFueSBub3RpZmljYXRpb24gd2hlbiB0aGUgYXBwIGlzIGNsb3NlZC4gVGhlIG5vdGlm aWNhdGlvbiB0dXJucyB1cCwgYnV0IG5vIGV2ZW50IGlzIGNhbGxlZCB0byB0aGUgQWVyb2dlYXIg ZXZlbnQgaGFuZGxlci48L3A+Cgo8cCBkaXI9ImF1dG8iPkdpdmVuIHRoYXQgd2UgYXJlIGdldHRp bmcgYXJiaXRyYXJ5IHJlc3VsdHMgZnJvbSB0aGUgc2FtZSBjb2RlYmFzZSwgY2xlYXJseSBzb21l dGhpbmcgaXMgcmVtaXNzLiBTb21ldGltZXMgaXQgd29ya3MgYW5kIHNvbWV0aW1lcyBpdCBkb2Vz buKAmXQuIFRoZXJlIGlzIG5vIGxvZ2ljIHRoYXQgd2UgY2FuIHNlZS4gV2XigJl2ZSBjbG9zZWQg ZG93biBYY29kZSBhZnRlciBpbnN0YWxsaW5nLCB3ZeKAmXZlIHN0YXJ0ZWQgYW5kIHN0b3BwZWQg b3VyIHNhbXBsZSBhcHAgYSBmZXcgdGltZXMgdG8gdHJ5IGFuZCBtYWtlIHN1cmUgaXRzIGNsb3Nl ZCBkb3duLCBldyBhcmUgc2VuZGluZyBleGFjdGx5IHRoZSBzYW1lIHBheWxvYWQgZWFjaCB0aW1l LjwvcD4KCjxwIGRpcj0iYXV0byI+V2UgZmVlbCB0aGF0IHRoZXJlIGlzIHNvbWUgc29ydCBvZiB0 aW1pbmcgb3IgcmFjZSBjb25kaXRpb24sIG9yIGlmIHRoaXMgd2FzIGEgcGllY2Ugb2YgQyBjb2Rl LCB0aGF0IHdlIGFyZSBvdmVyd3JpdGluZyBzb21ld2hlcmUgd2Ugc2hvdWxkbuKAmXQgYmUuIEl0 IGhhcyB0aGF0IHNvcnQgb2YgZmVlbGluZyBvZiBhIHBvaW50ZXIgZ29pbmcgYmFkIGJ1dCB3ZSBj YW5ub3Qgc2VlIHdoZXJlIHRoZSBpc3N1ZSBpcyBhdCBhbGwuIFRoZSBmYWN0IHRoYXQgd2UgZ2V0 IGRpZmZlcmVudCByZXN1bHRzIGZyb20gZG9pbmcgdGhlIHNhbWUgaW5zdGFsbCBpcyB2ZXJ5IHdv cnJ5aW5nIGJ1dCB3ZSBjYW7igJl0IHNheSB3aGV0aGVyIGl0cyB0aGUgQWVyb2dlYXIgcGx1Z2lu LCBJb25pYyBvciBvdXIgY29kZS48L3A+Cgo8cCBkaXI9ImF1dG8iPlRoYW5rcyw8L3A+Cgo8cCBk aXI9ImF1dG8iPlJvYjwvcD4KCjxwIGRpcj0iYXV0byI+T24gMTggRGVjIDIwMTUsIGF0IDE3OjI2 LCBSb2IgV2lsbGV0dCB3cm90ZTo8L3A+Cgo8YmxvY2txdW90ZT4KPHAgZGlyPSJhdXRvIj5Fcm9r LDwvcD4KCjxwIGRpcj0iYXV0byI+V2XigJl2ZSBub3QgZm9yZ290dGVuIHRoZSBub3RpZmljYXRp b24gaXNzdWUsIHdl4oCZcmUgc3RpbGwgd29ya2luZyBvbiBpdCB0byB0cnkgYW5kIGdldCB0byB0 aGUgYm90dG9tIG9mIGl0LiBUaGUgcHJvYmxlbSBmb3IgdXMgaXMgdGhhdCBpdHMgbm90IHNvIHNp bXBsZSB0byBjdXQgY29kZSBvdXQgYW5kIHRyeSBhbmQgcmVkdWNlIHRoZSBwcm9ibGVtIGRvd24u IE91ciBjb2RlIGlzIHF1aXRlIGludGVybGlua2VkLCBmb3IgZ29vZCBvciBmb3Igd29yc2UuPC9w PgoKPHAgZGlyPSJhdXRvIj5XZeKAmXZlIGFkZGVkIHNvbWUgc2ltcGxlIHNvdW5kIGRlYnVnZ2lu ZyB0byB0aGUgT2JqZWN0aXZlIEMgc291cmNlIGZvciB0aGUgQWVyb2dlYXIgcGx1Z2luLiBUaGlz IG1lYW5zIHRoYXQgd2UgY2FuIGhlYXIgd2hlcmUgdGhpbmdzIGFyZSB3aGVuIHRoZSBwbHVnaW4g c3RhcnRzIHVwIGZyb20gYSBjb2xkIHN0YXJ0IGFmdGVyIHJlY2VpdmluZyBhIG5vdGlmaWNhdGlv bi4gVGhpcyB3b3JrcyBxdWl0ZSB3ZWxsLjwvcD4KCjxwIGRpcj0iYXV0byI+V2UgaW5pdGlhbGx5 IGFkZGVkIGEgYmVlcCB0byBoZXJlPC9wPgoKPHByZT48Y29kZT4tICh2b2lkKW5vdGlmaWNhdGlv blJlY2VpdmVkIHsKTlNMb2coQCJOb3RpZmljYXRpb24gcmVjZWl2ZWQiKTsKCkF1ZGlvU2Vydmlj ZXNQbGF5U3lzdGVtU291bmQoMTAwNSk7CgoKaWYgKG5vdGlmaWNhdGlvbk1lc3NhZ2UgJmFtcDsm YW1wOyBzZWxmLmNhbGxiYWNrSWQpIHsKPC9jb2RlPjwvcHJlPgoKPHAgZGlyPSJhdXRvIj5hbmQg dGhpcyB3b3JrcyB3aGVuZXZlciB3ZSBnZXQgYSBub3RpZmljYXRpb24gaW4gdGhlIGZvcmVncm91 bmQgYW5kIHdoZW4gdGhlIGFwcCBpcyBpbiB0aGUgYmFja2dyb3VuZC4gV2UgdGhlbiBzdGFydGVk IHRyYWNpbmcgYmFja3dhcmRzIGluIHRoZSBzb3VyY2UgY29kZSB0byBzZWUgd2hhdCBjYWxsZWQg bm90aWZpY2F0aW9uUmVjZWl2ZWQ8L3A+Cgo8cCBkaXI9ImF1dG8iPldlIGNhbiBzZWUgaXQgaGVy ZTwvcD4KCjxwcmU+PGNvZGU+LSAodm9pZClyZWdpc3RlcjooQ0RWSW52b2tlZFVybENvbW1hbmQg Kiljb21tYW5kOyB7Ck5TTG9nKEAicmVnaXN0ZXIiKTsKc2VsZi5jYWxsYmFja0lkID0gY29tbWFu ZC5jYWxsYmFja0lkOwoKQXVkaW9TZXJ2aWNlc1BsYXlTeXN0ZW1Tb3VuZCgxMDA3KTsKCmlzSW5s aW5lID0gTk87Cgpbc2VsZi5jb21tYW5kRGVsZWdhdGUgcnVuSW5CYWNrZ3JvdW5kOl57CiBOU011 dGFibGVEaWN0aW9uYXJ5ICpvcHRpb25zID0gW3NlbGYgcGFyc2VPcHRpb25zOmNvbW1hbmRdOwog W3NlbGYgc2F2ZUNvbmZpZzpvcHRpb25zXTsKCiAvLyB3aGVuIHJ1bm5pbmcgdW5kZXIgaU9TIDgg d2Ugd2lsbCB1c2UgdGhlIG5ldyBBUEkgZm9yIEFQTlMgcmVnaXN0cmF0aW9uCiAjaWYgX19JUEhP TkVfT1NfVkVSU0lPTl9NQVhfQUxMT1dFRCAmZ3Q7PSA4MDAwMAogICAgIGlmIChbW1VJQXBwbGlj YXRpb24gc2hhcmVkQXBwbGljYXRpb25dIHJlc3BvbmRzVG9TZWxlY3RvcjpAc2VsZWN0b3IocmVn aXN0ZXJVc2VyTm90aWZpY2F0aW9uU2V0dGluZ3M6KV0pIHsKICAgICAgICAgVUlVc2VyTm90aWZp Y2F0aW9uU2V0dGluZ3MqIG5vdGlmaWNhdGlvblNldHRpbmdzID0gW1VJVXNlck5vdGlmaWNhdGlv blNldHRpbmdzIHNldHRpbmdzRm9yVHlwZXM6VUlVc2VyTm90aWZpY2F0aW9uVHlwZUFsZXJ0IHwg VUlVc2VyTm90aWZpY2F0aW9uVHlwZUJhZGdlIHwgVUlVc2VyTm90aWZpY2F0aW9uVHlwZVNvdW5k IGNhdGVnb3JpZXM6bmlsXTsKICAgICAgICAgW1tVSUFwcGxpY2F0aW9uIHNoYXJlZEFwcGxpY2F0 aW9uXSByZWdpc3RlclVzZXJOb3RpZmljYXRpb25TZXR0aW5nczpub3RpZmljYXRpb25TZXR0aW5n c107CiAgICAgICAgIFtbVUlBcHBsaWNhdGlvbiBzaGFyZWRBcHBsaWNhdGlvbl0gcmVnaXN0ZXJG b3JSZW1vdGVOb3RpZmljYXRpb25zXTsKICAgICB9IGVsc2UgewogICAgICAgICBbW1VJQXBwbGlj YXRpb24gc2hhcmVkQXBwbGljYXRpb25dIHJlZ2lzdGVyRm9yUmVtb3RlTm90aWZpY2F0aW9uVHlw ZXM6IChVSVJlbW90ZU5vdGlmaWNhdGlvblR5cGVCYWRnZSB8IFVJUmVtb3RlTm90aWZpY2F0aW9u VHlwZVNvdW5kIHwgVUlSZW1vdGVOb3RpZmljYXRpb25UeXBlQWxlcnQpXTsKICAgICB9CgogI2Vs c2UKICAgICBbW1VJQXBwbGljYXRpb24gc2hhcmVkQXBwbGljYXRpb25dIHJlZ2lzdGVyRm9yUmVt b3RlTm90aWZpY2F0aW9uVHlwZXM6IChVSVJlbW90ZU5vdGlmaWNhdGlvblR5cGVCYWRnZSB8IFVJ UmVtb3RlTm90aWZpY2F0aW9uVHlwZVNvdW5kIHwgVUlSZW1vdGVOb3RpZmljYXRpb25UeXBlQWxl cnQpXTsKICNlbmRpZgoKIENEVlBsdWdpblJlc3VsdCogcGx1Z2luUmVzdWx0ID0gW0NEVlBsdWdp blJlc3VsdCByZXN1bHRXaXRoU3RhdHVzOkNEVkNvbW1hbmRTdGF0dXNfTk9fUkVTVUxUXTsKIFtw bHVnaW5SZXN1bHQgc2V0S2VlcENhbGxiYWNrOkBZRVNdOwogW3NlbGYuY29tbWFuZERlbGVnYXRl IHNlbmRQbHVnaW5SZXN1bHQ6cGx1Z2luUmVzdWx0IGNhbGxiYWNrSWQ6Y29tbWFuZC5jYWxsYmFj a0lkXTsKfV07CgppZiAobm90aWZpY2F0aW9uTWVzc2FnZSkgICAgICAgICAgICAvLyBpZiB0aGVy ZSBpcyBhIHBlbmRpbmcgc3RhcnR1cCBub3RpZmljYXRpb24KewogQXVkaW9TZXJ2aWNlc1BsYXlT eXN0ZW1Tb3VuZCgxMDI0KTsKCiBbc2VsZiBub3RpZmljYXRpb25SZWNlaXZlZF07ICAgIC8vIGdv IGFoZWFkIGFuZCBwcm9jZXNzIGl0Cn0KfQo8L2NvZGU+PC9wcmU+Cgo8cCBkaXI9ImF1dG8iPlNv IHdlIGFkZCBzb21lIG1vcmUgYmVlcHMgaW4gdG8gdHJhY2sgZG93biB3aGF0cyBnb2luZyBvbi4g V2UgYWRkIEF1ZGlvU2VydmljZXNQbGF5U3lzdGVtU291bmQoMTAwNykgYXQgdGhlIGJlZ2lubmlu ZyBvZiB0aGUgZnVuY3Rpb24gYW5kIGFkZCBBdWRpb1NlcnZpY2VzUGxheVN5c3RlbVNvdW5kKDEw MjQpIGp1c3QgYmVmb3JlIHdlIGNhbGwgdGhlIG5vdGlmaWNhdGlvblJlY2VpdmVkIG1ldGhvZC48 L3A+Cgo8cCBkaXI9ImF1dG8iPldlIGdldCB0aGUgZmlyc3Qgc291bmRzIG9uIHN0YXJ0dXAgYnV0 IGRvIE5PVCBnZXQgdGhlIHNlY29uZCBzZXQgb2Ygc291bmRzLiBJdCBsb29rcyBsaWtlIG5vdGlm aWNhdGlvbk1lc3NhZ2UgIGlzIG5vdCBiZWluZyBzZXQgYXQgYXBwbGljYXRpb24gc3RhcnR1cC48 L3A+Cgo8cCBkaXI9ImF1dG8iPk91ciBwcm9ibGVtIG5vdyBpcyB0aGF0IHdlIGFyZSBub3QgT2Jq ZWN0aXZlLUMgZGV2ZWxvcGVycyBzbyB3ZSBhcmUgc3RydWdnbGluZyB0byBkZWJ1ZyBtdWNoIGZ1 cnRoZXIuIFNvIHRyeWluZyB0byB1bmRlcnN0YW5kIGhvdyBub3RpZmljYXRpb25NZXNzYWdlIGlz IHNldCBhbmQgZGVmaW5lZCBhcyBpdHMgZGVjbGFyZWQgYXMgQHN5bnRoZXNpcyBpcyB1bmNsZWFy LiBXZeKAmWxsIHN0YXJ0IHJlYWRpbmcgYW5kIGxlYXJuaW5nIHF1aWNrbHkgYnV0IGFzIHRoaXMg aXMgbmV3IGZvciB1cywgc28gd2Ugd2lsbCBiZSBzbG93LjwvcD4KCjxwIGRpcj0iYXV0byI+QW55 IHN1Z2dlc3Rpb25zIHdlbGNvbWVkLDwvcD4KCjxwIGRpcj0iYXV0byI+Um9iPC9wPgoKPHAgZGly PSJhdXRvIj5PbiAxNiBEZWMgMjAxNSwgYXQgMTY6NTQsIEVyaWsgSmFuIGRlIFdpdCB3cm90ZTo8 L3A+Cgo8YmxvY2txdW90ZT4KPHAgZGlyPSJhdXRvIj5IaSBSb2IsPC9wPgoKPHAgZGlyPSJhdXRv Ij5XaGF0IHlvdSBjb3VsZCB0cnkgaXMgdG8gZGVidWcgdGhpcyBpbiB4Y29kZSwgd2hlbiB0aGUg bm90aWZpY2F0aW9uIGlzPGJyPgp0b3VjaGVkIGl0IHNob3VsZCBsYXVuY2ggdGhlIGFwcCBhbmQg dGhhdCB3aWxsIGluIHR1cm4gY2FsbCB0aGUgSlM8YnI+CmNhbGxiYWNrLiBXb3VsZCBiZSBnb29k IHRvIHNlZSBpZiB0aGlzIGNvZGUgaXMgY2FsbGVkIDEwMCUgb2YgdGhlIHRpbWUuPC9wPgoKPHAg ZGlyPSJhdXRvIj5Zb3UgY2FuIHB1dCBhIGJyZWFrcG9pbnQgaGVyZTo8YnI+CjxhIGhyZWY9Imh0 dHBzOi8vZ2l0aHViLmNvbS9hZXJvZ2Vhci9hZXJvZ2Vhci1jb3Jkb3ZhLXB1c2gvYmxvYi9tYXN0 ZXIvc3JjL2lvcy9BcHBEZWxlZ2F0ZSUyQm5vdGlmaWNhdGlvbi5tI0w1NiI+aHR0cHM6Ly9naXRo dWIuY29tL2Flcm9nZWFyL2Flcm9nZWFyLWNvcmRvdmEtcHVzaC9ibG9iL21hc3Rlci9zcmMvaW9z L0FwcERlbGVnYXRlJTJCbm90aWZpY2F0aW9uLm0jTDU2PC9hPjwvcD4KCjxwIGRpcj0iYXV0byI+ VGhhdCBjb2RlIHdpbGwgZXhlY3V0ZSBvbiBjb2xkIHN0YXJ0IGFuZCBoZXJlOjxicj4KPGEgaHJl Zj0iaHR0cHM6Ly9naXRodWIuY29tL2Flcm9nZWFyL2Flcm9nZWFyLWNvcmRvdmEtcHVzaC9ibG9i L21hc3Rlci9zcmMvaW9zL0FHUHVzaFBsdWdpbi5tI0wxMDIiPmh0dHBzOi8vZ2l0aHViLmNvbS9h ZXJvZ2Vhci9hZXJvZ2Vhci1jb3Jkb3ZhLXB1c2gvYmxvYi9tYXN0ZXIvc3JjL2lvcy9BR1B1c2hQ bHVnaW4ubSNMMTAyPC9hPjwvcD4KCjxwIGRpcj0iYXV0byI+VGhhdCBpcyB3aGVyZSB0aGUgb25O b3RpZmljYXRpb24gY2FsbGJhY2sgZ2V0cyBpbnZva2VkLjwvcD4KCjxwIGRpcj0iYXV0byI+SG9w ZSB0aGlzIGhlbHBzLDwvcD4KCjxwIGRpcj0iYXV0byI+T24gV2VkLCBEZWMgMTYsIDIwMTUgYXQg NToxNCBQTSwgUm9iIFdpbGxldHQgJmx0OzxhIGhyZWY9Im1haWx0bzpyb2IuYWVyb2dlYXJAcm9i ZXJ0d2lsbGV0dC5jb20iPnJvYi5hZXJvZ2VhckByb2JlcnR3aWxsZXR0LmNvbTwvYT48L3A+Cgo8 YmxvY2txdW90ZT4KPHAgZGlyPSJhdXRvIj53cm90ZTo8L3A+Cgo8cCBkaXI9ImF1dG8iPlNlYmFz dGllbjwvcD4KCjxwIGRpcj0iYXV0byI+WWVzLCB3ZSBkbyBpdCBhdCB0aGF0IHBvaW50LCAkaW9u aWNQbGF0Zm9ybS5yZWFkeS4gSSBpbmNsdWRlIHRoZSB3aG9sZSBvZjxicj4KdGhhdCBhcmVhIG9m IGNvZGUgZm9yIHJlZmVyZW5jZSBidXQgd2XigJlyZSBub3QgZXhwZWN0aW5nIHlvdSB0byBkZWJ1 ZyBpdCBmb3I8YnI+CnVzLiBNZXJlbHkgdG8gZGVtb25zdHJhdGUgaXRzIHRoZXJlLjwvcD4KCjxw IGRpcj0iYXV0byI+QXQgdGhlIG1vbWVudCBhbGwgd2Ugd2FudCB0aGUgY29kZSB0byBkbyBpcyBw dXQgYW4gYWxlcnQgdXAuPC9wPgoKPHAgZGlyPSJhdXRvIj4ucnVuKGZ1bmN0aW9uKCRpb25pY1Bs YXRmb3JtICwgQ29yZG92YVNlcnZpY2UpIHs8YnI+CiRpb25pY1BsYXRmb3JtLnJlYWR5KGZ1bmN0 aW9uKCkgezxicj4KaWYgKHdpbmRvdy5TdGF0dXNCYXIpIHs8YnI+Ci8vIG9yZy5hcGFjaGUuY29y ZG92YS5zdGF0dXNiYXIgcmVxdWlyZWQ8YnI+ClN0YXR1c0Jhci5zdHlsZURlZmF1bHQoKTs8YnI+ Cn08L3A+Cgo8cCBkaXI9ImF1dG8iPkNvbnNvbGVMb2coJyZsdDsmbHQ7Jmx0OyBDb3Jkb3ZhIHJl YWR5ICZndDsmZ3Q7Jmd0OycpOzwvcD4KCjxwIGRpcj0iYXV0byI+LyogVGhpcyBzZWVtcyB0byBy ZW1vdmUgYW4gYW5ub3lpbmcgcGFnZSBmbGlja2VyIG9uIGlPUyB3aGVuIHRoZSBrZXlib2FyZCBp cyBkaXNwbGF5ZWQgKi88YnI+CmNvcmRvdmEucGx1Z2lucy5LZXlib2FyZC5kaXNhYmxlU2Nyb2xs KHRydWUpOzwvcD4KCjxwIGRpcj0iYXV0byI+aXNEZXZpY2VSZWFkeSA9IHRydWU7PC9wPgoKPHAg ZGlyPSJhdXRvIj52YXIgdXVpZCA9ICJEMjZGQkFGMS0yRUYyLTQ2MTQtODc1Ri00NDk3RUM0MjEy RDUvSkZMMS0wL2lvc19hcHAiOzwvcD4KCjxwIGRpcj0iYXV0byI+dmFyIGFlcm9HZWFyUHVzaENv bmZpZyA9IHs8YnI+CnB1c2hTZXJ2ZXJVUkw6ICI8YSBocmVmPSJodHRwczovL3B1c2gtamFtYnVz dGVyLnJoY2xvdWQuY29tL2FnLXB1c2gvIj5odHRwczovL3B1c2gtamFtYnVzdGVyLnJoY2xvdWQu Y29tL2FnLXB1c2gvPC9hPiIsPGJyPgppb3M6IHs8YnI+CiAgdmFyaWFudElEOiDigJxYWFhYWOKA nSw8YnI+CiAgdmFyaWFudFNlY3JldDog4oCcWVlZWVlZWeKAnTxicj4KfSAsPGJyPgovLyBzZW5k TWV0cmljSW5mbzogdHJ1ZSw8YnI+CmFsaWFzOiB1dWlkPGJyPgp9OzwvcD4KCjxwIGRpcj0iYXV0 byI+cHVzaC5yZWdpc3RlcihmdW5jdGlvbiAoZXZlbnQpIHs8YnI+CmFsZXJ0KCJFVkVOVCA9ICIg KyBKU09OLnN0cmluZ2lmeShldmVudCkpOzwvcD4KCjxwIGRpcj0iYXV0byI+fSAsICBmdW5jdGlv biAoKSB7PGJyPgppZiAoMSk8YnI+Cns8YnI+CiAgLy8gYWxlcnQoIkFlcm9HZWFyU3VjY2Vzc0hh bmRsZXI6IE9LICIgKyBKU09OLnN0cmluZ2lmeSh1dWlkKSk7PGJyPgogIC8vIENvbnNvbGVMb2co IlVVSUQgPSAiICsgdXVpZCk7PGJyPgp9PGJyPgp9ICwgZnVuY3Rpb24gKCkgezxicj4KfSAsIGFl cm9HZWFyUHVzaENvbmZpZyk7PC9wPgoKPHAgZGlyPSJhdXRvIj5XZSB3ZXJlIHN0aWxsIGxvYWRp bmcgdXAgYW5vdGhlciAxOCwwMDAgbGluZXMgb2YgY29kZSBzbyB3ZSBuZWVkIHRvIHN0YXJ0PGJy PgpwcnVuaW5nIHRoYXQgYmFjayB1bnRpbCB3ZSBoYXZlIHNvbWV0aGluZyB0aGF0IHdvcmtzLjwv cD4KCjxwIGRpcj0iYXV0byI+Um9iPC9wPgoKPHAgZGlyPSJhdXRvIj5PbiAxNiBEZWMgMjAxNSwg YXQgMTY6MDQsIFNlYmFzdGllbiBCbGFuYyB3cm90ZTo8L3A+Cgo8cCBkaXI9ImF1dG8iPkluIHRo ZSBpb25pYyBhcHAgd2hlbiBkbyB5b3UgZG8gdGhlIHJlZ2lzdHJhdGlvbiBvZiBVUFMgPyBvbiB0 aGU8YnI+CnBsYXRmb3JtUmVhZHkgZXZlbnQgPzwvcD4KCjxwIGRpcj0iYXV0byI+T24gV2VkLCBE ZWMgMTYsIDIwMTUgYXQgNDo1NCBQTSwgUm9iIFdpbGxldHQgJmx0Ozxicj4KPGEgaHJlZj0ibWFp bHRvOnJvYi5hZXJvZ2VhckByb2JlcnR3aWxsZXR0LmNvbSI+cm9iLmFlcm9nZWFyQHJvYmVydHdp bGxldHQuY29tPC9hPjwvcD4KCjxwIGRpcj0iYXV0byI+d3JvdGU6PC9wPgoKPHAgZGlyPSJhdXRv Ij5FcmlrLDwvcD4KCjxwIGRpcj0iYXV0byI+V2UgaGF2ZSBidWlsdCB0aGUgc2ltcGxlc3QgcG9z c2libGUgYXBwIHdlIGNhbiB0aGF0IHVzZXMgdGhlIEFlcm9nZWFyPGJyPgpwdXNoIHBsdWdpbiBi dXQgdXNpbmcgdGhlIGlvbmljIHRhYnMgc3RhcnRlciBraXQuPC9wPgoKPHAgZGlyPSJhdXRvIj48 YSBocmVmPSJodHRwOi8vaW9uaWNmcmFtZXdvcmsuY29tL2dldHRpbmctc3RhcnRlZC8iPmh0dHA6 Ly9pb25pY2ZyYW1ld29yay5jb20vZ2V0dGluZy1zdGFydGVkLzwvYT48L3A+Cgo8cCBkaXI9ImF1 dG8iPldlIGhhdmUgdGFrZW4gdGhlIGNvZGUgZGlyZWN0bHkgZnJvbSB0aGUgQ29yZG92YSBzaW1w bGUgYXBwIHRoYXQgd2UgaGF2ZTxicj4KZ290IHdvcmtpbmcgYW5kIHB1dCBpdCBpbnRvIHRoZSBJ b25pYyBhcHAuPC9wPgoKPHAgZGlyPSJhdXRvIj5pZiB3ZSBmb2xsb3cgeW91ciB0ZXN0cyBhcyBi ZWxvdzo8L3A+Cgo8cCBkaXI9ImF1dG8iPjEuPC9wPgoKPHAgZGlyPSJhdXRvIj5JT1MgQXBwIGlu IGZvcmVncm91bmQsIHdlIHNlbmQgYSBzaW1wbGUgcHVzaCBub3RpZmljYXRpb24gZnJvbSB0aGU8 YnI+CkFlcm9nZWFyIGNvbnNvbGUgLSBXb3JrcyBPSywgV2UgY2FuIHNlZSB0aGUgZXZlbnQuIEdv b2Q8YnI+CjIuPC9wPgoKPHAgZGlyPSJhdXRvIj5JT1MgQXBwIGluIGJhY2tncm91bmQsIHdlIHNl bmQgYSBzaW1wbGUgcHVzaCBub3RpZmljYXRpb24gZnJvbSB0aGU8YnI+CkFlcm9nZWFyIGNvbnNv bGUgLSBXb3JrcyBPSywgV2UgY2FuIHNlZSB0aGUgZXZlbnQuIEdvb2Q8YnI+CjMuPC9wPgoKPHAg ZGlyPSJhdXRvIj5JT1MgQXBwIGtpbGxlZCwgd2Ugc2VuZCBhIHNpbXBsZSBwdXNoIG5vdGlmaWNh dGlvbiBmcm9tIHRoZSBBZXJvZ2VhcjwvcD4KCjxwIGRpcj0iYXV0byI+Y29uc29sZSBhbmQgc29t ZSBvZiB0aGUgdGltZSB3aGVuIHdlIGNsaWNrIG9uIHRoZSBub3RpZmljYXRpb24gaW4gdGhlPGJy Pgpub3RpZmljYXRpb24gZHJhd2VyIHdlIGRvIE5PVCBnZXQgdGhlIG5vdGlmaWNhdGlvbiBoYW5k bGVyIGNhbGxlZC4gTm90PGJyPgpzbyBnb29kPC9wPgoKPHAgZGlyPSJhdXRvIj5Ib3dldmVyIGl0 IGRvZXMgYXBwZWFyIHRvIHdvcmsgbW9zdCBvZiB0aGUgdGltZSB3aXRoIG91ciBtaW5pbWFsIElv bmljPGJyPgphcHAsIGJ1dCBzb21lIG9mIHRoZSB0aW1lIGl0IGZhaWxzLiBXZSBoYWQgYSBydW4g b2YgMSBpbiAyIGZhaWx1cmVzIHdoZW48YnI+CndlIGNsaWNrIG9uIHRoZSBub3RpZmljYXRpb24u IE5vdyB3ZSBoYXZlIGp1c3QgZG9uZSAyMCBydW5zIGluIGEgcm93LDxicj4KZWFjaCB0aW1lIGtp bGxpbmcgdGhlIGFwcCBhZnRlciByZWNlaXZpbmcgdGhlIG5vdGlmaWNhdGlvbiBhbmQgbm90IGE8 YnI+CnNpbmdsZSBmYWlsdXJlLiBOb3RoaW5nIGNoYW5nZWQuPC9wPgoKPHAgZGlyPSJhdXRvIj5X ZSBjYW5ub3QgZmluZCBhbnkgb2J2aW91cyByZWFzb24gZm9yIHRoaXMgc28gd2UgYXJlIHN0aWxs PGJyPgppbnZlc3RpZ2F0aW5nLjwvcD4KCjxwIGRpcj0iYXV0byI+V2UgaGF2ZSByZWNvbmZpZ3Vy ZWQgb3VyIG1haW4gYXBwIHRvIHdvcmsgdGhlIHNhbWUgd2F5IGFzIHRoZSBtaW5pbWFsPGJyPgph cHAgYnV0IHdlIGFyZSBzdGlsbCBnZXR0aW5nIHRoZSBzYW1lIGlzc3VlcyBhcyBiZWZvcmUsIHdl IGNhbiBzZWUgdGhlPGJyPgpub3RpZmljYXRpb24gaW4gdGhlIGRyYXdlciBidXQgY2xpY2tpbmcg b24gaXQgZG9lcyBOT1QgY2FsbCB0aGUgc2FtZTxicj4KaGFuZGxlciB3aXRoIHRoZSBzYW1lIGNv ZGUgYXMgdGhlIG1pbmltYWwgYXBwLiBXZSBnZXQgemVybyBjYWxscyB0byB0aGU8YnI+Cm5vdGlm aWNhdGlvbiBldmVudCBoYW5kbGVyLjwvcD4KCjxwIGRpcj0iYXV0byI+V2UgYXJlIHdvbmRlcmlu ZyBpZiB0aGVyZSBpcyBhIHRpbWluZyBpc3N1ZSBzb21ld2hlcmUgaW4gb3VyIGNvZGUsIGJ1dDxi cj4Kd2UgY2Fu4oCZdCBzZWUgaXQuIFdlIGFsc28gd29uZGVyZWQgaWYgdGhlIHNpemUgb2YgdGhl IGNvZGUgd2UgYXJlPGJyPgpsb2FkaW5nIGlzIHRoZSBjYXVzZSBvZiBhIHRpbWluZyBpc3N1ZSBh cyB3ZWxsLjwvcD4KCjxwIGRpcj0iYXV0byI+SXMgdGhlcmUgYW55IHdheSBvZiBhZGRpbmcgbW9y ZSBkZWJ1Z2dpbmcgaW50byB0aGUgQWVyb2dlYXIgcHVzaCBwbHVnaW48YnI+CnRvIHNlZSBpZiB3 ZSBjYW4gdHJhY2sgdGhpbmdzIGRvd24gdGhhdCB3YXk/PC9wPgoKPHAgZGlyPSJhdXRvIj5JdHMg dmVyeSBmcnVzdHJhdGluZywgYnV0IHRoYW5rcyBmb3IgeW91ciBoZWxwIHRvIGRhdGUuIEl0IGRv ZXMgbG9vazxicj4KbGlrZSBpdHMgYW4gaW50ZXJhY3Rpb24gd2l0aCBvdXIgY29kZSwgSW9uaWMg YW5kIHRoZSBBZXJvZ2VhciBwbHVnaW4uIE15PGJyPgptb25leSBpcyBvbiBvdXIgY29kZSB0aG91 Z2guIFdl4oCZbGwgbm93IHN0YXJ0IHB1bGxpbmcgd29ya2luZyBjb2RlIG91dDxicj4Kb2Ygb3Vy IGFwcCB1bnRpbCB3ZSBnZXQgYmFjayB0byB0aGUgbWluaW1hbCBhcHAuIE9ubHkgMTgsNjA0IGxp bmVzIHRvIGdvPGJyPgo6KTwvcD4KCjxwIGRpcj0iYXV0byI+Um9iPC9wPgoKPHAgZGlyPSJhdXRv Ij5PbiAxNSBEZWMgMjAxNSwgYXQgMTA6MzYsIEVyaWsgSmFuIGRlIFdpdCB3cm90ZTo8L3A+Cgo8 cCBkaXI9ImF1dG8iPkhpIFJvYiw8L3A+Cgo8cCBkaXI9ImF1dG8iPlRoYXQgd291bGQgYmUgYSBi dWcsIGFsdGhvdWdoIEkgY2FuIG5vdCByZXByb2R1Y2UgaXQsIHRvIHRlc3QgaXQgdGhpczxicj4K aXM8YnI+CndoYXQgSSd2ZSBkb25lIHRvIHRlc3QgaXQ6PGJyPgokICZndDsgY29yZG92YSBjcmVh dGUgcHVzaC10ZXN0ICZsdDtteSBidW5kbGUgaWQmZ3Q7PGJyPgokICZndDsgY29yZG92YSBwbGF0 Zm9ybSBhZGQgaW9zPGJyPgokICZndDsgY29yZG92YSBwbHVnaW4gYWRkIGFlcm9nZWFyLWNvcmRv dmEtcHVzaDwvcD4KCjxwIGRpcj0iYXV0byI+Y29weSBwYXN0ZSB5b3VyIGpzIGNvZGUgaW50byB3 d3cvanMvaW5kZXguanMgb25EZXZpY2VSZWFkeSwgY2hhbmdlZDxicj4KcHVzaFNlcnZlclVybCBh bmQgdmFyaWFudCBpbmZvIGFuZCBjaGFuZ2VkIHF1b3RlcyB0byAiICh0aGlzIGlzIHlvdXI8YnI+ CmVtYWlsPGJyPgpjbGllbnQgbm8gZG91YnQpIGFuZCBjaGFuZ2VkIDogaW50byA7IGFmdGVyIGNv bnNvbGUubG9nKCJTdWNjZXNzIik8L3A+Cgo8cCBkaXI9ImF1dG8iPkF0dGFjaCBTYWZhcmkgZGVi dWdnZXIgYW5kIHNlbmQgYSBtZXNzYWdlIHdoZW4gdGhlIGFwcCBpcyBpbiB0aGU8YnI+CmZvcmVn cm91bmQ8YnI+CmFuZCBnZXQgaW4gdGhlIGNvbnNvbGU6PC9wPgoKPHAgZGlyPSJhdXRvIj5IYW5k bGVBZXJvR2Vhck5vdGlmaWNhdGlvbjogZXZlbnQgPSZndDs8L3A+Cgo8cCBkaXI9ImF1dG8iPnsi YWxlcnQiOiJ0ZXN0IiwiZm9yZWdyb3VuZCI6dHJ1ZSwiY29sZHN0YXJ0IjpmYWxzZSwic291bmQi OiJkZWZhdWx0IiwiYmFkZ2UiOi0xLCJwYXlsb2FkIjp7fX08L3A+Cgo8cCBkaXI9ImF1dG8iPkkg cHJlc3MgdGhlIGhvbWUgYnV0dG9uIGFuZCBzZW5kIHRoZSBhcHAgdG8gdGhlIGJhY2tncm91bmQg c2VuZDxicj4KYW5vdGhlcjxicj4KbWVzc2FnZSBhbmQgJ3RvdWNoJyB0aGUgbWVzc2FnZSB0byBs YXVuY2ggdGhlIGFwcDo8L3A+Cgo8cCBkaXI9ImF1dG8iPkhhbmRsZUFlcm9HZWFyTm90aWZpY2F0 aW9uOiBldmVudCA9Jmd0OzwvcD4KCjxwIGRpcj0iYXV0byI+eyJhbGVydCI6ImJhY2tncm91bmQi LCJmb3JlZ3JvdW5kIjpmYWxzZSwiY29sZHN0YXJ0IjpmYWxzZSwic291bmQiOiJkZWZhdWx0Iiwi YmFkZ2UiOi0xLCJwYXlsb2FkIjp7fX08L3A+Cgo8cCBkaXI9ImF1dG8iPlRoZSBJIGtpbGwgdGhl IGFwcCBieSBwcmVzc2luZyBob21lIHR3aWNlIGFuZCBzd2lwaW5nIG92ZXIgdGhlIGFwcCB0bzxi cj4KcmVtb3ZlIGl0IHNlbmQgYW5vdGhlciBtZXNzYWdlIGFuZCAndG91Y2gnIGl0IHRvIGxhdW5j aCB0aGUgYXBwLiBUaGlzPGJyPgpraWxsczxicj4KbXkgc2FmYXJpIGRlYnVnZ2VyIHNvIG5vIHdh eSB0byBzZWUgdGhlIGNvbnNvbGUgbG9nLCBidXQgaW4gdGhpcyBjYXNlPGJyPgpjb2xkc3RhcnQg c2hvdWxkIGJlIHRydWUuIFRvIHRlc3QgdGhpcyBiZXR0ZXIgY2hhbmdlZCB0aGUgY29kZSB0bzxi cj4KYWxlcnQ8YnI+Cmluc3RlYWQgb2YgY29uc29sZTo8L3A+Cgo8cCBkaXI9ImF1dG8iPmZ1bmN0 aW9uIEhhbmRsZUFlcm9HZWFyTm90aWZpY2F0aW9uKGV2ZW50KSB7PGJyPgphbGVydCgiSGFuZGxl QWVyb0dlYXJOb3RpZmljYXRpb246IGV2ZW50ID0mZ3Q7ICIgKyBldmVudC5jb2xkc3RhcnQpOzwv cD4KCjxwIGRpcj0iYXV0byI+Ly8gU3R1ZmYgY3V0IGZvciBjbGFyaXR5PGJyPgp9PC9wPgoKPHAg ZGlyPSJhdXRvIj5JIHNlbmQgYW5vdGhlciBub3RpZmljYXRpb24gJ3RvdWNoJyBpdCB0byBsYXVu Y2ggdGhlIGFwcCBhbmQgc2VlIHRoZTxicj4KYWxlcnQ8YnI+CmJveCBkaXNwbGF5IHRoZSB0ZXh0 OjwvcD4KCjxwIGRpcj0iYXV0byI+SGFuZGxlQWVyb0dlYXJOb3RpZmljYXRpb246IGV2ZW50ID0m Z3Q7IHRydWU8L3A+Cgo8cCBkaXI9ImF1dG8iPkhvcGUgdGhpcyBoZWxwczwvcD4KCjxwIGRpcj0i YXV0byI+T24gTW9uLCBEZWMgMTQsIDIwMTUgYXQgMTA6MjAgUE0sIFJvYiBXaWxsZXR0ICZsdDs8 YnI+CjxhIGhyZWY9Im1haWx0bzpyb2IuYWVyb2dlYXJAcm9iZXJ0d2lsbGV0dC5jb20iPnJvYi5h ZXJvZ2VhckByb2JlcnR3aWxsZXR0LmNvbTwvYT4mZ3Q7IHdyb3RlOjwvcD4KCjxwIGRpcj0iYXV0 byI+SGksPC9wPgoKPHAgZGlyPSJhdXRvIj5XZSB0aGluayB3ZSBoYXZlIGZvdW5kIGEgcG9zc2li bGUgYnVnIGluIHRoZSBBZXJvZ2VhciBDb3Jkb3ZhIDIuMC40PGJyPgpwdXNoPGJyPgpwbHVnaW4g c3BlY2lmaWNhbGx5IG9uIHRoZSBpT1Mgc2lkZS48YnI+ClN1bW1hcnk8L3A+Cgo8cCBkaXI9ImF1 dG8iPldlIGhhdmUgdHdvIHZlcnNpb25zIG9mIG91ciBhcHAsIGFuIEFuZHJvaWQgYW5kIGFuIElP UyB2ZXJzaW9uLiBCb3RoPGJyPgp1c2U8YnI+CnRoZSBsYXRlc3QgQ29yZG92YSBwdXNoIHBsdWdp biAyLjAuNC4gVGhleSBhbHNvIGJvdGggaGF2ZSB0aGUgbGF0ZXN0PGJyPgpDb3Jkb3ZhIHBsYXRm b3JtcywgYW5kcm9pZCA0LjEuMSwgaW9zIDMuOS4yLiBCb3RoIHRoZSBpT1MgYW5kIEFuZHJvaWQ8 YnI+CnZlcnNpb25zIGFyZSBjb21waWxlZCBhdCB0aGUgc2FtZSB0aW1lLiBXZSBhcmUgcnVubmlu ZyBjb3Jkb3ZhIDUuMy4zPGJyPgp3aXRoPGJyPgpJb25pYyAxLjcuOCAoPykuPC9wPgoKPHAgZGly PSJhdXRvIj4xLjwvcD4KCjxwIGRpcj0iYXV0byI+V2UgbWFrZSBzdXJlIHRoYXQgYm90aCBhcHBz IGFyZSBOT1Qgc3RhcnRlZCB1cCBvbiBlYWNoIGRldmljZS4gV2U8YnI+CmFsc288YnI+CmNoZWNr IHRoZXkgYXJlIE5PVCBpbiB0aGUgYmFja2dyb3VuZC48YnI+CjIuPC9wPgoKPHAgZGlyPSJhdXRv Ij5XZSBzZW5kIHRoZSBzYW1lIHNpbXBsZSBub3RpZmljYXRpb24gdG8gZWFjaCBkZXZpY2UuIFRo aXM8YnI+Cm5vdGlmaWNhdGlvbjxicj4KY29uZmlnIGlzIGFzIGJlbG93LCB3ZSBoYXZlIGFub255 bWlzZWQgdGhlIHZhcmlhbnRzIGFuZCBhbGlhcyBpbiB0aGlzPGJyPgpKU09OPGJyPgpzdHJ1Y3R1 cmUsIHRob3VnaCB3ZSBjYW4gcmVwb3J0IHRoYXQgdGhlIFVQUyBzZXJ2ZXIgc2VuZHMgdGhlIGRh dGE8YnI+CmNvcnJlY3RseS4gV2UgdXNlIHRoZSBhZGRpdGlvbmFsRGF0YSBmbGFnIHRvIHByb3Zp ZGUgdGhlIGluZm9ybWF0aW9uPGJyPgpuZWNlc3NhcnkgdG8gZGVjaWRlIHdoaWNoIG5vdGlmaWNh dGlvbiBoYXMgYmVlbiBjbGlja2VkIGluIHRoZTxicj4Kbm90aWZpY2F0aW9uPGJyPgpkcmF3ZXIu PC9wPgoKPHAgZGlyPSJhdXRvIj4ndmFyaWFudHMnID0mZ3Q7IFvigJh2YXJpYW50MeKAmSzigJl2 YXJpYW50MuKAmSBdLDxicj4KJ21lc3NhZ2UnID0mZ3Q7IHs8YnI+CidhZGRpdGlvbmFsRGF0YScg PSZndDsgeyAnRGlzcnVwdGlvbl9JZCcgPSZndDsgJzEwNzU0NicsPGJyPgonRXBvY2hUaW1lJyA9 Jmd0OyAnMTQ1MDEyNTI2OCc8YnI+Cn0sPGJyPgonYWxlcnQnID0mZ3Q7ICdDYW5ub24gU3RyZWV0 IChFQzROKSAoQWxsIERpcmVjdGlvbnMpIGF0IHRoZSBqdW5jdGlvbiBvZjxicj4KS2luZyBXaWxs aWFtIFN0cmVldCAtIFRvIGZhY2lsaXRhdGUgYSBoZWF2eSBsaWZ0IGluIENhbm5vbiBTdHJlZXQs PGJyPgpDYW5ub24gU3RyZWV0IHdpbGwgYmUgY2xvc2VkLiBUcmFmZmljIGlzIHNsb3cgbW92aW5n IG9uIGRpdmVyc2lvbi4nPGJyPgp9LDxicj4KJ2FsaWFzJyA9Jmd0OyBbIOKAmGFsaWFzMeKAmSBd LDxicj4KJ3R0bCcgPSZndDsgNjAwPGJyPgp9OzwvcD4KCjxwIGRpcj0iYXV0byI+MS48L3A+Cgo8 cCBkaXI9ImF1dG8iPkJvdGggZGV2aWNlcyBzaG93IHRoZSBtZXNzYWdlLCB0aGUgQW5kcm9pZCBk ZXZpY2Ugc3RhY2tzIHRoZSBtZXNzYWdlPGJyPgphbmQgdGhlIGlPUyBkZXZpY2UgZGlzcGxheSBh biBpbmRpdmlkdWFsIG1lc3NhZ2UuIFRoaXMgbG9va3MgY29ycmVjdC48YnI+CjIuPC9wPgoKPHAg ZGlyPSJhdXRvIj5DbGlja2luZyBvbiB0aGUgQW5kcm9pZCBzdGFja2VkIG1lc3NhZ2Ugc3RhcnRz IHVwIHRoZSBhcHAgYW5kIHRoZTxicj4KSmF2YXNjcmlwdCBub3RpZmljYXRpb24gaGFuZGxlciB3 ZSBoYXZlIGRlZmluZWQsPGJyPgpIYW5kbGVBZXJvR2Vhck5vdGlmaWNhdGlvbjxicj4KaXMgY2Fs bGVkPC9wPgoKPHAgZGlyPSJhdXRvIj5IYW5kbGVBZXJvR2Vhck5vdGlmaWNhdGlvbjogZXZlbnQg PSZndDsgeyJhbGVydCI6IkNhbm5vbiBTdHJlZXQgKEVDNE4pPGJyPgooQWxsIERpcmVjdGlvbnMp IGF0IHRoZSBqdW5jdGlvbiBvZiBLaW5nIFdpbGxpYW0gU3RyZWV0IC0gVG88YnI+CmZhY2lsaXRh dGUgYSBoZWF2eSBsaWZ0IGluIENhbm5vbiBTdHJlZXQsIENhbm5vbiBTdHJlZXQgd2lsbCBiZTxi cj4KY2xvc2VkLiBUcmFmZmljIGlzIHNsb3cgbW92aW5nIG9uPC9wPgoKPHAgZGlyPSJhdXRvIj5k aXZlcnNpb24uIiwiY29sZHN0YXJ0Ijp0cnVlLCJmb3JlZ3JvdW5kIjp0cnVlLCJwYXlsb2FkIjp7 ImFsZXJ0IjoiQ2Fubm9uPC9wPgoKPHAgZGlyPSJhdXRvIj5TdHJlZXQgKEVDNE4pIChBbGwgRGly ZWN0aW9ucykgYXQgdGhlIGp1bmN0aW9uIG9mIEtpbmcgV2lsbGlhbSBTdHJlZXQ8YnI+Ci0gVG8g ZmFjaWxpdGF0ZSBhIGhlYXZ5IGxpZnQgaW4gQ2Fubm9uIFN0cmVldCwgQ2Fubm9uIFN0cmVldCB3 aWxsIGJlPGJyPgpjbG9zZWQuIFRyYWZmaWMgaXMgc2xvdyBtb3Zpbmcgb24gZGl2ZXJzaW9uLiIs ImJhZGdlIjoiLTEifX08L3A+Cgo8cCBkaXI9ImF1dG8iPjEuPC9wPgoKPHAgZGlyPSJhdXRvIj5D bGlja2luZyBvbiB0aGUgbm90aWZpY2F0aW9uIGluIHRoZSBub3RpZmljYXRpb24gZHJhd2VyIG9u IHRoZSBpT1M8YnI+CmRldmljZSBhbHNvIHN0YXJ0cyBvdXIgYXBwIHVwIGNvcnJlY3RseSBidXQg dGhlIG5vdGlmaWNhdGlvbiBoYW5kbGVyLDxicj4KSGFuZGxlQWVyb0dlYXJOb3RpZmljYXRpb24o KSwgaXMgTk9UIGNhbGxlZC4gVGhlIGFwcCBzdGFydHMgdXAgYXM8YnI+Cm5vcm1hbCBhczxicj4K aWYgdGhlIG5vdGlmaWNhdGlvbiBoYWQgbm90IGJlZW4gY2xpY2tlZC4gV2Ugd291bGQgZXhwZWN0 IHRoZTxicj4Kbm90aWZpY2F0aW9uPGJyPgpoYW5kbGVyIHRvIGJlIGNhbGxlZCBpbiBpT1MgYXMg aXQgaXMgaW4gQW5kcm9pZC48YnI+CjIuPC9wPgoKPHAgZGlyPSJhdXRvIj5BbGwgbm90aWZpY2F0 aW9ucyBhcmUgY2xlYXJlZCBvbiBib3RoIEFuZHJvaWQgYW5kIGlPUyBjb3JyZWN0bHkgd2hlbjxi cj4KdGhlIGFwcCBpcyBzdGFydGVkIHVwLjxicj4KMy48L3A+Cgo8cCBkaXI9ImF1dG8iPldlIGRl ZmluZSBIYW5kbGVBZXJvR2Vhck5vdGlmaWNhdGlvbiBhczwvcD4KCjxwIGRpcj0iYXV0byI+dmFy IGFlcm9HZWFyUHVzaENvbmZpZyA9IHs8YnI+CnB1c2hTZXJ2ZXJVUkw6ICI8YSBocmVmPSJodHRw czovL3B1c2gtamFtYnVzdGVyLnJoY2xvdWQuY29tL2FnLXB1c2gvIj5odHRwczovL3B1c2gtamFt YnVzdGVyLnJoY2xvdWQuY29tL2FnLXB1c2gvPC9hPiIsPGJyPgppb3M6IHs8YnI+CnZhcmlhbnRJ RDog4oCcdmFyaWFudGlkX29ic2N1cmVk4oCdLDxicj4KdmFyaWFudFNlY3JldDog4oCcdmFyaWFu dF9zZWNyZXRfb2JzY3VyZWTigJ08YnI+Cn0gLDxicj4KYW5kcm9pZDogezxicj4Kc2VuZGVySUQ6 ICJ2YXJpYW50aWRfb2JzY3VyZWQiICw8YnI+CnZhcmlhbnRJRDogInZhcmlhbnRfaWRfb2JzY3Vy ZWQiICw8YnI+CnZhcmlhbnRTZWNyZXQ6ICJ2YXJpYW50X3NlY3JldF9vYnNjdXJlZCI8YnI+Cn0g LDxicj4Kc2VuZE1ldHJpY0luZm86IHRydWUsPGJyPgphbGlhczogYWxpYXMxPGJyPgp9OzwvcD4K CjxwIGRpcj0iYXV0byI+ZnVuY3Rpb24gSGFuZGxlQWVyb0dlYXJOb3RpZmljYXRpb24oZXZlbnQp IHs8YnI+CmNvbnNvbGUubG9nKOKAnEhhbmRsZUFlcm9HZWFyTm90aWZpY2F0aW9uOiBldmVudCA9 Jmd0OyDigJwgKzxicj4KSlNPTi5zdHJpbmdpZnkoZXZlbnQpKTs8L3A+Cgo8cCBkaXI9ImF1dG8i Pi8vIFN0dWZmIGN1dCBmb3IgY2xhcml0eTxicj4KfTwvcD4KCjxwIGRpcj0iYXV0byI+Ly8gU2xp Z2h0bHkgc2ltcGxpZmllZCByZWdpc3RyYXRpb24gZXZlbnQuPGJyPgpwdXNoLnJlZ2lzdGVyKEhh bmRsZUFlcm9HZWFyTm90aWZpY2F0aW9uICwgZnVuY3Rpb24gKCkgezxicj4KY29uc29sZS5sb2co 4oCcU3VjY2Vzc+KAnSk6PGJyPgp9ICwgZnVuY3Rpb24gKCkgezxicj4KY29uc29sZS5sb2co4oCc RmFpbHVyZeKAnSk7PGJyPgp9ICwgYWVyb0dlYXJQdXNoQ29uZmlnKTs8L3A+Cgo8cCBkaXI9ImF1 dG8iPldlIGNhbm5vdCBzZWUgYW55IHJlZmVyZW5jZSB0byB0aGlzIGlzc3VlIGluIHRoZSBKSVJB IGRhdGFiYXNlIGFuZDxicj4Kd29uZGVyZWQgaWYgaXQgaXMgYSBidWcgb3Igbm90LjwvcD4KCjxw IGRpcj0iYXV0byI+SWYgaXRzIGEgYnVnIHdlIGFyZSBoYXBweSB0byByYWlzZSBpdCBhY2NvcmRp bmdseS48L3A+Cgo8cCBkaXI9ImF1dG8iPlBsZWFzZSBsZXQgdXMga25vdyw8L3A+Cgo8cCBkaXI9 ImF1dG8iPlRoYW5rczwvcD4KCjxoMj5Sb2I8L2gyPgoKPHAgZGlyPSJhdXRvIj5BZXJvZ2Vhci11 c2VycyBtYWlsaW5nIGxpc3Q8YnI+CjxhIGhyZWY9Im1haWx0bzpBZXJvZ2Vhci11c2Vyc0BsaXN0 cy5qYm9zcy5vcmciPkFlcm9nZWFyLXVzZXJzQGxpc3RzLmpib3NzLm9yZzwvYT48YnI+CjxhIGhy ZWY9Imh0dHBzOi8vbGlzdHMuamJvc3Mub3JnL21haWxtYW4vbGlzdGluZm8vYWVyb2dlYXItdXNl cnMiPmh0dHBzOi8vbGlzdHMuamJvc3Mub3JnL21haWxtYW4vbGlzdGluZm8vYWVyb2dlYXItdXNl cnM8L2E+PC9wPgoKPHAgZGlyPSJhdXRvIj4tLTxicj4KQ2hlZXJzLDwvcD4KCjxoMj5FcmlrIEph bjwvaDI+Cgo8cCBkaXI9ImF1dG8iPkFlcm9nZWFyLXVzZXJzIG1haWxpbmcgbGlzdDxicj4KPGEg aHJlZj0ibWFpbHRvOkFlcm9nZWFyLXVzZXJzQGxpc3RzLmpib3NzLm9yZyI+QWVyb2dlYXItdXNl cnNAbGlzdHMuamJvc3Mub3JnPC9hPjxicj4KPGEgaHJlZj0iaHR0cHM6Ly9saXN0cy5qYm9zcy5v cmcvbWFpbG1hbi9saXN0aW5mby9hZXJvZ2Vhci11c2VycyI+aHR0cHM6Ly9saXN0cy5qYm9zcy5v cmcvbWFpbG1hbi9saXN0aW5mby9hZXJvZ2Vhci11c2VyczwvYT48L3A+Cgo8aHI+Cgo8cCBkaXI9 ImF1dG8iPkFlcm9nZWFyLXVzZXJzIG1haWxpbmcgbGlzdDxicj4KPGEgaHJlZj0ibWFpbHRvOkFl cm9nZWFyLXVzZXJzQGxpc3RzLmpib3NzLm9yZyI+QWVyb2dlYXItdXNlcnNAbGlzdHMuamJvc3Mu b3JnPC9hPjxicj4KPGEgaHJlZj0iaHR0cHM6Ly9saXN0cy5qYm9zcy5vcmcvbWFpbG1hbi9saXN0 aW5mby9hZXJvZ2Vhci11c2VycyI+aHR0cHM6Ly9saXN0cy5qYm9zcy5vcmcvbWFpbG1hbi9saXN0 aW5mby9hZXJvZ2Vhci11c2VyczwvYT48L3A+Cgo8aHI+Cgo8cCBkaXI9ImF1dG8iPkFlcm9nZWFy LXVzZXJzIG1haWxpbmcgbGlzdDxicj4KPGEgaHJlZj0ibWFpbHRvOkFlcm9nZWFyLXVzZXJzQGxp c3RzLmpib3NzLm9yZyI+QWVyb2dlYXItdXNlcnNAbGlzdHMuamJvc3Mub3JnPC9hPjxicj4KPGEg aHJlZj0iaHR0cHM6Ly9saXN0cy5qYm9zcy5vcmcvbWFpbG1hbi9saXN0aW5mby9hZXJvZ2Vhci11 c2VycyI+aHR0cHM6Ly9saXN0cy5qYm9zcy5vcmcvbWFpbG1hbi9saXN0aW5mby9hZXJvZ2Vhci11 c2VyczwvYT48L3A+Cgo8aHI+Cgo8cCBkaXI9ImF1dG8iPkFlcm9nZWFyLXVzZXJzIG1haWxpbmcg bGlzdDxicj4KPGEgaHJlZj0ibWFpbHRvOkFlcm9nZWFyLXVzZXJzQGxpc3RzLmpib3NzLm9yZyI+ QWVyb2dlYXItdXNlcnNAbGlzdHMuamJvc3Mub3JnPC9hPjxicj4KPGEgaHJlZj0iaHR0cHM6Ly9s aXN0cy5qYm9zcy5vcmcvbWFpbG1hbi9saXN0aW5mby9hZXJvZ2Vhci11c2VycyI+aHR0cHM6Ly9s aXN0cy5qYm9zcy5vcmcvbWFpbG1hbi9saXN0aW5mby9hZXJvZ2Vhci11c2VyczwvYT48L3A+Cjwv YmxvY2txdW90ZT4KCjxwIGRpcj0iYXV0byI+LS0gPGJyPgpDaGVlcnMsPGJyPgpFcmlrIEphbjwv cD4KCjxocj4KCjxwIGRpcj0iYXV0byI+QWVyb2dlYXItdXNlcnMgbWFpbGluZyBsaXN0PGJyPgo8 YSBocmVmPSJtYWlsdG86QWVyb2dlYXItdXNlcnNAbGlzdHMuamJvc3Mub3JnIj5BZXJvZ2Vhci11 c2Vyc0BsaXN0cy5qYm9zcy5vcmc8L2E+PGJyPgo8YSBocmVmPSJodHRwczovL2xpc3RzLmpib3Nz Lm9yZy9tYWlsbWFuL2xpc3RpbmZvL2Flcm9nZWFyLXVzZXJzIj5odHRwczovL2xpc3RzLmpib3Nz Lm9yZy9tYWlsbWFuL2xpc3RpbmZvL2Flcm9nZWFyLXVzZXJzPC9hPjwvcD4KPC9ibG9ja3F1b3Rl PgoKPGhyPgoKPHAgZGlyPSJhdXRvIj5BZXJvZ2Vhci11c2VycyBtYWlsaW5nIGxpc3Q8YnI+Cjxh IGhyZWY9Im1haWx0bzpBZXJvZ2Vhci11c2Vyc0BsaXN0cy5qYm9zcy5vcmciPkFlcm9nZWFyLXVz ZXJzQGxpc3RzLmpib3NzLm9yZzwvYT48YnI+CjxhIGhyZWY9Imh0dHBzOi8vbGlzdHMuamJvc3Mu b3JnL21haWxtYW4vbGlzdGluZm8vYWVyb2dlYXItdXNlcnMiPmh0dHBzOi8vbGlzdHMuamJvc3Mu b3JnL21haWxtYW4vbGlzdGluZm8vYWVyb2dlYXItdXNlcnM8L2E+PC9wPgo8L2Jsb2NrcXVvdGU+ Cgo8aHI+Cgo8cCBkaXI9ImF1dG8iPkFlcm9nZWFyLXVzZXJzIG1haWxpbmcgbGlzdDxicj4KPGEg aHJlZj0ibWFpbHRvOkFlcm9nZWFyLXVzZXJzQGxpc3RzLmpib3NzLm9yZyI+QWVyb2dlYXItdXNl cnNAbGlzdHMuamJvc3Mub3JnPC9hPjxicj4KPGEgaHJlZj0iaHR0cHM6Ly9saXN0cy5qYm9zcy5v cmcvbWFpbG1hbi9saXN0aW5mby9hZXJvZ2Vhci11c2VycyI+aHR0cHM6Ly9saXN0cy5qYm9zcy5v cmcvbWFpbG1hbi9saXN0aW5mby9hZXJvZ2Vhci11c2VyczwvYT48L3A+CjwvYmxvY2txdW90ZT4K CjwvZGl2Pg== --===============3356764396286687352==--