Merge "WifiMetrics: Add wifi passpoint provisioning metrics" into qt-dev
diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java
index 1812c00..125cd09 100644
--- a/service/java/com/android/server/wifi/WifiMetrics.java
+++ b/service/java/com/android/server/wifi/WifiMetrics.java
@@ -31,6 +31,7 @@
 import android.net.wifi.WifiManager.DeviceMobilityState;
 import android.net.wifi.WifiUsabilityStatsEntry.ProbeStatus;
 import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.net.wifi.hotspot2.ProvisioningCallback;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -62,6 +63,8 @@
 import com.android.server.wifi.nano.WifiMetricsProto.LinkProbeStats.LinkProbeFailureReasonCount;
 import com.android.server.wifi.nano.WifiMetricsProto.LinkSpeedCount;
 import com.android.server.wifi.nano.WifiMetricsProto.NetworkSelectionExperimentDecisions;
+import com.android.server.wifi.nano.WifiMetricsProto.PasspointProvisionStats;
+import com.android.server.wifi.nano.WifiMetricsProto.PasspointProvisionStats.ProvisionFailureCount;
 import com.android.server.wifi.nano.WifiMetricsProto.PnoScanMetrics;
 import com.android.server.wifi.nano.WifiMetricsProto.SoftApConnectedClientsEvent;
 import com.android.server.wifi.nano.WifiMetricsProto.StaEvent;
@@ -402,6 +405,12 @@
      */
     private final SparseIntArray mNetworkIdToNominatorId = new SparseIntArray();
 
+    /** passpoint provision success count */
+    private int mNumProvisionSuccess = 0;
+
+    /** Mapping of failure code to the respective passpoint provision failure count. */
+    private final IntCounter mPasspointProvisionFailureCounts = new IntCounter();
+
     @VisibleForTesting
     static class NetworkSelectionExperimentResults {
         public static final int MAX_CHOICES = 10;
@@ -2533,6 +2542,11 @@
                             + mInstalledPasspointProfileType.valueAt(i));
                 }
 
+                pw.println("mWifiLogProto.passpointProvisionStats.numProvisionSuccess="
+                            + mNumProvisionSuccess);
+                pw.println("mWifiLogProto.passpointProvisionStats.provisionFailureCount:"
+                            + mPasspointProvisionFailureCounts);
+
                 pw.println("mWifiLogProto.numRadioModeChangeToMcc="
                         + mWifiLogProto.numRadioModeChangeToMcc);
                 pw.println("mWifiLogProto.numRadioModeChangeToScc="
@@ -3289,6 +3303,21 @@
 
             mWifiLogProto.wifiLockStats = mWifiLockStats;
             mWifiLogProto.wifiToggleStats = mWifiToggleStats;
+
+            /**
+             * Convert the SparseIntArray of passpoint provision failure code
+             * and counts to the proto's repeated IntKeyVal array.
+             */
+            mWifiLogProto.passpointProvisionStats = new PasspointProvisionStats();
+            mWifiLogProto.passpointProvisionStats.numProvisionSuccess = mNumProvisionSuccess;
+            mWifiLogProto.passpointProvisionStats.provisionFailureCount =
+                    mPasspointProvisionFailureCounts.toProto(ProvisionFailureCount.class,
+                            (key, count) -> {
+                                ProvisionFailureCount entry = new ProvisionFailureCount();
+                                entry.failureCode = key;
+                                entry.count = count;
+                                return entry;
+                            });
         }
     }
 
@@ -3471,6 +3500,8 @@
             mWifiLockLowLatencyActiveSessionDurationSecHistogram.clear();
             mWifiLockStats.clear();
             mWifiToggleStats.clear();
+            mPasspointProvisionFailureCounts.clear();
+            mNumProvisionSuccess = 0;
         }
     }
 
@@ -4911,4 +4942,114 @@
             }
         }
     }
