Fix unit tests for ActiveModeWarden, ClientModeManager

Fixed/Added unit tests for all the changes required to merge
ScanOnlyModeManager to ClientModeManager. Some tests were removed
because they don't make sense in the new architecture.

Also, fixed a bunch of test comments that were already out of date.

Bug: 128585344
Bug: 127624451
Test: atest com.android.server.wifi
Change-Id: Ifb4397e9ca565408f9e62ad8c8bb4f26ef014076
diff --git a/service/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java b/service/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java
index 83bb1e1..db2f361 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java
@@ -64,8 +64,7 @@
 public class ActiveModeWardenTest extends WifiBaseTest {
     public static final String TAG = "WifiActiveModeWardenTest";
 
-    private static final String CLIENT_MODE_STATE_STRING = "StaEnabledState";
-    private static final String SCAN_ONLY_MODE_STATE_STRING = "StaDisabledWithScanState";
+    private static final String STA_ENABLED_STATE_STRING = "StaEnabledState";
     private static final String STA_DISABLED_STATE_STRING = "StaDisabledState";
 
     private static final String WIFI_IFACE_NAME = "mockWlan";
@@ -78,7 +77,6 @@
     @Mock WifiNative mWifiNative;
     @Mock WifiApConfigStore mWifiApConfigStore;
     @Mock ClientModeManager mClientModeManager;
-    @Mock ScanOnlyModeManager mScanOnlyModeManager;
     @Mock SoftApManager mSoftApManager;
     @Mock DefaultModeManager mDefaultModeManager;
     @Mock IBatteryStats mBatteryStats;
@@ -90,8 +88,8 @@
     @Mock WifiSettingsStore mSettingsStore;
     @Mock WifiPermissionsUtil mWifiPermissionsUtil;
 
-    ClientModeManager.Listener mClientListener;
-    ScanOnlyModeManager.Listener mScanOnlyListener;
+    ActiveModeManager.Listener mClientListener;
+    ActiveModeManager.Listener mSoftApListener;
     WifiManager.SoftApCallback mSoftApManagerCallback;
     SoftApModeConfiguration mSoftApConfig;
     @Mock WifiManager.SoftApCallback mSoftApStateMachineCallback;
@@ -115,7 +113,6 @@
         when(mWifiInjector.getScanRequestProxy()).thenReturn(mScanRequestProxy);
         when(mClientModeManager.getScanMode()).thenReturn(SCAN_WITH_HIDDEN_NETWORKS);
         when(mContext.getResources()).thenReturn(mResources);
-        when(mScanOnlyModeManager.getScanMode()).thenReturn(SCAN_WITHOUT_HIDDEN_NETWORKS);
         when(mSoftApManager.getScanMode()).thenReturn(SCAN_NONE);
 
         when(mResources.getString(R.string.wifi_localhotspot_configure_ssid_default))
@@ -134,22 +131,17 @@
                 mClientListener = (ClientModeManager.Listener) args[0];
                 return mClientModeManager;
             }
-        }).when(mWifiInjector).makeClientModeManager(any(ClientModeManager.Listener.class));
-        doAnswer(new Answer<ScanOnlyModeManager>() {
-            public ScanOnlyModeManager answer(InvocationOnMock invocation) {
-                Object[] args = invocation.getArguments();
-                mScanOnlyListener = (ScanOnlyModeManager.Listener) args[0];
-                return mScanOnlyModeManager;
-            }
-        }).when(mWifiInjector).makeScanOnlyModeManager(any(ScanOnlyModeManager.Listener.class));
+        }).when(mWifiInjector).makeClientModeManager(any(ActiveModeManager.Listener.class));
         doAnswer(new Answer<SoftApManager>() {
             public SoftApManager answer(InvocationOnMock invocation) {
                 Object[] args = invocation.getArguments();
-                mSoftApManagerCallback = (WifiManager.SoftApCallback) args[0];
-                mSoftApConfig = (SoftApModeConfiguration) args[1];
+                mSoftApListener = (ActiveModeManager.Listener) args[0];
+                mSoftApManagerCallback = (WifiManager.SoftApCallback) args[1];
+                mSoftApConfig = (SoftApModeConfiguration) args[2];
                 return mSoftApManager;
             }
-        }).when(mWifiInjector).makeSoftApManager(any(WifiManager.SoftApCallback.class), any());
+        }).when(mWifiInjector).makeSoftApManager(any(ActiveModeManager.Listener.class),
+                any(WifiManager.SoftApCallback.class), any());
 
         mActiveModeWarden = createActiveModeWarden();
         mActiveModeWarden.start();
@@ -191,43 +183,39 @@
     }
 
     /**
-     * Helper method to enter the ClientModeActiveState for ActiveModeWarden.
+     * Helper method to enter the StaEnabledState and set ClientModeManager in ConnectMode.
      */
     private void enterClientModeActiveState() throws Exception {
-        String fromState = mActiveModeWarden.getCurrentMode();
+        when(mClientModeManager.getScanMode()).thenReturn(SCAN_WITH_HIDDEN_NETWORKS);
         when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true);
         mActiveModeWarden.wifiToggled();
         mLooper.dispatchAll();
-        mClientListener.onStateChanged(WifiManager.WIFI_STATE_ENABLED);
+        mClientListener.onStarted();
         mLooper.dispatchAll();
 
-        assertInClientState();
+        assertInStaEnabledState();
         verify(mClientModeManager).start();
-        if (fromState.equals(SCAN_ONLY_MODE_STATE_STRING)) {
-            verify(mScanRequestProxy).enableScanning(false, false);
-        }
+        verify(mClientModeManager).switchToConnectMode();
         verify(mScanRequestProxy).enableScanning(true, true);
         verify(mBatteryStats).noteWifiOn();
     }
 
     /**
-     * Helper method to enter the ScanOnlyModeActiveState for ActiveModeWarden.
+     * Helper method to enter the StaEnabledState and set ClientModeManager in ScanOnlyMode.
      */
     private void enterScanOnlyModeActiveState() throws Exception {
-        String fromState = mActiveModeWarden.getCurrentMode();
+        when(mClientModeManager.getScanMode()).thenReturn(SCAN_WITHOUT_HIDDEN_NETWORKS);
         when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
         when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true);
         when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
         mActiveModeWarden.wifiToggled();
         mLooper.dispatchAll();
-        mScanOnlyListener.onStateChanged(WifiManager.WIFI_STATE_ENABLED);
+        mClientListener.onStarted();
         mLooper.dispatchAll();
 
-        assertInScanOnlyState();
-        verify(mScanOnlyModeManager).start();
-        if (fromState.equals(CLIENT_MODE_STATE_STRING)) {
-            verify(mScanRequestProxy).enableScanning(false, false);
-        }
+        assertInStaEnabledState();
+        verify(mClientModeManager).start();
+        verify(mClientModeManager).switchToScanOnlyMode();
         verify(mScanRequestProxy).enableScanning(true, false);
         verify(mBatteryStats).noteWifiOn();
         verify(mBatteryStats).noteWifiState(BatteryStats.WIFI_STATE_OFF_SCANNING, null);
@@ -239,7 +227,7 @@
     }
 
     /**
-     * Helper method to enter the SoftApActiveMode for ActiveModeWarden.
+     * Helper method to activate SoftApManager.
      *
      * This method puts the test object into the correct state and verifies steps along the way.
      */
@@ -251,8 +239,7 @@
         verify(mSoftApManager).start();
         if (fromState.equals(STA_DISABLED_STATE_STRING)) {
             verify(mBatteryStats).noteWifiOn();
-        } else if (!fromState.equals(SCAN_ONLY_MODE_STATE_STRING)
-                && !fromState.equals(CLIENT_MODE_STATE_STRING)) {
+        } else if (!fromState.equals(STA_ENABLED_STATE_STRING)) {
             verify(mScanRequestProxy, atLeastOnce()).enableScanning(false, false);
         }
     }
@@ -266,8 +253,7 @@
         mLooper.dispatchAll();
 
         assertInStaDisabledState();
-        if (fromState.equals(SCAN_ONLY_MODE_STATE_STRING)
-                || fromState.equals(CLIENT_MODE_STATE_STRING)) {
+        if (fromState.equals(STA_ENABLED_STATE_STRING)) {
             verify(mScanRequestProxy).enableScanning(false, false);
         }
     }
@@ -277,12 +263,8 @@
         mLooper.dispatchAll();
     }
 
