public async Task <AsyncProvisioningInfoResult> GetProvisioningInfoAsync(
            DiscoveredService discovered,
            WiFiDirectServiceConfigurationMethod configMethod
            )
        {
            WiFiDirectServiceProvisioningInfo provisioningInfo    = null;
            ProvisioningInfoWrapper           provisioningWrapper = null;
            Exception error   = null;
            bool      success = false;

            try
            {
                ThrowIfDisposed();

                WiFiDirectTestLogger.Log(
                    "GetProvisioningInfoAsync... (config method={0}) (Discovery={1})",
                    configMethod.ToString(),
                    discovered.Handle
                    );

                provisioningInfo = await discovered.GetProvisioningInfoAsync(configMethod);

                provisioningWrapper = new ProvisioningInfoWrapper(provisioningInfo);

                success = true;
            }
            catch (Exception ex)
            {
                WiFiDirectTestLogger.Log("Exception in GetProvisioningInfoAsync (this may be expected)");
                error = ex;
            }

            return(new AsyncProvisioningInfoResult(provisioningWrapper, success, error));
        }
        private void ExecuteInternal()
        {
            try
            {
                WiFiDirectTestLogger.Log(
                    "Beginning Connect Scenario from Discovery Handle {0} to Advertiser {1}. GetProvisioning={2}, ValidateData={3}",
                    connectParameters.DiscoveryHandle,
                    connectParameters.AdvertiserHandle,
                    connectParameters.Options.CallGetProvisioningInfo,
                    connectParameters.Options.ValidateData
                    );

                string pin = "";

                // Get the current session counts
                int advertiserCountBefore = advertiserWFDController.GetServiceSessionCount();
                int seekerCountBefore     = seekerWFDController.GetServiceSessionCount();

                // Set any options (like prefer GO)
                // This also calls OpenSession()

                if (connectParameters.Options.DeclineConnect)
                {
                    if (!connectParameters.Options.CallGetProvisioningInfo ||
                        connectParameters.Options.ExpectConnectSuccess)
                    {
                        throw new Exception(String.Format(
                                                CultureInfo.InvariantCulture,
                                                "Bad test case, decline connection should call get provisioning info and expect failure"
                                                ));
                    }

                    advertiserWFDController.DeclineNextServiceConnectionRequest(connectParameters.AdvertiserHandle);
                }

                if (!connectParameters.Options.ExpectAdvertiserConnectSuccess)
                {
                    advertiserWFDController.ExpectNextServiceConnectionRequestFailure(connectParameters.AdvertiserHandle);
                }

                Stopwatch openSessionStopwatch = new Stopwatch();
                openSessionStopwatch.Start();
                seekerWFDController.SetServiceOptions(
                    connectParameters.DiscoveryHandle,
                    connectParameters.Options.PreferGO,
                    connectParameters.Options.SessionInfo
                    );
                openSessionStopwatch.Stop();

                WiFiDirectTestLogger.Log("OpenSession completed in {0} ms.", openSessionStopwatch.ElapsedMilliseconds);

                // Optionally GetProvisioningInfo before doing a PIN connection

                if (connectParameters.Options.CallGetProvisioningInfo)
                {
                    ProvisioningInfoWrapper provisioningInfo = null;
                    Stopwatch provDiscStopwatch = new Stopwatch();
                    // Handle expected failures in GetProvisioningInfo
                    try
                    {
                        provDiscStopwatch.Start();
                        provisioningInfo = seekerWFDController.GetServiceProvisioningInfo(
                            connectParameters.DiscoveryHandle,
                            connectParameters.Options.PreferredConfigMethod
                            );
                    }
                    catch (Exception e)
                    {
                        if (connectParameters.Options.ExpectGetProvisioningSuccess)
                        {
                            throw;
                        }
                        else
                        {
                            WiFiDirectTestLogger.Log("Caught expected exception in GetProvisioningInfo: {0}", e.Message);

                            if (connectParameters.Options.DeclineConnect)
                            {
                                advertiserWFDController.CheckAdvertiserLastSessionDeclined(connectParameters.AdvertiserHandle);
                            }

                            succeeded = true;
                            return;
                        }
                    }
                    finally
                    {
                        provDiscStopwatch.Stop();
                        WiFiDirectTestLogger.Log("GetServiceProvisioningInfo completed in {0} ms.", provDiscStopwatch.ElapsedMilliseconds);

                        if (succeeded && connectParameters.Options.DeclineConnect)
                        {
                            // 30 seconds is much more time than actually needed
                            if (provDiscStopwatch.ElapsedMilliseconds > 30000)
                            {
                                throw new Exception(String.Format(
                                                        CultureInfo.InvariantCulture,
                                                        "Expected decline to fail connect before 2 minute timeout, took too long, decline did not succeed properly"
                                                        ));
                            }
                        }
                    }

                    if (!connectParameters.Options.ExpectGetProvisioningSuccess)
                    {
                        throw new Exception(String.Format(
                                                CultureInfo.InvariantCulture,
                                                "Expected GetProvisioningInfo to fail"
                                                ));
                    }

                    if (provisioningInfo.IsGroupFormationNeeded != connectParameters.Options.ExpectGroupFormationNeeded)
                    {
                        throw new Exception(String.Format(
                                                CultureInfo.InvariantCulture,
                                                "Expected Group Formation {0}, Actual Group Formation {1}",
                                                (connectParameters.Options.ExpectGroupFormationNeeded) ? "Needed" : "Not Needed",
                                                (provisioningInfo.IsGroupFormationNeeded) ? "Needed" : "Not Needed"
                                                ));
                    }

                    if (provisioningInfo.IsGroupFormationNeeded &&
                        provisioningInfo.SelectedConfigMethod != WiFiDirectServiceConfigurationMethod.Default)
                    {
                        if (provisioningInfo.SelectedConfigMethod == WiFiDirectServiceConfigurationMethod.PinDisplay)
                        {
                            // Seeker should have generated a PIN, now advertiser can enter the PIN
                            pin = seekerWFDController.GetServiceDisplayedPin();
                            advertiserWFDController.EnterServicesPin(pin);
                        }
                        else
                        {
                            // Advertiser will generate/display PIN, enter on seeker side before connecting
                            pin = advertiserWFDController.GetServiceDisplayedPin();
                            seekerWFDController.EnterServicesPin(pin);
                        }
                    }
                    WiFiDirectTestLogger.Log("Get Provisioning Info complete, using PIN: {0}", pin);
                }

                // Some tests will validate that this works even if there is a time delay from provisioning info available on seeker to calling connect
                // Add a sleep here if that is the case
                if (connectParameters.Options.DelaySeekerConnectCall)
                {
                    // 5 seconds should be long enough for advertiser to attempt the connect before seeker is ready
                    Task.Delay(5000).Wait();
                }

                // Now do the real connect
                Stopwatch connectStopwatch = new Stopwatch();

                // Handle expected failures in ConnectService
                try
                {
                    connectStopwatch.Start();
                    seekerSessionHandle = seekerWFDController.ConnectService(
                        connectParameters.DiscoveryHandle
                        );
                }
                catch (Exception e)
                {
                    if (connectParameters.Options.ExpectConnectSuccess)
                    {
                        throw;
                    }
                    else
                    {
                        WiFiDirectTestLogger.Log("Caught expected exception in ConnectService: {0}", e.Message);
                        succeeded = true;
                        return;
                    }
                }
                finally
                {
                    connectStopwatch.Stop();
                    WiFiDirectTestLogger.Log("Connect completed in {0} ms.", connectStopwatch.ElapsedMilliseconds);

                    if (!connectParameters.Options.ExpectAdvertiserConnectSuccess)
                    {
                        advertiserWFDController.CheckAdvertiserLastSessionFailed(connectParameters.AdvertiserHandle);
                    }

                    if (succeeded && connectParameters.Options.DeclineConnect)
                    {
                        // 30 seconds is much more time than actually needed
                        if (connectStopwatch.ElapsedMilliseconds > 30000)
                        {
                            throw new Exception(String.Format(
                                                    CultureInfo.InvariantCulture,
                                                    "Expected decline to fail connect before 2 minute timeout, took too long, decline did not succeed properly"
                                                    ));
                        }
                    }
                }

                if (!connectParameters.Options.ExpectConnectSuccess)
                {
                    throw new Exception(String.Format(
                                            CultureInfo.InvariantCulture,
                                            "Expected Connect to fail"
                                            ));
                }

                // Advertiser should have gotten the connection
                advertiserSessionHandle = advertiserWFDController.GetAdvertiserLastSession(
                    connectParameters.AdvertiserHandle,
                    pin.Length == 0 // autoAccept
                    );

                ServiceSessionInfo advertiserSession = advertiserWFDController.GetServiceSessionInfo(advertiserSessionHandle);

                if (advertiserSession.Status != WiFiDirectServiceSessionStatus.Open)
                {
                    throw new Exception(String.Format(
                                            CultureInfo.InvariantCulture,
                                            "Advertiser session is not open (Status={0}, ErrorStatus={1})",
                                            advertiserSession.Status,
                                            advertiserSession.ErrorStatus
                                            ));
                }

                if (connectParameters.Options.SessionInfo.Length > 0 &&
                    connectParameters.Options.SessionInfo != advertiserSession.DeferredSessionInfo)
                {
                    throw new Exception(String.Format(
                                            CultureInfo.InvariantCulture,
                                            "Advertiser and Seeker session info mismatch! (Seeker={0}) (Advertiser={1})",
                                            WiFiDirectTestUtilities.GetTruncatedString(connectParameters.Options.SessionInfo),
                                            WiFiDirectTestUtilities.GetTruncatedString(advertiserSession.DeferredSessionInfo)
                                            ));
                }

                ServiceSessionInfo seekerSession = seekerWFDController.GetServiceSessionInfo(seekerSessionHandle);

                // Compare sessions for correct data
                if (advertiserSession.ServiceName != seekerSession.ServiceName ||
                    advertiserSession.AdvertisementId != seekerSession.AdvertisementId ||
                    advertiserSession.ServiceAddress != seekerSession.ServiceAddress ||
                    advertiserSession.SessionAddress != seekerSession.SessionAddress ||
                    advertiserSession.SessionId != seekerSession.SessionId)
                {
                    throw new Exception(String.Format(
                                            CultureInfo.InvariantCulture,
                                            "Advertiser and Seeker session mismatch! (Seeker={0}) (Advertiser={1})",
                                            seekerSession.ToString(),
                                            advertiserSession.ToString()
                                            ));
                }

                if (connectParameters.Options.ExpectDeferred)
                {
                    seekerWFDController.CheckServiceSessionDeferred(seekerSessionHandle, true);
                    var advertiserInfo = advertiserWFDController.GetAdvertiserInfo(connectParameters.AdvertiserHandle);

                    if (advertiserInfo.DeferredSessionInfo.Length > 0 &&
                        seekerSession.DeferredSessionInfo != advertiserInfo.DeferredSessionInfo)
                    {
                        throw new Exception(String.Format(
                                                CultureInfo.InvariantCulture,
                                                "Advertiser and Seeker deferred session info mismatch! (Seeker={0}) (Advertiser={1})",
                                                WiFiDirectTestUtilities.GetTruncatedString(seekerSession.DeferredSessionInfo),
                                                WiFiDirectTestUtilities.GetTruncatedString(advertiserInfo.DeferredSessionInfo)
                                                ));
                    }
                }
                else
                {
                    seekerWFDController.CheckServiceSessionDeferred(seekerSessionHandle, false);

                    if (seekerSession.DeferredSessionInfo != "")
                    {
                        throw new Exception(String.Format(
                                                CultureInfo.InvariantCulture,
                                                "Seeker Received Deferred Session info, was not deferred session! (Session Info={0})",
                                                WiFiDirectTestUtilities.GetTruncatedString(seekerSession.DeferredSessionInfo)
                                                ));
                    }
                }

                // Check that we added 1 session to each side
                int advertiserCountAfter = advertiserWFDController.GetServiceSessionCount();
                int seekerCountAfter     = seekerWFDController.GetServiceSessionCount();

                if (advertiserCountBefore + 1 != advertiserCountAfter ||
                    seekerCountBefore + 1 != seekerCountAfter)
                {
                    throw new Exception(String.Format(
                                            CultureInfo.InvariantCulture,
                                            "Expected 1 new session on each side! (Seeker {0} -> {1}, Advertiser {2} -> {3})",
                                            seekerCountBefore,
                                            seekerCountAfter,
                                            advertiserCountBefore,
                                            advertiserCountAfter
                                            ));
                }

                if (connectParameters.Options.ValidateData)
                {
                    var dataScenario = new ServicesOpenSocketSendDataScenario(
                        seekerWFDController,
                        advertiserWFDController,
                        new ServicesOpenSocketSendDataParameters(
                            seekerSessionHandle,
                            advertiserSessionHandle,
                            WiFiDirectServiceIPProtocol.Tcp,
                            validationPort++,
                            65536
                            )
                        );

                    validateDataResults = dataScenario.Execute();

                    if (!validateDataResults.ScenarioSucceeded)
                    {
                        throw new Exception("Failed data validation!");
                    }
                }

                succeeded = true;
            }
            catch (Exception e)
            {
                WiFiDirectTestLogger.Error("Caught exception while executing service connect scenario: {0}", e);
            }
        }