+
+    /**
+     * Increment number of passpoint provision failure
+     * @param failureCode indicates error condition
+     */
+    public void incrementPasspointProvisionFailure(int failureCode) {
+        int provisionFailureCode;
+        synchronized (mLock) {
+            switch (failureCode) {
+                case ProvisioningCallback.OSU_FAILURE_AP_CONNECTION:
+                    provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_AP_CONNECTION;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_SERVER_URL_INVALID:
+                    provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_SERVER_URL_INVALID;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_SERVER_CONNECTION:
+                    provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_SERVER_CONNECTION;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_SERVER_VALIDATION:
+                    provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_SERVER_VALIDATION;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION:
+                    provisionFailureCode = PasspointProvisionStats
+                            .OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_PROVISIONING_ABORTED:
+                    provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_PROVISIONING_ABORTED;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE:
+                    provisionFailureCode = PasspointProvisionStats
+                            .OSU_FAILURE_PROVISIONING_NOT_AVAILABLE;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_INVALID_URL_FORMAT_FOR_OSU:
+                    provisionFailureCode = PasspointProvisionStats
+                            .OSU_FAILURE_INVALID_URL_FORMAT_FOR_OSU;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_UNEXPECTED_COMMAND_TYPE:
+                    provisionFailureCode = PasspointProvisionStats
+                            .OSU_FAILURE_UNEXPECTED_COMMAND_TYPE;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE:
+                    provisionFailureCode = PasspointProvisionStats
+                            .OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_SOAP_MESSAGE_EXCHANGE:
+                    provisionFailureCode = PasspointProvisionStats
+                            .OSU_FAILURE_SOAP_MESSAGE_EXCHANGE;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_START_REDIRECT_LISTENER:
+                    provisionFailureCode = PasspointProvisionStats
+                            .OSU_FAILURE_START_REDIRECT_LISTENER;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER:
+                    provisionFailureCode = PasspointProvisionStats
+                            .OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_NO_OSU_ACTIVITY_FOUND:
+                    provisionFailureCode = PasspointProvisionStats
+                            .OSU_FAILURE_NO_OSU_ACTIVITY_FOUND;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS:
+                    provisionFailureCode = PasspointProvisionStats
+                            .OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_NO_PPS_MO:
+                    provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_NO_PPS_MO;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE:
+                    provisionFailureCode = PasspointProvisionStats
+                            .OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE:
+                    provisionFailureCode = PasspointProvisionStats
+                            .OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE:
+                    provisionFailureCode = PasspointProvisionStats
+                            .OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES:
+                    provisionFailureCode = PasspointProvisionStats
+                            .OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE:
+                    provisionFailureCode = PasspointProvisionStats
+                            .OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION:
+                    provisionFailureCode = PasspointProvisionStats
+                            .OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION;
+                    break;
+                case ProvisioningCallback.OSU_FAILURE_OSU_PROVIDER_NOT_FOUND:
+                    provisionFailureCode = PasspointProvisionStats
+                            .OSU_FAILURE_OSU_PROVIDER_NOT_FOUND;
+                    break;
+                default:
+                    provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_UNKNOWN;
+            }
+            mPasspointProvisionFailureCounts.increment(provisionFailureCode);
+        }
+    }
+
+    /**
+     * Increment number of passpoint provision success
+     */
+    public void incrementPasspointProvisionSuccess() {
+        synchronized (mLock) {
+            mNumProvisionSuccess++;
+        }
+    }
 }
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
index df14aa8..ad5cd74 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
@@ -241,7 +241,8 @@
                 mKeyStore, mSimAccessor, new UserDataSourceHandler()));
         wifiConfigStore.registerStoreData(objectFactory.makePasspointConfigSharedStoreData(
                 new SharedDataSourceHandler()));
-        mPasspointProvisioner = objectFactory.makePasspointProvisioner(context, wifiNative, this);
+        mPasspointProvisioner = objectFactory.makePasspointProvisioner(context, wifiNative,
+                this, wifiMetrics);
         sPasspointManager = this;
     }
 
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointObjectFactory.java b/service/java/com/android/server/wifi/hotspot2/PasspointObjectFactory.java
index 20880f2..216a041 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointObjectFactory.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointObjectFactory.java
@@ -23,6 +23,7 @@
 import com.android.server.wifi.Clock;
 import com.android.server.wifi.SIMAccessor;
 import com.android.server.wifi.WifiKeyStore;
+import com.android.server.wifi.WifiMetrics;
 import com.android.server.wifi.WifiNative;
 
 import java.security.KeyStore;