-    private void assertInScanOnlyState() {
-        assertThat(mActiveModeWarden.getCurrentMode()).isEqualTo(SCAN_ONLY_MODE_STATE_STRING);
-    }
-
-    private void assertInClientState() {
-        assertThat(mActiveModeWarden.getCurrentMode()).isEqualTo(CLIENT_MODE_STATE_STRING);
+    private void assertInStaEnabledState() {
+        assertThat(mActiveModeWarden.getCurrentMode()).isEqualTo(STA_ENABLED_STATE_STRING);
     }
 
     private void assertInStaDisabledState() {
@@ -403,15 +385,15 @@
                 .isEqualTo(expectedStopInvocationCounts);
     }
 
-    /** Test that after starting up, ActiveModeWarden is in the Disabled State. */
+    /** Test that after starting up, ActiveModeWarden is in the StaDisabled State. */
     @Test
-    public void testWifiDisabledAtStartup() {
+    public void testStaDisabledAtStartup() {
         assertInStaDisabledState();
     }
 
     /**
-     * Test that ActiveModeWarden properly enters the ScanOnlyModeActiveState from the
-     * WifiDisabled state.
+     * Test that ActiveModeWarden properly enters the StaEnabledState (in ScanOnlyMode) from the
+     * StaDisabled state.
      */
     @Test
     public void testEnterScanOnlyModeFromDisabled() throws Exception {
@@ -419,8 +401,8 @@
     }
 
     /**
-     * Test that ActiveModeWarden properly enters the SoftApModeActiveState from the
-     * WifiDisabled state.
+     * Test that ActiveModeWarden properly starts the SoftApManager from the
+     * StaDisabled state.
      */
     @Test
     public void testEnterSoftApModeFromDisabled() throws Exception {
@@ -428,18 +410,18 @@
     }
 
     /**
-     * Test that ActiveModeWarden properly enters the SoftApModeActiveState from another state.
+     * Test that ActiveModeWarden properly starts the SoftApManager from another state.
      */
     @Test
     public void testEnterSoftApModeFromDifferentState() throws Exception {
         enterClientModeActiveState();
-        assertInClientState();
+        assertInStaEnabledState();
         reset(mBatteryStats, mScanRequestProxy);
         enterSoftApActiveMode();
     }
 
     /**
-     * Test that we can disable wifi fully from the ScanOnlyModeActiveState.
+     * Test that we can disable wifi fully from the StaEnabledState (in ScanOnlyMode).
      */
     @Test
     public void testDisableWifiFromScanOnlyModeActiveState() throws Exception {
@@ -449,13 +431,13 @@
         mActiveModeWarden.scanAlwaysModeChanged();
         mLooper.dispatchAll();
 
-        verify(mScanOnlyModeManager).stop();
+        verify(mClientModeManager).stop();
         verify(mBatteryStats).noteWifiOff();
         assertInStaDisabledState();
     }
 
     /**
-     * Test that we can disable wifi from the SoftApModeActiveState and not impact softap.
+     * Test that we can disable wifi when SoftApManager is active and not impact softap.
      */
     @Test
     public void testDisableWifiFromSoftApModeActiveStateDoesNotStopSoftAp() throws Exception {
@@ -469,8 +451,7 @@
     }
 
     /**
-     * Test that we can switch from ScanOnlyActiveMode to another mode.
-     * Expectation: When switching out of ScanOnlyModeActivState we stop the ScanOnlyModeManager.
+     * Test that we can switch from the StaEnabledState (in ScanOnlyMode) to another mode.
      */
     @Test
     public void testSwitchModeWhenScanOnlyModeActiveState() throws Exception {
@@ -479,12 +460,12 @@
         reset(mBatteryStats, mScanRequestProxy);
         enterClientModeActiveState();
         mLooper.dispatchAll();
-        verify(mScanOnlyModeManager).stop();
-        assertInClientState();
+        verify(mClientModeManager).switchToConnectMode();
+        assertInStaEnabledState();
     }
 
     /**
-     * Reentering ClientModeActiveState should be a NOP.
+     * Reentering StaEnabledState should be a NOP.
      */
     @Test
     public void testReenterClientModeActiveStateIsNop() throws Exception {
@@ -497,8 +478,7 @@
     }
 
     /**
-     * Test that we can switch from SoftApActiveMode to another mode.
-     * Expectation: When switching out of SoftApModeActiveState we do not impact softap operation
+     * Test that we can switch mode when SoftApManager is active to another mode.
      */
     @Test
     public void testSwitchModeWhenSoftApActiveMode() throws Exception {
@@ -509,21 +489,19 @@
         enterClientModeActiveState();
         mLooper.dispatchAll();
         verify(mSoftApManager, never()).stop();
-        assertInClientState();
+        assertInStaEnabledState();
         verify(mWifiNative, never()).teardownAllInterfaces();
     }
 
     /**
-     * Test that we do enter the SoftApModeActiveState if we are already in WifiDisabledState due to
+     * Test that we activate SoftApModeManager if we are already in StaDisabledState due to
      * a failure.
-     * Expectations: We should exit the current WifiDisabledState and re-enter before successfully
-     * entering the SoftApModeActiveState.
      */
     @Test
     public void testEnterSoftApModeActiveWhenAlreadyInSoftApMode() throws Exception {
         enterSoftApActiveMode();
         // now inject failure through the SoftApManager.Listener
-        mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, 0);
+        mSoftApListener.onStartFailure();
         mLooper.dispatchAll();
         assertInStaDisabledState();
         // clear the first call to start SoftApManager
@@ -533,64 +511,59 @@
     }
 
     /**
-     * Test that we return to the WifiDisabledState after a failure is reported when in the
-     * ScanOnlyModeActiveState.
-     * Expectations: we should exit the ScanOnlyModeActiveState and stop the ScanOnlyModeManager.
+     * Test that we return to the StaDisabledState after a failure is reported when in the
+     * StaEnabledState.
      */
     @Test
     public void testScanOnlyModeFailureWhenActive() throws Exception {
         enterScanOnlyModeActiveState();
         // now inject a failure through the ScanOnlyModeManager.Listener
-        mScanOnlyListener.onStateChanged(WifiManager.WIFI_STATE_UNKNOWN);
+        mClientListener.onStartFailure();
         mLooper.dispatchAll();
         assertInStaDisabledState();
-        verify(mScanOnlyModeManager).stop();
+        verify(mClientModeManager).stop();
         verify(mBatteryStats).noteWifiOff();
     }
 
     /**
-     * Test that we return to the WifiDisabledState after a failure is reported when in the
-     * SoftApModeActiveState.
-     * Expectations: We should exit the SoftApModeActiveState and stop the SoftApManager.
+     * Test that we return to the StaDisabledState after a failure is reported when
+     * SoftApManager is active.
      */
     @Test
     public void testSoftApFailureWhenActive() throws Exception {
         enterSoftApActiveMode();
         // now inject failure through the SoftApManager.Listener
-        mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, 0);
+        mSoftApListener.onStartFailure();
         mLooper.dispatchAll();
         verify(mBatteryStats).noteWifiOff();
     }
 
     /**
-     * Test that we return to the WifiDisabledState after the ScanOnlyModeManager is stopping in the
-     * ScanOnlyModeActiveState.
-     * Expectations: We should exit the ScanOnlyModeActiveState and stop the ScanOnlyModeManager.
+     * Test that we return to the DisabledState after the ClientModeManager running in ScanOnlyMode
+     * is stopped.
      */
     @Test
     public void testScanOnlyModeDisabledWhenActive() throws Exception {
         enterScanOnlyModeActiveState();
 
         // now inject the stop message through the ScanOnlyModeManager.Listener
-        mScanOnlyListener.onStateChanged(WifiManager.WIFI_STATE_DISABLED);
+        mClientListener.onStopped();
         mLooper.dispatchAll();
 
         assertInStaDisabledState();
-        verify(mScanOnlyModeManager).stop();
+        verify(mClientModeManager).stop();
         verify(mBatteryStats).noteWifiOff();
     }
 
     /**
-     * Test that we return to the WifiDisabledState after the SoftApManager is stopped in the
-     * SoftApModeActiveState.
-     * Expectations: We should exit the SoftApModeActiveState and stop the SoftApManager.
+     * Test that we return to the StaDisabledState after the SoftApManager is stopped.
      */
     @Test
     public void testSoftApDisabledWhenActive() throws Exception {
         enterSoftApActiveMode();
         reset(mWifiNative);
         // now inject failure through the SoftApManager.Listener
-        mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, 0);
+        mSoftApListener.onStartFailure();
         mLooper.dispatchAll();
         verify(mBatteryStats).noteWifiOff();
         verifyNoMoreInteractions(mWifiNative);
@@ -603,6 +576,7 @@
     public void callsWifiServiceCallbackOnSoftApStateChanged() throws Exception {
         enterSoftApActiveMode();
 
+        mSoftApListener.onStarted();
         mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_ENABLED, 0);
         mLooper.dispatchAll();
 
@@ -618,6 +592,7 @@
         enterSoftApActiveMode(new SoftApModeConfiguration(
                 WifiManager.IFACE_IP_MODE_LOCAL_ONLY, null));
 
+        mSoftApListener.onStarted();
         mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_ENABLED, 0);
         mLooper.dispatchAll();
 
@@ -661,7 +636,6 @@
      */
     @Test
     public void testNullCallbackToWifiServiceImplForNumClientsChanged() throws Exception {
-
         final int testNumClients = 3;
 
         //set the callback to null
@@ -676,37 +650,20 @@
     /**
      * Test that we remain in the active state when we get a state change update that scan mode is
      * active.
-     * Expectations: We should remain in the ScanOnlyModeActive state.
      */
     @Test
     public void testScanOnlyModeStaysActiveOnEnabledUpdate() throws Exception {
         enterScanOnlyModeActiveState();
-        // now inject failure through the SoftApManager.Listener
-        mScanOnlyListener.onStateChanged(WifiManager.WIFI_STATE_ENABLED);
+        // now inject success through the Listener
+        mClientListener.onStarted();
         mLooper.dispatchAll();
-        assertInScanOnlyState();
-        verify(mScanOnlyModeManager, never()).stop();
-    }
-
-    /**
-     * Test that we do not act on unepected state string messages and remain in the active state.
-     * Expectations: We should remain in the ScanOnlyModeActive state.
-     */
-    @Test
-    public void testScanOnlyModeStaysActiveOnUnexpectedStateUpdate() throws Exception {
-        enterScanOnlyModeActiveState();
-        // now inject failure through the SoftApManager.Listener
-        mScanOnlyListener.onStateChanged(WifiManager.WIFI_AP_STATE_DISABLING);
-        mLooper.dispatchAll();
-        assertInScanOnlyState();
-        verify(mScanOnlyModeManager, never()).stop();
+        assertInStaEnabledState();
+        verify(mClientModeManager, never()).stop();
     }
 
     /**
      * Test that a config passed in to the call to enterSoftApMode is used to create the new
      * SoftApManager.
-     * Expectations: We should create a SoftApManager in WifiInjector with the config passed in to
-     * ActiveModeWarden to switch to SoftApMode.
      */
     @Test
     public void testConfigIsPassedToWifiInjector() throws Exception {
@@ -722,8 +679,6 @@
      * WifiInjector.makeSoftApManager.
      *
      * Passing a null config to SoftApManager indicates that the default config should be used.
-     *
-     * Expectations: WifiInjector should be called with a null config.
      */
     @Test
     public void testNullConfigIsPassedToWifiInjector() throws Exception {
@@ -747,12 +702,14 @@
         SoftApModeConfiguration softApConfig2 =
                 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, config2);
 
-        when(mWifiInjector.makeSoftApManager(any(WifiManager.SoftApCallback.class),
+        when(mWifiInjector.makeSoftApManager(any(ActiveModeManager.Listener.class),
+                                             any(WifiManager.SoftApCallback.class),
                                              eq(softApConfig1)))
                 .thenReturn(mSoftApManager);
         // make a second softap manager
         SoftApManager softapManager = mock(SoftApManager.class);
-        when(mWifiInjector.makeSoftApManager(any(WifiManager.SoftApCallback.class),
+        when(mWifiInjector.makeSoftApManager(any(ActiveModeManager.Listener.class),
+                                             any(WifiManager.SoftApCallback.class),
                                              eq(softApConfig2)))
                 .thenReturn(softapManager);
 
@@ -766,8 +723,6 @@
 
     /**
      * Test that we safely disable wifi if it is already disabled.
-     * Expectations: We should not interact with WifiNative since we should have already cleaned up
-     * everything.
      */
     @Test
     public void disableWifiWhenAlreadyOff() throws Exception {
@@ -806,7 +761,7 @@
     public void shutdownWifiDoesNotCrashWhenClientModeExitsOnDestroyed() throws Exception {
         enterClientModeActiveState();
 
-        mClientListener.onStateChanged(WifiManager.WIFI_STATE_DISABLED);
+        mClientListener.onStopped();
         mLooper.dispatchAll();
 
         shutdownWifi();
@@ -823,7 +778,7 @@
 
         shutdownWifi();
 
-        mClientListener.onStateChanged(WifiManager.WIFI_STATE_DISABLED);
+        mClientListener.onStopped();
         mLooper.dispatchAll();
 
         assertInStaDisabledState();
@@ -836,6 +791,7 @@
     public void shutdownWifiDoesNotCrashWhenSoftApExitsOnDestroyed() throws Exception {
         enterSoftApActiveMode();
 
+        mSoftApListener.onStopped();
         mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0);
         mLooper.dispatchAll();
 
@@ -853,6 +809,7 @@
 
         shutdownWifi();
 
+        mSoftApListener.onStopped();
         mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0);
         mLooper.dispatchAll();
 
@@ -884,9 +841,7 @@
         mActiveModeWarden.dump(null, writer, null);
 
         verify(mSoftApManager).dump(null, writer, null);
-        // can only be in scan or client, so we should not have a client mode active
-        verify(mClientModeManager, never()).dump(null, writer, null);
-        verify(mScanOnlyModeManager).dump(null, writer, null);
+        verify(mClientModeManager).dump(null, writer, null);
     }
 
     /**
@@ -905,12 +860,14 @@
 
         // mock SoftAPManagers
         when(mSoftApManager.getIpMode()).thenReturn(WifiManager.IFACE_IP_MODE_TETHERED);
-        when(mWifiInjector.makeSoftApManager(any(WifiManager.SoftApCallback.class),
+        when(mWifiInjector.makeSoftApManager(any(ActiveModeManager.Listener.class),
+                                             any(WifiManager.SoftApCallback.class),
                                              eq(tetherConfig)))
                 .thenReturn(mSoftApManager);
         SoftApManager lohsSoftapManager = mock(SoftApManager.class);
         when(lohsSoftapManager.getIpMode()).thenReturn(WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
-        when(mWifiInjector.makeSoftApManager(any(WifiManager.SoftApCallback.class),
+        when(mWifiInjector.makeSoftApManager(any(ActiveModeManager.Listener.class),
+                                             any(WifiManager.SoftApCallback.class),
                                              eq(lohsConfig)))
                 .thenReturn(lohsSoftapManager);
 
@@ -940,7 +897,7 @@
         mActiveModeWarden.wifiToggled();
         mLooper.dispatchAll();
 
-        assertInClientState();
+        assertInStaEnabledState();
     }
 
     /**
@@ -951,9 +908,10 @@
         when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true);
         mActiveModeWarden.scanAlwaysModeChanged();
         mLooper.dispatchAll();
-        verify(mScanOnlyModeManager).start();
-        assertInScanOnlyState();
-        verify(mScanOnlyModeManager, never()).stop();
+        verify(mClientModeManager).start();
+        verify(mClientModeManager).switchToScanOnlyMode();
+        assertInStaEnabledState();
+        verify(mClientModeManager, never()).stop();
     }
 
     /**
@@ -967,7 +925,7 @@
         mActiveModeWarden.start();
         mLooper.dispatchAll();
 
-        assertInScanOnlyState();
+        assertInStaEnabledState();
     }
 
     /**
@@ -981,7 +939,10 @@
         mActiveModeWarden.start();
         mLooper.dispatchAll();
 
-        assertInClientState();
+        assertInStaEnabledState();
+
+        verify(mClientModeManager).start();
+        verify(mClientModeManager).switchToConnectMode();
     }
 
     /**
@@ -990,7 +951,6 @@
     @Test
     public void testDoesNotEnterScanModeWhenLocationModeDisabled() throws Exception {
         // Start a new WifiController with wifi disabled
-        when(mSettingsStore.isAirplaneModeOn()).thenReturn(false);
         when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
         when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false);
         when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false);
@@ -1035,7 +995,7 @@
         broadcastReceiver.onReceive(mContext, intent);
         mLooper.dispatchAll();
 
-        assertInScanOnlyState();
+        assertInStaEnabledState();
     }
 
 
@@ -1058,7 +1018,7 @@
         verify(mContext).registerReceiver(bcastRxCaptor.capture(), any(IntentFilter.class));
         BroadcastReceiver broadcastReceiver = bcastRxCaptor.getValue();
 
-        assertInScanOnlyState();
+        assertInStaEnabledState();
 
         when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false);
         Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION);
@@ -1110,7 +1070,7 @@
     @Test
     public void testEcmDisabledReturnsToClientMode() throws Exception {
         enableWifi();
-        assertInClientState();
+        assertInStaEnabledState();
 
         // Test with WifiDisableInECBM turned on:
         when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true);
@@ -1125,7 +1085,7 @@
         mActiveModeWarden.emergencyCallbackModeChanged(false);
         mLooper.dispatchAll();
 
-        assertInClientState();
+        assertInStaEnabledState();
     }
 
     /**
@@ -1138,7 +1098,7 @@
         mActiveModeWarden.scanAlwaysModeChanged();
         mLooper.dispatchAll();
 
-        assertInScanOnlyState();
+        assertInStaEnabledState();
 
         // Test with WifiDisableInECBM turned on:
         when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true);
@@ -1160,7 +1120,7 @@
         mActiveModeWarden.scanAlwaysModeChanged();
         mLooper.dispatchAll();
 
-        assertInScanOnlyState();
+        assertInStaEnabledState();
 
         // Test with WifiDisableInECBM turned off:
         when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(false);
@@ -1181,7 +1141,7 @@
         mActiveModeWarden.scanAlwaysModeChanged();
         mLooper.dispatchAll();
 
-        assertInScanOnlyState();
+        assertInStaEnabledState();
 
         // Test with WifiDisableInECBM turned on:
         when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true);
@@ -1196,7 +1156,7 @@
         mActiveModeWarden.emergencyCallbackModeChanged(false);
         mLooper.dispatchAll();
 
-        assertInScanOnlyState();
+        assertInStaEnabledState();
     }
 
     /**
@@ -1275,7 +1235,6 @@
         assertInStaDisabledState();
         verify(mSoftApManager, never()).start();
         verify(mClientModeManager, never()).start();
-        verify(mScanOnlyModeManager, never()).start();
 
         // Test with WifiDisableInECBM turned on:
         when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true);
@@ -1296,7 +1255,7 @@
         assertInStaDisabledState();
 
         enableWifi();
-        assertInClientState();
+        assertInStaEnabledState();
 
         // Test with WifiDisableInECBM turned on:
         when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true);
@@ -1310,7 +1269,7 @@
         mActiveModeWarden.emergencyCallStateChanged(false);
         mLooper.dispatchAll();
 
-        assertInClientState();
+        assertInStaEnabledState();
     }
 
     /**
@@ -1321,7 +1280,7 @@
         assertInStaDisabledState();
 
         enableWifi();
-        assertInClientState();
+        assertInStaEnabledState();
 
         // Test with WifiDisableInECBM turned on:
         when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true);
@@ -1345,7 +1304,7 @@
         // stay in ecm, do not send an additional client mode trigger
         assertInEmergencyMode();
         // assert that the underlying state is still client state
-        assertInClientState();
+        assertInStaEnabledState();
         // client mode still only started once
         verify(mClientModeManager).start();
 
@@ -1354,7 +1313,7 @@
 
         // now we can re-enable wifi
         verify(mClientModeManager, times(2)).start();
-        assertInClientState();
+        assertInStaEnabledState();
     }
 
     /**
@@ -1366,7 +1325,7 @@
 
         enableWifi();
 
-        assertInClientState();
+        assertInStaEnabledState();
         verify(mClientModeManager).start();
 
         // Test with WifiDisableInECBM turned on:
@@ -1376,7 +1335,7 @@
             mActiveModeWarden.emergencyCallbackModeChanged(true);
             mLooper.dispatchAll();
         });
-        assertInClientState();
+        assertInStaEnabledState();
 
         assertEnteredEcmMode(() -> {
             mActiveModeWarden.emergencyCallStateChanged(true);
@@ -1388,14 +1347,14 @@
 
         // stay in ecm, do not send an additional client mode trigger
         verify(mClientModeManager).start();
-        assertInClientState();
+        assertInStaEnabledState();
 
         mActiveModeWarden.emergencyCallbackModeChanged(false);
         mLooper.dispatchAll();
 
         // now we can re-enable wifi
         verify(mClientModeManager, times(2)).start();
-        assertInClientState();
+        assertInStaEnabledState();
     }
 
     /**
@@ -1408,7 +1367,7 @@
 
         enableWifi();
 
-        assertInClientState();
+        assertInStaEnabledState();
         verify(mClientModeManager).start();
 
         // Test with WifiDisableInECBM turned on:
@@ -1418,7 +1377,7 @@
             mActiveModeWarden.emergencyCallStateChanged(true);
             mLooper.dispatchAll();
         });
-        assertInClientState();
+        assertInStaEnabledState();
 
         assertEnteredEcmMode(() -> {
             mActiveModeWarden.emergencyCallbackModeChanged(true);
@@ -1430,14 +1389,14 @@
 
         // stay in ecm, do not send an additional client mode trigger
         verify(mClientModeManager).start();
-        assertInClientState();
+        assertInStaEnabledState();
 
         mActiveModeWarden.emergencyCallStateChanged(false);
         mLooper.dispatchAll();
 
         // now we can re-enable wifi
         verify(mClientModeManager, times(2)).start();
-        assertInClientState();
+        assertInStaEnabledState();
     }
 
     /**
@@ -1454,7 +1413,7 @@
         enableWifi();
 
         verify(mClientModeManager).start();
-        assertInClientState();
+        assertInStaEnabledState();
 
         // Test with WifiDisableInECBM turned on:
         when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true);
@@ -1467,7 +1426,7 @@
             mActiveModeWarden.emergencyCallbackModeChanged(true);
             mLooper.dispatchAll();
         });
-        assertInClientState();
+        assertInStaEnabledState();
 
         assertEnteredEcmMode(() -> {
             mActiveModeWarden.emergencyCallbackModeChanged(false);
@@ -1482,7 +1441,7 @@
 
         // didn't enter client mode again
         verify(mClientModeManager).start();
-        assertInClientState();
+        assertInStaEnabledState();
 
         // now we will exit ECM
         mActiveModeWarden.emergencyCallStateChanged(false);
@@ -1490,7 +1449,7 @@
 
         // now we can re-enable wifi
         verify(mClientModeManager, times(2)).start();
-        assertInClientState();
+        assertInStaEnabledState();
     }
 
     /**
@@ -1544,7 +1503,7 @@
         mActiveModeWarden.scanAlwaysModeChanged();
         mLooper.dispatchAll();
 
-        verify(mScanOnlyModeManager, never()).start();
+        verify(mClientModeManager, never()).start();
         assertInStaDisabledState();
     }
 
@@ -1591,7 +1550,7 @@
         mLooper.dispatchAll();
 
         assertInStaDisabledState();
-        verifyNoMoreInteractions(mSoftApManager, mClientModeManager, mScanOnlyModeManager);
+        verifyNoMoreInteractions(mSoftApManager, mClientModeManager);
     }
 
     /**
@@ -1621,7 +1580,7 @@
     @Test
     public void testScanModeStoppedDoesNotSwitchModesWhenInEcm() throws Exception {
         enterScanOnlyModeActiveState();
-        assertInScanOnlyState();
+        assertInStaEnabledState();
 
         // Test with WifiDisableInECBM turned on:
         when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true);
@@ -1631,10 +1590,10 @@
             mLooper.dispatchAll();
         });
 
-        mScanOnlyListener.onStateChanged(WifiManager.WIFI_STATE_DISABLED);
+        mClientListener.onStopped();
         mLooper.dispatchAll();
 
-        assertInScanOnlyState();
+        assertInStaEnabledState();
     }
 
     /**
@@ -1643,7 +1602,7 @@
     @Test
     public void testClientModeStoppedDoesNotSwitchModesWhenInEcm() throws Exception {
         enterClientModeActiveState();
-        assertInClientState();
+        assertInStaEnabledState();
 
         // Test with WifiDisableInECBM turned on:
         when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true);
@@ -1653,10 +1612,10 @@
             mLooper.dispatchAll();
         });
 
-        mClientListener.onStateChanged(WifiManager.WIFI_STATE_DISABLED);
+        mClientListener.onStopped();
         mLooper.dispatchAll();
 
-        assertInClientState();
+        assertInStaEnabledState();
     }
 
     /**
@@ -1669,21 +1628,20 @@
     @Test
     public void testReturnToStaEnabledStateAfterAPModeShutdown() throws Exception {
         enableWifi();
-        assertInClientState();
+        assertInStaEnabledState();
         verify(mClientModeManager).start();
 
         mActiveModeWarden.startSoftAp(
                 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null));
         // add an "unexpected" sta mode stop to simulate a single interface device
-        mClientListener.onStateChanged(WifiManager.WIFI_STATE_DISABLED);
+        mClientListener.onStopped();
         mLooper.dispatchAll();
 
-        when(mSettingsStore.getWifiSavedState()).thenReturn(1);
         mActiveModeWarden.softApStopped();
         mLooper.dispatchAll();
 
         verify(mClientModeManager, times(2)).start();
-        assertInClientState();
+        assertInStaEnabledState();
     }
 
     /**
@@ -1699,7 +1657,7 @@
     @Test
     public void testReturnToStaEnabledStateAfterWifiEnabledShutdown() throws Exception {
         enableWifi();
-        assertInClientState();
+        assertInStaEnabledState();
         verify(mClientModeManager).start();
 
         mActiveModeWarden.startSoftAp(
@@ -1713,7 +1671,7 @@
 
         // wasn't called again
         verify(mClientModeManager).start();
-        assertInClientState();
+        assertInStaEnabledState();
     }
 
     @Test
@@ -1738,7 +1696,7 @@
     @Test
     public void testRecoveryDisabledTurnsWifiOff() throws Exception {
         enableWifi();
-        assertInClientState();
+        assertInStaEnabledState();
         mActiveModeWarden.recoveryDisableWifi();
         mLooper.dispatchAll();
         verify(mClientModeManager).stop();
@@ -1774,7 +1732,7 @@
         mLooper.dispatchAll();
 
         assertInStaDisabledState();
-        verifyNoMoreInteractions(mScanOnlyModeManager, mClientModeManager, mSoftApManager);
+        verifyNoMoreInteractions(mClientModeManager, mSoftApManager);
     }
 
     /**
@@ -1795,20 +1753,22 @@
         mActiveModeWarden.scanAlwaysModeChanged();
         mLooper.dispatchAll();
 
-        assertInScanOnlyState();
-        verify(mScanOnlyModeManager).start();
+        assertInStaEnabledState();
+        verify(mClientModeManager).start();
+        verify(mClientModeManager).switchToScanOnlyMode();
 
         mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE);
         mLooper.dispatchAll();
 
-        verify(mScanOnlyModeManager).stop();
+        verify(mClientModeManager).stop();
         assertInStaDisabledState();
 
         mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS);
         mLooper.dispatchAll();
 
-        verify(mScanOnlyModeManager, times(2)).start();
-        assertInScanOnlyState();
+        verify(mClientModeManager, times(2)).start();
+        verify(mClientModeManager, times(2)).switchToScanOnlyMode();
+        assertInStaEnabledState();
     }
 
     /**
@@ -1824,7 +1784,7 @@
     @Test
     public void testRestartWifiStackInStaEnabledState() throws Exception {
         enableWifi();
-        assertInClientState();
+        assertInStaEnabledState();
         verify(mClientModeManager).start();
 
         assertWifiShutDown(() -> {
@@ -1840,7 +1800,7 @@
 
         // started again
         verify(mClientModeManager, times(2)).start();
-        assertInClientState();
+        assertInStaEnabledState();
     }
 
     /**
@@ -1853,15 +1813,16 @@
     @Test
     public void testRestartWifiStackDoesNotExitECMMode() throws Exception {
         enableWifi();
-        assertInClientState();
+        assertInStaEnabledState();
         verify(mClientModeManager).start();
+        verify(mClientModeManager).switchToConnectMode();
 
         when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true);
         assertEnteredEcmMode(() -> {
             mActiveModeWarden.emergencyCallStateChanged(true);
             mLooper.dispatchAll();
         });
-        assertInClientState();
+        assertInStaEnabledState();
         verify(mClientModeManager).stop();
 
         mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_LAST_RESORT_WATCHDOG);
@@ -1869,8 +1830,8 @@
 
         verify(mClientModeManager).start(); // wasn't called again
         assertInEmergencyMode();
-        assertInClientState();
-        verifyNoMoreInteractions(mScanOnlyModeManager, mClientModeManager, mSoftApManager);
+        assertInStaEnabledState();
+        verifyNoMoreInteractions(mClientModeManager, mSoftApManager);
     }
 
     /**
@@ -1909,7 +1870,7 @@
         mLooper.dispatchAll();
 
         assertInStaDisabledState();
-        verify(mScanOnlyModeManager, never()).start();
+        verify(mClientModeManager, never()).start();
     }
 
     /**
@@ -1928,8 +1889,9 @@
         mActiveModeWarden.wifiToggled();
         mLooper.dispatchAll();
 
-        assertInScanOnlyState();
-        verify(mScanOnlyModeManager).start();
+        assertInStaEnabledState();
+        verify(mClientModeManager).start();
+        verify(mClientModeManager).switchToScanOnlyMode();
     }
 
     /**
@@ -1947,7 +1909,7 @@
             mActiveModeWarden.emergencyCallbackModeChanged(true);
             mLooper.dispatchAll();
         });
-        assertInClientState();
+        assertInStaEnabledState();
         verify(mClientModeManager).stop();
 
         mActiveModeWarden.emergencyCallbackModeChanged(false);
@@ -1956,6 +1918,6 @@
         assertThat(mActiveModeWarden.isInEmergencyMode()).isFalse();
         // client mode restarted
         verify(mClientModeManager, times(2)).start();
-        assertInClientState();
+        assertInStaEnabledState();
     }
 }
diff --git a/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
index 96086c7..2d4dae2 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
@@ -2099,7 +2099,6 @@
         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
         inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(true));
         inOrder.verify(mWifiNetworkFactory).setWifiState(eq(true));
-        inOrderSarMgr.verify(mSarManager).setClientWifiState(WifiManager.WIFI_STATE_ENABLED);
         inOrderMetrics.verify(mWifiMetrics)
                 .setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED);
         inOrderMetrics.verify(mWifiMetrics).logStaEvent(StaEvent.TYPE_WIFI_ENABLED);
@@ -2123,7 +2122,6 @@
         assertEquals(WifiManager.WIFI_STATE_DISABLED, mCmi.syncGetWifiState());
         inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(false));
         inOrder.verify(mWifiNetworkFactory).setWifiState(eq(false));
-        inOrderSarMgr.verify(mSarManager).setClientWifiState(WifiManager.WIFI_STATE_DISABLED);
         inOrderMetrics.verify(mWifiMetrics).setWifiState(WifiMetricsProto.WifiLog.WIFI_DISABLED);
         inOrderMetrics.verify(mWifiMetrics).logStaEvent(StaEvent.TYPE_WIFI_DISABLED);
         assertNull(wifiInfo.getBSSID());
@@ -2147,7 +2145,6 @@
         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
         inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(true));
         inOrder.verify(mWifiNetworkFactory).setWifiState(eq(true));
-        inOrderSarMgr.verify(mSarManager).setClientWifiState(WifiManager.WIFI_STATE_ENABLED);
         inOrderMetrics.verify(mWifiMetrics)
                 .setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED);
         inOrderMetrics.verify(mWifiMetrics).logStaEvent(StaEvent.TYPE_WIFI_ENABLED);
diff --git a/service/tests/wifitests/src/com/android/server/wifi/ClientModeManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/ClientModeManagerTest.java
index a5d1605..e94d307 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/ClientModeManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/ClientModeManagerTest.java
@@ -17,9 +17,7 @@
 package com.android.server.wifi;
 
 import static android.net.wifi.WifiManager.EXTRA_PREVIOUS_WIFI_STATE;
-import static android.net.wifi.WifiManager.EXTRA_SCAN_AVAILABLE;
 import static android.net.wifi.WifiManager.EXTRA_WIFI_STATE;
-import static android.net.wifi.WifiManager.WIFI_SCAN_AVAILABLE;
 import static android.net.wifi.WifiManager.WIFI_STATE_CHANGED_ACTION;
 import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
 import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING;
@@ -28,6 +26,7 @@
 import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.*;
 
 import android.content.Context;
@@ -40,6 +39,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -62,7 +62,8 @@
     @Mock WifiMetrics mWifiMetrics;
     @Mock WifiNative mWifiNative;
     @Mock ClientModeManager.Listener mListener;
-    @Mock WifiMonitor mWifiMonitor;
+    @Mock SarManager mSarManager;
+    @Mock WakeupController mWakeupController;
     @Mock ClientModeImpl mClientModeImpl;
 
     final ArgumentCaptor<WifiNative.InterfaceCallback> mInterfaceCallbackCaptor =
@@ -79,44 +80,72 @@
 
     private ClientModeManager createClientModeManager() {
         return new ClientModeManager(mContext, mLooper.getLooper(), mWifiNative, mListener,
-                mWifiMetrics, mClientModeImpl);
+                mWifiMetrics, mSarManager, mWakeupController, mClientModeImpl);
     }
 
-    private void startClientModeAndVerifyEnabled() throws Exception {
-        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
-
-        when(mWifiNative.setupInterfaceForClientInConnectivityMode(any()))
+    private void startClientInScanOnlyModeAndVerifyEnabled() throws Exception {
+        when(mWifiNative.setupInterfaceForClientInScanMode(any()))
                 .thenReturn(TEST_INTERFACE_NAME);
         mClientModeManager.start();
         mLooper.dispatchAll();
 
-        verify(mWifiNative).setupInterfaceForClientInConnectivityMode(
+        verify(mWifiNative).setupInterfaceForClientInScanMode(
                 mInterfaceCallbackCaptor.capture());
+        verify(mClientModeImpl).setOperationalMode(
+                ClientModeImpl.SCAN_ONLY_MODE, TEST_INTERFACE_NAME);
+        verify(mSarManager).setScanOnlyWifiState(WIFI_STATE_ENABLED);
 
         // now mark the interface as up
         mInterfaceCallbackCaptor.getValue().onUp(TEST_INTERFACE_NAME);
         mLooper.dispatchAll();
 
+        // Ensure that no public broadcasts were sent.
+        verifyNoMoreInteractions(mContext);
+        verify(mListener).onStarted();
+    }
+
+    private void startClientInConnectModeAndVerifyEnabled() throws Exception {
+        when(mWifiNative.setupInterfaceForClientInScanMode(any()))
+                .thenReturn(TEST_INTERFACE_NAME);
+        when(mWifiNative.switchClientInterfaceToConnectivityMode(any()))
+                .thenReturn(true);
+        mClientModeManager.start();
+        mLooper.dispatchAll();
+
+        verify(mWifiNative).setupInterfaceForClientInScanMode(
+                mInterfaceCallbackCaptor.capture());
+        verify(mClientModeImpl).setOperationalMode(
+                ClientModeImpl.SCAN_ONLY_MODE, TEST_INTERFACE_NAME);
+        mLooper.dispatchAll();
+
+        mClientModeManager.switchToConnectMode();
+        mLooper.dispatchAll();
+
+        verify(mWifiNative).switchClientInterfaceToConnectivityMode(TEST_INTERFACE_NAME);
+        verify(mClientModeImpl).setOperationalMode(
+                ClientModeImpl.CONNECT_MODE, TEST_INTERFACE_NAME);
+        verify(mSarManager).setClientWifiState(WIFI_STATE_ENABLED);
+
+        // now mark the interface as up
+        mInterfaceCallbackCaptor.getValue().onUp(TEST_INTERFACE_NAME);
+        mLooper.dispatchAll();
+
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mContext, atLeastOnce()).sendStickyBroadcastAsUser(intentCaptor.capture(),
                 eq(UserHandle.ALL));
 
         List<Intent> intents = intentCaptor.getAllValues();
         assertEquals(2, intents.size());
         Log.d(TAG, "captured intents: " + intents);
-        checkWifiStateChangedBroadcast(intents.get(0), WIFI_STATE_ENABLING, WIFI_STATE_DISABLED);
-        checkWifiStateChangedBroadcast(intents.get(1), WIFI_STATE_ENABLED, WIFI_STATE_ENABLING);
+        checkWifiConnectModeStateChangedBroadcast(intents.get(0), WIFI_STATE_ENABLING,
+                WIFI_STATE_DISABLED);
+        checkWifiConnectModeStateChangedBroadcast(intents.get(1), WIFI_STATE_ENABLED,
+                WIFI_STATE_ENABLING);
 
-        checkWifiStateChangeListenerUpdate(WIFI_STATE_ENABLED);
+        verify(mListener, times(2)).onStarted();
     }
 
-    private void checkWifiScanStateChangedBroadcast(Intent intent, int expectedCurrentState) {
-        String action = intent.getAction();
-        assertEquals(WIFI_SCAN_AVAILABLE, action);
-        int currentState = intent.getIntExtra(EXTRA_SCAN_AVAILABLE, WIFI_STATE_UNKNOWN);
-        assertEquals(expectedCurrentState, currentState);
-    }
-
-    private void checkWifiStateChangedBroadcast(
+    private void checkWifiConnectModeStateChangedBroadcast(
             Intent intent, int expectedCurrentState, int expectedPrevState) {
         String action = intent.getAction();
         assertEquals(WIFI_STATE_CHANGED_ACTION, action);
@@ -128,80 +157,135 @@
         verify(mClientModeImpl, atLeastOnce()).setWifiStateForApiCalls(expectedCurrentState);
     }
 
+    private void verifyConnectModeNotificationsForCleanShutdown(int fromState) {
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContext, atLeastOnce())
+                .sendStickyBroadcastAsUser(intentCaptor.capture(), eq(UserHandle.ALL));
 
-    private void checkWifiStateChangeListenerUpdate(int expectedCurrentState) {
-        verify(mListener).onStateChanged(eq(expectedCurrentState));
+        List<Intent> intents = intentCaptor.getAllValues();
+        assertTrue(intents.size() >= 2);
+        checkWifiConnectModeStateChangedBroadcast(intents.get(intents.size() - 2),
+                WIFI_STATE_DISABLING, fromState);
+        checkWifiConnectModeStateChangedBroadcast(intents.get(intents.size() - 1),
+                WIFI_STATE_DISABLED, WIFI_STATE_DISABLING);
     }
 
-    private void verifyNotificationsForCleanShutdown(int fromState) {
+    private void verifyConnectModeNotificationsForFailure() {
         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mContext, atLeastOnce())
                 .sendStickyBroadcastAsUser(intentCaptor.capture(), eq(UserHandle.ALL));
 
         List<Intent> intents = intentCaptor.getAllValues();
         assertEquals(2, intents.size());
-        checkWifiStateChangedBroadcast(intents.get(0), WIFI_STATE_DISABLING, fromState);
-        checkWifiStateChangedBroadcast(intents.get(1), WIFI_STATE_DISABLED, WIFI_STATE_DISABLING);
-    }
-
-    private void verifyNotificationsForFailure() {
-        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
-        verify(mContext, atLeastOnce())
-                .sendStickyBroadcastAsUser(intentCaptor.capture(), eq(UserHandle.ALL));
-
-        List<Intent> intents = intentCaptor.getAllValues();
-        assertEquals(2, intents.size());
-        checkWifiStateChangedBroadcast(intents.get(0), WIFI_STATE_DISABLING, WIFI_STATE_UNKNOWN);
-        checkWifiStateChangedBroadcast(intents.get(1), WIFI_STATE_DISABLED, WIFI_STATE_DISABLING);
-        checkWifiStateChangeListenerUpdate(WIFI_STATE_UNKNOWN);
+        checkWifiConnectModeStateChangedBroadcast(intents.get(0), WIFI_STATE_DISABLING,
+                WIFI_STATE_UNKNOWN);
+        checkWifiConnectModeStateChangedBroadcast(intents.get(1), WIFI_STATE_DISABLED,
+                WIFI_STATE_DISABLING);
     }
 
     /**
      * ClientMode start sets up an interface in ClientMode.
      */
     @Test
-    public void clientModeStartCreatesClientInterface() throws Exception {
-        startClientModeAndVerifyEnabled();
+    public void clientInConnectModeStartCreatesClientInterface() throws Exception {
+        startClientInConnectModeAndVerifyEnabled();
     }
 
     /**
-     * ClientMode increments failure metrics when failing to setup client mode.
+     * ClientMode start sets up an interface in ClientMode.
      */
     @Test
-    public void detectAndReportErrorWhenSetupForClientWifiNativeFailure() throws Exception {
-        when(mWifiNative.setupInterfaceForClientInConnectivityMode(any())).thenReturn(null);
-        mClientModeManager.start();
+    public void clientInScanOnlyModeStartCreatesClientInterface() throws Exception {
+        startClientInScanOnlyModeAndVerifyEnabled();
+    }
+
+    /**
+     * Switch ClientModeManager from ScanOnly mode To Connect mode.
+     */
+    @Test
+    public void switchFromScanOnlyModeToConnectMode() throws Exception {
+        startClientInScanOnlyModeAndVerifyEnabled();
+
+        when(mWifiNative.switchClientInterfaceToConnectivityMode(any()))
+                .thenReturn(true);
+        mClientModeManager.switchToConnectMode();
         mLooper.dispatchAll();
 
+        verify(mSarManager).setScanOnlyWifiState(WIFI_STATE_DISABLED);
+        verify(mClientModeImpl).setOperationalMode(
+                ClientModeImpl.SCAN_ONLY_MODE, TEST_INTERFACE_NAME);
+        verify(mClientModeImpl).setOperationalMode(
+                ClientModeImpl.CONNECT_MODE, TEST_INTERFACE_NAME);
+        verify(mSarManager).setClientWifiState(WIFI_STATE_ENABLED);
+
         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mContext, atLeastOnce()).sendStickyBroadcastAsUser(intentCaptor.capture(),
                 eq(UserHandle.ALL));
+
         List<Intent> intents = intentCaptor.getAllValues();
         assertEquals(2, intents.size());
-        checkWifiStateChangedBroadcast(intents.get(0), WIFI_STATE_ENABLING, WIFI_STATE_DISABLED);
-        checkWifiStateChangedBroadcast(intents.get(1), WIFI_STATE_DISABLED, WIFI_STATE_UNKNOWN);
-        checkWifiStateChangeListenerUpdate(WIFI_STATE_UNKNOWN);
+        Log.d(TAG, "captured intents: " + intents);
+        checkWifiConnectModeStateChangedBroadcast(intents.get(0), WIFI_STATE_ENABLING,
+                WIFI_STATE_DISABLED);
+        checkWifiConnectModeStateChangedBroadcast(intents.get(1), WIFI_STATE_ENABLED,
+                WIFI_STATE_ENABLING);
+
+        verify(mListener, times(2)).onStarted();
     }
 
     /**
-     * ClientMode start does not indicate scanning is available when the interface name is empty.
+     * Switch ClientModeManager from Connect mode to ScanOnly mode.
      */
     @Test
-    public void clientModeStartDoesNotSendScanningActiveWhenClientInterfaceNameIsEmpty()
+    public void switchFromConnectModeToScanOnlyMode() throws Exception {
+        startClientInConnectModeAndVerifyEnabled();
+
+        when(mWifiNative.switchClientInterfaceToScanMode(any()))
+                .thenReturn(true);
+        mClientModeManager.switchToScanOnlyMode();
+        mLooper.dispatchAll();
+
+        verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED);
+
+        verify(mSarManager).setClientWifiState(WIFI_STATE_DISABLED);
+        verify(mWifiNative).setupInterfaceForClientInScanMode(
+                mInterfaceCallbackCaptor.capture());
+        verify(mWifiNative).switchClientInterfaceToScanMode(TEST_INTERFACE_NAME);
+        verify(mClientModeImpl, times(2)).setOperationalMode(
+                ClientModeImpl.SCAN_ONLY_MODE, TEST_INTERFACE_NAME);
+        verify(mSarManager, times(2)).setScanOnlyWifiState(WIFI_STATE_ENABLED);
+
+        // Ensure that no public broadcasts were sent.
+        verifyNoMoreInteractions(mContext);
+        verify(mListener, times(3)).onStarted();
+    }
+
+    /**
+     * ClientMode increments failure metrics when failing to setup client mode in connectivity mode.
+     */
+    @Test
+    public void detectAndReportErrorWhenSetupForClientInConnectivityModeWifiNativeFailure()
             throws Exception {
-        when(mWifiNative.setupInterfaceForClientInConnectivityMode(any())).thenReturn("");
+        when(mWifiNative.setupInterfaceForClientInScanMode(any()))
+                .thenReturn(TEST_INTERFACE_NAME);
+        when(mWifiNative.switchClientInterfaceToConnectivityMode(any())).thenReturn(false);
+
         mClientModeManager.start();
         mLooper.dispatchAll();
 
+        mClientModeManager.switchToConnectMode();
+        mLooper.dispatchAll();
+
         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mContext, atLeastOnce()).sendStickyBroadcastAsUser(intentCaptor.capture(),
                 eq(UserHandle.ALL));
-
         List<Intent> intents = intentCaptor.getAllValues();
         assertEquals(2, intents.size());
-        checkWifiStateChangedBroadcast(intents.get(0), WIFI_STATE_ENABLING, WIFI_STATE_DISABLED);
-        checkWifiStateChangedBroadcast(intents.get(1), WIFI_STATE_DISABLED, WIFI_STATE_UNKNOWN);
-        checkWifiStateChangeListenerUpdate(WIFI_STATE_UNKNOWN);
+        checkWifiConnectModeStateChangedBroadcast(intents.get(0), WIFI_STATE_ENABLING,
+                WIFI_STATE_DISABLED);
+        checkWifiConnectModeStateChangedBroadcast(intents.get(1), WIFI_STATE_DISABLED,
+                WIFI_STATE_UNKNOWN);
+        verify(mListener).onStartFailure();
     }
 
     /**
@@ -209,7 +293,7 @@
      */
     @Test
     public void clientModeStartCalledTwice() throws Exception {
-        startClientModeAndVerifyEnabled();
+        startClientInConnectModeAndVerifyEnabled();
         reset(mWifiNative, mContext);
         mClientModeManager.start();
         mLooper.dispatchAll();
@@ -221,12 +305,13 @@
      */
     @Test
     public void clientModeStopCleansUpState() throws Exception {
-        startClientModeAndVerifyEnabled();
+        startClientInConnectModeAndVerifyEnabled();
         reset(mContext, mListener);
         mClientModeManager.stop();
         mLooper.dispatchAll();
+        verify(mListener).onStopped();
 
-        verifyNotificationsForCleanShutdown(WIFI_STATE_ENABLED);
+        verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED);
 
         // on an explicit stop, we should not trigger the callback
         verifyNoMoreInteractions(mListener);
@@ -237,18 +322,18 @@
      */
     @Test
     public void clientModeStopWhenNotStartedDoesNotUpdateScanStateUpdates() throws Exception {
-        startClientModeAndVerifyEnabled();
+        startClientInConnectModeAndVerifyEnabled();
         reset(mContext);
         mClientModeManager.stop();
         mLooper.dispatchAll();
-        verifyNotificationsForCleanShutdown(WIFI_STATE_ENABLED);
+        verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED);
 
         reset(mContext, mListener);
         // now call stop again
         mClientModeManager.stop();
         mLooper.dispatchAll();
         verify(mContext, never()).sendStickyBroadcastAsUser(any(), any());
-        verify(mListener, never()).onStateChanged(anyInt());
+        verifyNoMoreInteractions(mListener);
     }
 
     /**
@@ -256,13 +341,14 @@
      */
     @Test
     public void clientModeStartedStopsWhenInterfaceDown() throws Exception {
-        startClientModeAndVerifyEnabled();
+        startClientInConnectModeAndVerifyEnabled();
         reset(mContext);
         when(mClientModeImpl.isConnectedMacRandomizationEnabled()).thenReturn(false);
         mInterfaceCallbackCaptor.getValue().onDown(TEST_INTERFACE_NAME);
         mLooper.dispatchAll();
         verify(mClientModeImpl).failureDetected(eq(SelfRecovery.REASON_STA_IFACE_DOWN));
-        verifyNotificationsForFailure();
+        verifyConnectModeNotificationsForFailure();
+        verify(mListener).onStopped();
     }
 
     /**
@@ -272,7 +358,7 @@
     @Test
     public void clientModeStartedWithConnectedMacRandDoesNotStopWhenInterfaceDown()
             throws Exception {
-        startClientModeAndVerifyEnabled();
+        startClientInConnectModeAndVerifyEnabled();
         reset(mContext);
         when(mClientModeImpl.isConnectedMacRandomizationEnabled()).thenReturn(true);
         mInterfaceCallbackCaptor.getValue().onDown(TEST_INTERFACE_NAME);
@@ -286,12 +372,13 @@
      */
     @Test
     public void clientModeStartedStopsOnInterfaceDestroyed() throws Exception {
-        startClientModeAndVerifyEnabled();
+        startClientInConnectModeAndVerifyEnabled();
         reset(mContext);
         mInterfaceCallbackCaptor.getValue().onDestroyed(TEST_INTERFACE_NAME);
         mLooper.dispatchAll();
-        verifyNotificationsForCleanShutdown(WIFI_STATE_ENABLED);
+        verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED);
         verify(mClientModeImpl).handleIfaceDestroyed();
+        verify(mListener).onStopped();
     }
 
     /**
@@ -299,7 +386,7 @@
      */
     @Test
     public void noCallbackOnInterfaceDestroyedWhenAlreadyStopped() throws Exception {
-        startClientModeAndVerifyEnabled();
+        startClientInConnectModeAndVerifyEnabled();
 
         reset(mListener);
 
@@ -309,8 +396,37 @@
         // now trigger interface destroyed and make sure callback doesn't get called
         mInterfaceCallbackCaptor.getValue().onDestroyed(TEST_INTERFACE_NAME);
         mLooper.dispatchAll();
+        verify(mListener).onStopped();
 
         verifyNoMoreInteractions(mListener);
         verify(mClientModeImpl, never()).handleIfaceDestroyed();
     }
+
+    /**
+     * Entering ScanOnly state starts the WakeupController.
+     */
+    @Test
+    public void scanModeEnterStartsWakeupController() throws Exception {
+        startClientInScanOnlyModeAndVerifyEnabled();
+
+        verify(mWakeupController).start();
+    }
+
+    /**
+     * Exiting ScanOnly state stops the WakeupController.
+     */
+    @Test
+    public void scanModeExitStopsWakeupController() throws Exception {
+        startClientInScanOnlyModeAndVerifyEnabled();
+
+        mClientModeManager.stop();
+        mLooper.dispatchAll();
+
+        InOrder inOrder = inOrder(mWakeupController, mWifiNative, mListener);
+
+        inOrder.verify(mListener).onStarted();
+        inOrder.verify(mWakeupController).start();
+        inOrder.verify(mWakeupController).stop();
+        inOrder.verify(mWifiNative).teardownInterface(eq(TEST_INTERFACE_NAME));
+    }
 }
diff --git a/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java
index ee84497..4e0ef1a 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java
@@ -85,6 +85,7 @@
     @Mock Resources mResources;
     @Mock WifiNative mWifiNative;
     @Mock WifiManager.SoftApCallback mCallback;
+    @Mock ActiveModeManager.Listener mListener;
     @Mock FrameworkFacade mFrameworkFacade;
     @Mock WifiApConfigStore mWifiApConfigStore;
     @Mock WifiMetrics mWifiMetrics;
@@ -133,6 +134,7 @@
                                                            mFrameworkFacade,
                                                            mWifiNative,
                                                            countryCode,
+                                                           mListener,
                                                            mCallback,
                                                            mWifiApConfigStore,
                                                            config,
@@ -207,6 +209,7 @@
                                                            mFrameworkFacade,
                                                            mWifiNative,
                                                            TEST_COUNTRY_CODE,
+                                                           mListener,
                                                            mCallback,
                                                            mWifiApConfigStore,
                                                            nullApConfig,
@@ -218,6 +221,7 @@
         mLooper.dispatchAll();
         verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED,
                 WifiManager.SAP_START_FAILURE_GENERAL);
+        verify(mListener).onStartFailure();
         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mContext, times(2)).sendStickyBroadcastAsUser(intentCaptor.capture(),
                 eq(UserHandle.ALL));
@@ -251,6 +255,7 @@
                                                            mFrameworkFacade,
                                                            mWifiNative,
                                                            TEST_COUNTRY_CODE,
+                                                           mListener,
                                                            mCallback,
                                                            mWifiApConfigStore,
                                                            nullApConfig,
@@ -262,6 +267,7 @@
         mLooper.dispatchAll();
         verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED,
                 WifiManager.SAP_START_FAILURE_GENERAL);