@@ -122,8 +123,8 @@
      * @return {@link PasspointProvisioner}
      */
     public PasspointProvisioner makePasspointProvisioner(Context context, WifiNative wifiNative,
-            PasspointManager passpointManager) {
-        return new PasspointProvisioner(context, wifiNative, this, passpointManager);
+            PasspointManager passpointManager, WifiMetrics wifiMetrics) {
+        return new PasspointProvisioner(context, wifiNative, this, passpointManager, wifiMetrics);
     }
 
     /**
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointProvisioner.java b/service/java/com/android/server/wifi/hotspot2/PasspointProvisioner.java
index bf9e6d3..bdd035f 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointProvisioner.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointProvisioner.java
@@ -35,6 +35,8 @@
 import android.os.UserHandle;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.wifi.WifiMetrics;
 import com.android.server.wifi.WifiNative;
 import com.android.server.wifi.hotspot2.anqp.ANQPElement;
 import com.android.server.wifi.hotspot2.anqp.Constants;
@@ -88,9 +90,12 @@
     private WifiManager mWifiManager;
     private PasspointManager mPasspointManager;
     private Looper mLooper;
+    private final WifiMetrics mWifiMetrics;
 
-    PasspointProvisioner(Context context, WifiNative wifiNative,
-            PasspointObjectFactory objectFactory, PasspointManager passpointManager) {
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public PasspointProvisioner(Context context, WifiNative wifiNative,
+            PasspointObjectFactory objectFactory, PasspointManager passpointManager,
+            WifiMetrics wifiMetrics) {
         mContext = context;
         mOsuNetworkConnection = objectFactory.makeOsuNetworkConnection(context);
         mProvisioningStateMachine = new ProvisioningStateMachine();
@@ -100,6 +105,7 @@
         mSystemInfo = objectFactory.getSystemInfo(context, wifiNative);
         mObjectFactory = objectFactory;
         mPasspointManager = passpointManager;
+        mWifiMetrics = wifiMetrics;
     }
 
     /**
@@ -687,6 +693,7 @@
         }
 
         private void invokeProvisioningCompleteCallback() {
+            mWifiMetrics.incrementPasspointProvisionSuccess();
             if (mProvisioningCallback == null) {
                 Log.e(TAG, "No provisioning complete callback registered");
                 return;
@@ -950,6 +957,7 @@
         }
 
         private void resetStateMachineForFailure(int failureCode) {
+            mWifiMetrics.incrementPasspointProvisionFailure(failureCode);
             invokeProvisioningCallback(PROVISIONING_FAILURE, failureCode);
             resetStateMachine();
         }
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
index b5fee9f..9b9f032 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
@@ -59,6 +59,7 @@
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiSsid;
 import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.net.wifi.hotspot2.ProvisioningCallback;
 import android.net.wifi.hotspot2.pps.Credential;
 import android.os.Handler;
 import android.os.IBinder;
@@ -87,6 +88,7 @@
 import com.android.server.wifi.nano.WifiMetricsProto.LinkProbeStats.LinkProbeFailureReasonCount;
 import com.android.server.wifi.nano.WifiMetricsProto.NetworkSelectionExperimentDecisions;
 import com.android.server.wifi.nano.WifiMetricsProto.PasspointProfileTypeCount;
+import com.android.server.wifi.nano.WifiMetricsProto.PasspointProvisionStats;
 import com.android.server.wifi.nano.WifiMetricsProto.PnoScanMetrics;
 import com.android.server.wifi.nano.WifiMetricsProto.SoftApConnectedClientsEvent;
 import com.android.server.wifi.nano.WifiMetricsProto.StaEvent;
@@ -1258,6 +1260,40 @@
         }
         assertEquals(null, count);
     }
+
+    /**
+     * Test the number of Passpoint provision with the failure code are collected correctly
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testPasspointProvisionMetrics() throws Exception {
+        //Increment count for provisioning success.
+        mWifiMetrics.incrementPasspointProvisionSuccess();
+
+        // Increment count for provisioning unavailable
+        mWifiMetrics.incrementPasspointProvisionFailure(
+                ProvisioningCallback.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE);
+        mWifiMetrics.incrementPasspointProvisionFailure(
+                ProvisioningCallback.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE);
+
+        // Increment count for server connection failure
+        mWifiMetrics.incrementPasspointProvisionFailure(
+                ProvisioningCallback.OSU_FAILURE_AP_CONNECTION);
+
+        // Dump proto and deserialize
+        dumpProtoAndDeserialize();
+
+        assertEquals(mDecodedProto.passpointProvisionStats.numProvisionSuccess, 1);
+        assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount.length, 2);
+        assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[0].failureCode,
+                PasspointProvisionStats.OSU_FAILURE_AP_CONNECTION);
+        assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[0].count, 1);
+        assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[1].failureCode,
+                PasspointProvisionStats.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE);
+        assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[1].count, 2);
+    }
+
     /**
      * Combination of all other WifiMetrics unit tests, an internal-integration test, or functional
      * test
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java
index 8503c45..578a015 100644
--- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java
@@ -192,7 +192,8 @@
         when(mObjectFactory.makeWfaKeyStore()).thenReturn(mWfaKeyStore);
         when(mWfaKeyStore.get()).thenReturn(mKeyStore);
         when(mObjectFactory.makePasspointProvisioner(any(Context.class), any(WifiNative.class),
-                any(PasspointManager.class))).thenReturn(mPasspointProvisioner);
+                any(PasspointManager.class), any(WifiMetrics.class)))
+                .thenReturn(mPasspointProvisioner);
         mManager = new PasspointManager(mContext, mWifiNative, mWifiKeyStore, mClock,
                 mSimAccessor, mObjectFactory, mWifiConfigManager, mWifiConfigStore, mWifiMetrics);
         ArgumentCaptor<PasspointEventHandler.Callbacks> callbacks =
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProvisionerTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProvisionerTest.java
index c83023e..7be5344 100644
--- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProvisionerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProvisionerTest.java
@@ -21,6 +21,7 @@
 import static org.mockito.ArgumentMatchers.anyMap;
 import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
@@ -62,6 +63,7 @@
 
 import com.android.dx.mockito.inline.extended.ExtendedMockito;
 import com.android.org.conscrypt.TrustManagerImpl;
+import com.android.server.wifi.WifiMetrics;
 import com.android.server.wifi.WifiNative;
 import com.android.server.wifi.hotspot2.anqp.ANQPElement;
 import com.android.server.wifi.hotspot2.anqp.Constants;
@@ -191,6 +193,7 @@
     @Mock PasspointConfiguration mPasspointConfiguration;
     @Mock X509Certificate mX509Certificate;
     @Mock SoapSerializationEnvelope mSoapSerializationEnvelope;
+    @Mock WifiMetrics mWifiMetrics;
 
     @Before
     public void setUp() throws Exception {
@@ -217,7 +220,7 @@
         doReturn(mWifiManager).when(mContext)
                 .getSystemService(eq(Context.WIFI_SERVICE));
         mPasspointProvisioner = new PasspointProvisioner(mContext, mWifiNative, mObjectFactory,
-                mPasspointManager);
+                mPasspointManager, mWifiMetrics);
         when(mOsuNetworkConnection.connect(any(WifiSsid.class), any(), any())).thenReturn(true);
         when(mOsuServerConnection.connect(any(URL.class), any(Network.class))).thenReturn(true);
         when(mOsuServerConnection.validateProvider(any(Locale.class),
@@ -404,11 +407,25 @@
                         mOsuServerCallbacks.getSessionId(), trustRootCertificates);
                 mLooper.dispatchAll();
                 verify(mCallback).onProvisioningComplete();
+                // Verify WifiMetrics for provisioning success.
+                verify(mWifiMetrics).incrementPasspointProvisionSuccess();
             }
         }
     }
 
     /**
+     * Verifies provisioning failure state.
+     */
+    private void verifyProvisioningFailure(int failureCode) throws RemoteException {
+        verify(mCallback).onProvisioningFailure(failureCode);
+        // Verify WifiMetrics for provisioning failure.
+        // incrementPasspointProvisionFailure() has to be called only once
+        // and with correct failureCode
+        verify(mWifiMetrics).incrementPasspointProvisionFailure(failureCode);
+        verify(mWifiMetrics).incrementPasspointProvisionFailure(anyInt());
+    }
+
+    /**
      * Verifies initialization and starting subscription provisioning flow.
      */
     @Test