+        verify(mListener).onStartFailure();
         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mContext).sendStickyBroadcastAsUser(intentCaptor.capture(),
                 eq(UserHandle.ALL));
@@ -294,6 +300,7 @@
                                                            mFrameworkFacade,
                                                            mWifiNative,
                                                            TEST_COUNTRY_CODE,
+                                                           mListener,
                                                            mCallback,
                                                            mWifiApConfigStore,
                                                            nullApConfig,
@@ -305,6 +312,7 @@
         mLooper.dispatchAll();
         verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED,
                 WifiManager.SAP_START_FAILURE_GENERAL);
+        verify(mListener).onStartFailure();
         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mContext).sendStickyBroadcastAsUser(intentCaptor.capture(),
                 eq(UserHandle.ALL));
@@ -336,6 +344,7 @@
                 mFrameworkFacade,
                 mWifiNative,
                 null,
+                mListener,
                 mCallback,
                 mWifiApConfigStore,
                 softApConfig,
@@ -383,6 +392,7 @@
                                                            mFrameworkFacade,
                                                            mWifiNative,
                                                            TEST_COUNTRY_CODE,
+                                                           mListener,
                                                            mCallback,
                                                            mWifiApConfigStore,
                                                            softApConfig,
@@ -500,6 +510,7 @@
                                                            mFrameworkFacade,
                                                            mWifiNative,
                                                            TEST_COUNTRY_CODE,
+                                                           mListener,
                                                            mCallback,
                                                            mWifiApConfigStore,
                                                            softApConfig,
@@ -539,6 +550,7 @@
                                                            mFrameworkFacade,
                                                            mWifiNative,
                                                            TEST_COUNTRY_CODE,
+                                                           mListener,
                                                            mCallback,
                                                            mWifiApConfigStore,
                                                            softApModeConfig,
@@ -551,6 +563,7 @@
         mLooper.dispatchAll();
         verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED,
                 WifiManager.SAP_START_FAILURE_GENERAL);
+        verify(mListener).onStartFailure();
         verify(mWifiNative).teardownInterface(TEST_INTERFACE_NAME);
     }
 
@@ -566,6 +579,7 @@
         mLooper.dispatchAll();
         /* Verify no state changes. */
         verify(mCallback, never()).onStateChanged(anyInt(), anyInt());
+        verifyNoMoreInteractions(mListener);
         verify(mSarManager, never()).setSapWifiState(anyInt());
         verify(mContext, never()).sendStickyBroadcastAsUser(any(), any());
         verify(mWifiNative, never()).teardownInterface(anyString());
@@ -583,7 +597,7 @@
         // reset to clear verified Intents for ap state change updates
         reset(mContext);
 
-        InOrder order = inOrder(mCallback, mContext);
+        InOrder order = inOrder(mCallback, mListener, mContext);
 
         mSoftApManager.stop();
         mLooper.dispatchAll();