@@ -425,7 +442,7 @@
 
         initAndStartProvisioning();
 
-        verify(mCallback).onProvisioningFailure(
+        verifyProvisioningFailure(
                 ProvisioningCallback.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE);
     }
 
@@ -439,7 +456,7 @@
 
         initAndStartProvisioning();
 
-        verify(mCallback).onProvisioningFailure(
+        verifyProvisioningFailure(
                 ProvisioningCallback.OSU_FAILURE_OSU_PROVIDER_NOT_FOUND);
     }
 
@@ -514,7 +531,7 @@
         assertTrue(mPasspointProvisioner.startSubscriptionProvisioning(
                 TEST_UID, mOsuProvider, mCallback2));
         mLooper.dispatchAll();
-        verify(mCallback).onProvisioningFailure(
+        verifyProvisioningFailure(
                 ProvisioningCallback.OSU_FAILURE_PROVISIONING_ABORTED);
     }
 
@@ -539,7 +556,7 @@
         mLooper.dispatchAll();
 
         // Since creating an instance of RedirectListener, directly move to FAILED_STATE
-        verify(mCallback).onProvisioningFailure(
+        verifyProvisioningFailure(
                 ProvisioningCallback.OSU_FAILURE_START_REDIRECT_LISTENER);
 
         // Failure case, no more runnable posted
@@ -556,7 +573,7 @@
         initAndStartProvisioning();
 
         // Since connection attempt fails, directly move to FAILED_STATE
-        verify(mCallback).onProvisioningFailure(ProvisioningCallback.OSU_FAILURE_AP_CONNECTION);
+        verifyProvisioningFailure(ProvisioningCallback.OSU_FAILURE_AP_CONNECTION);
         // Failure case, no more runnables posted
         verifyNoMoreInteractions(mCallback);
     }
@@ -575,7 +592,7 @@
         mOsuNetworkCallbacks.onDisconnected();
 
         // Move to failed state
-        verify(mCallback).onProvisioningFailure(ProvisioningCallback.OSU_FAILURE_AP_CONNECTION);
+        verifyProvisioningFailure(ProvisioningCallback.OSU_FAILURE_AP_CONNECTION);
         // Failure case, no more runnable posted
         verifyNoMoreInteractions(mCallback);
     }
@@ -591,7 +608,7 @@
         mOsuNetworkCallbacks.onDisconnected();
 
         // Move to failed state
-        verify(mCallback).onProvisioningFailure(ProvisioningCallback.OSU_FAILURE_AP_CONNECTION);
+        verifyProvisioningFailure(ProvisioningCallback.OSU_FAILURE_AP_CONNECTION);
         // No more callbacks, Osu server validation not initiated
         verifyNoMoreInteractions(mCallback);
     }
@@ -607,7 +624,7 @@
         mOsuNetworkCallbacks.onWifiDisabled();
 
         // Wifi Disable is processed first and move to failed state
-        verify(mCallback).onProvisioningFailure(ProvisioningCallback.OSU_FAILURE_AP_CONNECTION);
+        verifyProvisioningFailure(ProvisioningCallback.OSU_FAILURE_AP_CONNECTION);
         // OSU server connection event is not handled
         verifyNoMoreInteractions(mCallback);
     }
@@ -622,7 +639,7 @@
         initAndStartProvisioning();
 
         // Attempting to connect to OSU server fails due to invalid server URL, move to failed state
-        verify(mCallback).onProvisioningFailure(
+        verifyProvisioningFailure(
                 ProvisioningCallback.OSU_FAILURE_SERVER_URL_INVALID);
         // No further runnable posted
         verifyNoMoreInteractions(mCallback);
@@ -638,7 +655,7 @@
         stopAfterStep(STEP_AP_CONNECT);
 
         // Connection to OSU Server fails, move to failed state
-        verify(mCallback).onProvisioningFailure(ProvisioningCallback.OSU_FAILURE_SERVER_CONNECTION);
+        verifyProvisioningFailure(ProvisioningCallback.OSU_FAILURE_SERVER_CONNECTION);
         // No further runnable posted
         verifyNoMoreInteractions(mCallback);
     }