@@ -618,7 +632,7 @@
         // reset to clear verified Intents for ap state change updates
         reset(mContext);
 
-        InOrder order = inOrder(mCallback, mContext);
+        InOrder order = inOrder(mCallback, mListener, mContext);
 
         mWifiNativeInterfaceCallbackCaptor.getValue().onDestroyed(TEST_INTERFACE_NAME);
 
@@ -637,6 +651,7 @@
         checkApStateChangedBroadcast(intentCaptor.getValue(), WIFI_AP_STATE_DISABLED,
                 WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME,
                 softApModeConfig.getTargetMode());
+        order.verify(mListener).onStopped();
     }
 
     /**
@@ -650,6 +665,7 @@
 
         mSoftApManager.stop();
         mLooper.dispatchAll();
+        verify(mListener).onStopped();
 
         verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLING, 0);
         verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0);
@@ -660,7 +676,7 @@
         mWifiNativeInterfaceCallbackCaptor.getValue().onDestroyed(TEST_INTERFACE_NAME);
         mLooper.dispatchAll();
 
-        verifyNoMoreInteractions(mCallback);
+        verifyNoMoreInteractions(mCallback, mListener);
     }
 
     /**
@@ -675,7 +691,7 @@
         // reset to clear verified Intents for ap state change updates
         reset(mContext, mCallback, mWifiNative);
 
-        InOrder order = inOrder(mCallback, mContext);
+        InOrder order = inOrder(mCallback, mListener, mContext);
 
         mWifiNativeInterfaceCallbackCaptor.getValue().onDown(TEST_INTERFACE_NAME);
 
@@ -683,6 +699,7 @@
 
         order.verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED,
                 WifiManager.SAP_START_FAILURE_GENERAL);
+        order.verify(mListener).onStopped();
         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mContext, times(3)).sendStickyBroadcastAsUser(intentCaptor.capture(),
                 eq(UserHandle.ALL));
@@ -717,7 +734,7 @@
 
         mLooper.dispatchAll();
 
-        verifyNoMoreInteractions(mContext, mCallback, mWifiNative);
+        verifyNoMoreInteractions(mContext, mCallback, mListener, mWifiNative);
     }
 
     /**
@@ -732,13 +749,14 @@
         // reset to clear verified Intents for ap state change updates
         reset(mContext, mCallback, mWifiNative);
 
-        InOrder order = inOrder(mCallback, mContext);
+        InOrder order = inOrder(mCallback, mListener, mContext);
 
         mSoftApListenerCaptor.getValue().onFailure();
         mLooper.dispatchAll();
 
         order.verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED,
                 WifiManager.SAP_START_FAILURE_GENERAL);
+        order.verify(mListener).onStopped();
         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mContext, times(3)).sendStickyBroadcastAsUser(intentCaptor.capture(),
                 eq(UserHandle.ALL));
@@ -1117,6 +1135,7 @@
         checkApStateChangedBroadcast(capturedIntents.get(1), WIFI_AP_STATE_ENABLED,
                 WIFI_AP_STATE_ENABLING, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME,
                 softApConfig.getTargetMode());
+        verify(mListener).onStarted();
         verify(mWifiMetrics).addSoftApUpChangedEvent(true, softApConfig.mTargetMode);
         verify(mFrameworkFacade).registerContentObserver(eq(mContext), any(Uri.class), eq(true),
                 observerCaptor.capture());