@@ -656,7 +673,7 @@
         mLooper.dispatchAll();
 
         // Server validation failure, move to failed state
-        verify(mCallback).onProvisioningFailure(ProvisioningCallback.OSU_FAILURE_SERVER_VALIDATION);
+        verifyProvisioningFailure(ProvisioningCallback.OSU_FAILURE_SERVER_VALIDATION);
         // No further runnable posted
         verifyNoMoreInteractions(mCallback);
     }
@@ -721,7 +738,7 @@
         mLooper.dispatchAll();
 
         // Provider validation failure is processed next, move to failed state
-        verify(mCallback).onProvisioningFailure(
+        verifyProvisioningFailure(
                 ProvisioningCallback.OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION);
         // No further runnable posted
         verifyNoMoreInteractions(mCallback);
@@ -749,7 +766,7 @@
 
         verify(mCallback).onProvisioningStatus(
                 ProvisioningCallback.OSU_STATUS_SERVER_CONNECTED);
-        verify(mCallback).onProvisioningFailure(
+        verifyProvisioningFailure(
                 ProvisioningCallback.OSU_FAILURE_SOAP_MESSAGE_EXCHANGE);
         // No further runnable posted
         verifyNoMoreInteractions(mCallback);
@@ -785,7 +802,7 @@
                 mSppResponseMessage);
         mLooper.dispatchAll();
 
-        verify(mCallback).onProvisioningFailure(
+        verifyProvisioningFailure(
                 ProvisioningCallback.OSU_FAILURE_NO_OSU_ACTIVITY_FOUND);
         // No further runnable posted
         verifyNoMoreInteractions(mCallback);
@@ -804,7 +821,7 @@
         mLooper.dispatchAll();
 
         verify(mRedirectListener, atLeastOnce()).stopServer(any(Handler.class));
-        verify(mCallback).onProvisioningFailure(
+        verifyProvisioningFailure(
                 ProvisioningCallback.OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER);
         // No further runnable posted
         verifyNoMoreInteractions(mCallback);
@@ -833,7 +850,7 @@
                 mSppResponseMessage);
         mLooper.dispatchAll();
 
-        verify(mCallback).onProvisioningFailure(
+        verifyProvisioningFailure(
                 ProvisioningCallback.OSU_FAILURE_UNEXPECTED_COMMAND_TYPE);
     }
 
@@ -855,7 +872,7 @@
                 mExchangeCompleteMessage);
         mLooper.dispatchAll();
 
-        verify(mCallback).onProvisioningFailure(
+        verifyProvisioningFailure(
                 ProvisioningCallback.OSU_FAILURE_PROVISIONING_ABORTED);
     }
 
@@ -883,7 +900,7 @@
         when(mOsuServerConnection.retrieveTrustRootCerts(anyMap())).thenReturn(false);
         stopAfterStep(STEP_WAIT_FOR_THIRD_SOAP_RESPONSE);
 
-        verify(mCallback).onProvisioningFailure(
+        verifyProvisioningFailure(
                 ProvisioningCallback.OSU_FAILURE_SERVER_CONNECTION);
     }
 
@@ -910,7 +927,7 @@
                 mOsuServerCallbacks.getSessionId(), trustRootCertificates);
         mLooper.dispatchAll();
 
-        verify(mCallback).onProvisioningFailure(
+        verifyProvisioningFailure(
                 ProvisioningCallback.OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION);
     }
 
@@ -932,7 +949,7 @@
                 mOsuServerCallbacks.getSessionId(), trustRootCertificates);
         mLooper.dispatchAll();
 
-        verify(mCallback).onProvisioningFailure(
+        verifyProvisioningFailure(
                 ProvisioningCallback.OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES);
     }
 
@@ -960,7 +977,7 @@
                 mOsuServerCallbacks.getSessionId(), trustRootCertificates);
         mLooper.dispatchAll();
 
-        verify(mCallback).onProvisioningFailure(
+        verifyProvisioningFailure(
                 ProvisioningCallback.OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES);
     }