WifiController: activate SoftApMode in WSMP

Allow WifiController to enter SoftApMode via the WifiStateMachinePrime
impl instead of the WifiStateMachine impl.  Note:  WifiStateMachine will
shadow WifiStateMachinePrime to handle API calls, but will not be
managing the mode.

Bug: 31830541
Test: frameworks/opt/net/wifi/tests/wifitests/runtests.sh
Test: wifi integration tests
Test: manual testing from Settings and QS
Test: related wifi CTS tests
Change-Id: I9a24393ff5625734c785599eba2aed61a886ba26
diff --git a/service/java/com/android/server/wifi/SoftApManager.java b/service/java/com/android/server/wifi/SoftApManager.java
index 0abde24..6d5fd27 100644
--- a/service/java/com/android/server/wifi/SoftApManager.java
+++ b/service/java/com/android/server/wifi/SoftApManager.java
@@ -235,12 +235,11 @@
     }
 
     /**
-     * Teardown soft AP.
+     * Teardown soft AP and teardown the interface.
      */
     private void stopSoftAp() {
         if (!mWifiNative.stopSoftAp()) {
-            Log.d(TAG, "Soft AP stop failed");
-            return;
+            Log.e(TAG, "Soft AP stop failed");
         }
         Log.d(TAG, "Soft AP is stopped");
     }
@@ -308,9 +307,11 @@
                         if (statusAndInterface.first == WifiNative.SETUP_SUCCESS) {
                             mApInterface = statusAndInterface.second;
                         } else {
+                            Log.e(TAG, "setup failure when creating ap interface.");
                             incrementMetricsForSetupFailure(statusAndInterface.first);
                         }
                         if (mApInterface == null) {
+                            Log.e(TAG, "Not starting softap mode without an interface.");
                             updateApState(WifiManager.WIFI_AP_STATE_FAILED,
                                           WifiManager.WIFI_AP_STATE_DISABLED,
                                           WifiManager.SAP_START_FAILURE_GENERAL);
@@ -323,6 +324,7 @@
                         } catch (RemoteException e) {
                             // Failed to get the interface name. This is not a good sign and we
                             // should report a failure.
+                            Log.e(TAG, "Failed to get the interface name.");
                             updateApState(WifiManager.WIFI_AP_STATE_FAILED,
                                           WifiManager.WIFI_AP_STATE_DISABLED,
                                           WifiManager.SAP_START_FAILURE_GENERAL);
diff --git a/service/java/com/android/server/wifi/WifiController.java b/service/java/com/android/server/wifi/WifiController.java
index 0455e34..dc98595 100644
--- a/service/java/com/android/server/wifi/WifiController.java
+++ b/service/java/com/android/server/wifi/WifiController.java
@@ -438,7 +438,8 @@
         @Override
         public void enter() {
             mWifiStateMachine.setSupplicantRunning(false);
-            // Supplicant can't restart right away, so not the time we switched off
+            mWifiStateMachinePrime.disableWifi();
+            // Supplicant can't restart right away, so note the time we switched off
             mDisabledTimestamp = SystemClock.elapsedRealtime();
             mDeferredEnableSerialNumber++;
             mHaveDeferredEnable = false;
@@ -484,6 +485,7 @@
                         }
                         mWifiStateMachine.setHostApRunning((SoftApModeConfiguration) msg.obj,
                                 true);
+                        mWifiStateMachinePrime.enterSoftAPMode((SoftApModeConfiguration) msg.obj);
                         transitionTo(mApEnabledState);
                     }
                     break;
@@ -568,8 +570,13 @@
                     if (msg.arg1 == 1) {
                         // remeber that we were enabled
                         mSettingsStore.setWifiSavedState(WifiSettingsStore.WIFI_ENABLED);
-                        deferMessage(obtainMessage(msg.what, msg.arg1, 1, msg.obj));
-                        transitionTo(mApStaDisabledState);
+                        mWifiStateMachine.setHostApRunning((SoftApModeConfiguration) msg.obj, true);
+                        mWifiStateMachinePrime.enterSoftAPMode((SoftApModeConfiguration) msg.obj);
+                        transitionTo(mApEnabledState);
+                        // we should just go directly to ApEnabled since we will kill interfaces
+                        // from WSMP
+                        //deferMessage(obtainMessage(msg.what, msg.arg1, 1, msg.obj));
+                        //transitionTo(mApStaDisabledState);
                     }
                     break;
                 default:
@@ -633,8 +640,14 @@
                     // Before starting tethering, turn off supplicant for scan mode
                     if (msg.arg1 == 1) {
                         mSettingsStore.setWifiSavedState(WifiSettingsStore.WIFI_DISABLED);
-                        deferMessage(obtainMessage(msg.what, msg.arg1, 1, msg.obj));
-                        transitionTo(mApStaDisabledState);
+
+                        mWifiStateMachine.setHostApRunning((SoftApModeConfiguration) msg.obj, true);
+                        mWifiStateMachinePrime.enterSoftAPMode((SoftApModeConfiguration) msg.obj);
+                        transitionTo(mApEnabledState);
+                        // we should just go directly to ApEnabled since we will kill interfaces
+                        // from WSMP
+                        //deferMessage(obtainMessage(msg.what, msg.arg1, 1, msg.obj));
+                        //transitionTo(mApStaDisabledState);
                     }
                     break;
                 case CMD_DEFERRED_TOGGLE:
@@ -704,22 +717,26 @@
                 case CMD_AIRPLANE_TOGGLED:
                     if (mSettingsStore.isAirplaneModeOn()) {
                         mWifiStateMachine.setHostApRunning(null, false);
+                        mWifiStateMachinePrime.disableWifi();
                         mPendingState = mApStaDisabledState;
                     }
                     break;
                 case CMD_WIFI_TOGGLED:
                     if (mSettingsStore.isWifiToggleEnabled()) {
                         mWifiStateMachine.setHostApRunning(null, false);
+                        mWifiStateMachinePrime.disableWifi();
                         mPendingState = mDeviceActiveState;
                     }
                     break;
                 case CMD_SET_AP:
                     if (msg.arg1 == 0) {
                         mWifiStateMachine.setHostApRunning(null, false);
+                        mWifiStateMachinePrime.disableWifi();
                         mPendingState = getNextWifiState();
                     }
                     break;
                 case CMD_AP_STOPPED:
+                    mWifiStateMachine.setHostApRunning(null, false);
                     if (mPendingState == null) {
                         /**
                          * Stop triggered internally, either tether notification
@@ -739,10 +756,12 @@
                 case CMD_EMERGENCY_MODE_CHANGED:
                     if (msg.arg1 == 1) {
                         mWifiStateMachine.setHostApRunning(null, false);
+                        mWifiStateMachinePrime.disableWifi();
                         mPendingState = mEcmState;
                     }
                     break;
                 case CMD_AP_START_FAILURE:
+                    mWifiStateMachine.setHostApRunning(null, false);
                     transitionTo(getNextWifiState());
                     break;
                 default:
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index 95caf29..505a09b 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -4150,6 +4150,9 @@
             // Tearing down the client interfaces below is going to stop our supplicant.
             mWifiMonitor.stopAllMonitoring();
 
+            // stop hostapd in case it was running from SoftApMode
+            mWifiNative.stopSoftAp();
+
             mWifiNative.deregisterWificondDeathHandler();
             mWifiNative.tearDown();
         }
@@ -4296,9 +4299,12 @@
                         transitionTo(mInitialState);
                     }
                     break;
+                case CMD_START_AP:
+                    // now go directly to softap mode since we handle teardown in WSMP
+                    transitionTo(mSoftApState);
+                    break;
                 case CMD_START_SUPPLICANT:
                 case CMD_STOP_SUPPLICANT:
-                case CMD_START_AP:
                 case CMD_STOP_AP:
                 case CMD_SET_OPERATIONAL_MODE:
                     messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED;
@@ -4448,10 +4454,12 @@
                         sendMessage(mBufferedScanMsg.remove());
                     break;
                 case CMD_START_AP:
-                    /* Cannot start soft AP while in client mode */
-                    loge("Failed to start soft AP with a running supplicant");
-                    setWifiApState(WIFI_AP_STATE_FAILED, WifiManager.SAP_START_FAILURE_GENERAL,
-                            null, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
+                //    /* Cannot start soft AP while in client mode */
+                //    loge("Failed to start soft AP with a running supplicant");
+                //    setWifiApState(WIFI_AP_STATE_FAILED, WifiManager.SAP_START_FAILURE_GENERAL,
+                //            null, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
+                    // now go directly to softap mode since we handle teardown in WSMP
+                    transitionTo(mSoftApState);
                     break;
                 case CMD_SET_OPERATIONAL_MODE:
                     mOperationalMode = message.arg1;
@@ -4907,6 +4915,7 @@
             }
             mWifiInfo.reset();
             mWifiInfo.setSupplicantState(SupplicantState.DISCONNECTED);
+            setWifiState(WIFI_STATE_DISABLED);
         }
 
         @Override
@@ -6945,6 +6954,7 @@
         private String mIfaceName;
         private int mMode;
 
+        /*
         private class SoftApListener implements SoftApManager.Listener {
             @Override
             public void onStateChanged(int state, int reason) {
@@ -6957,6 +6967,7 @@
                 setWifiApState(state, reason, mIfaceName, mMode);
             }
         }
+        */
 
         @Override
         public void enter() {
@@ -6964,9 +6975,10 @@
             if (message.what != CMD_START_AP) {
                 throw new RuntimeException("Illegal transition to SoftApState: " + message);
             }
+            /*
             SoftApModeConfiguration config = (SoftApModeConfiguration) message.obj;
             mMode = config.getTargetMode();
-            /*
+
             IApInterface apInterface = null;
             Pair<Integer, IApInterface> statusAndInterface =
                     mWifiNative.setupForSoftApMode(mInterfaceName);
@@ -6993,13 +7005,14 @@
                 transitionTo(mInitialState);
                 return;
             }
-            */
+
             checkAndSetConnectivityInstance();
             mSoftApManager = mWifiInjector.makeSoftApManager(mNwService,
                                                              new SoftApListener(),
                                                              config);
             mSoftApManager.start();
             mWifiStateTracker.updateState(WifiStateTracker.SOFT_AP);
+            */
         }
 
         @Override
@@ -7018,7 +7031,8 @@
                     /* Ignore start command when it is starting/started. */
                     break;
                 case CMD_STOP_AP:
-                    mSoftApManager.stop();
+                    //mSoftApManager.stop();
+                    transitionTo(mInitialState);
                     break;
                 case CMD_START_AP_FAILURE:
                     transitionTo(mInitialState);
diff --git a/service/java/com/android/server/wifi/WifiStateMachinePrime.java b/service/java/com/android/server/wifi/WifiStateMachinePrime.java
index 35cb7e5..2d3aaba 100644
--- a/service/java/com/android/server/wifi/WifiStateMachinePrime.java
+++ b/service/java/com/android/server/wifi/WifiStateMachinePrime.java
@@ -205,6 +205,7 @@
         }
 
         private void cleanup() {
+            mWifiNative.disableSupplicant();
             mWifiNative.tearDown();
         }
 
@@ -252,6 +253,9 @@
 
             @Override
             public void enter() {
+                // For now - need to clean up from other mode management in WSM
+                cleanup();
+
                 final Message message = mModeStateMachine.getCurrentMessage();
                 if (message.what != ModeStateMachine.CMD_START_SOFT_AP_MODE) {
                     Log.d(TAG, "Entering SoftAPMode (idle)");
@@ -275,7 +279,8 @@
                         // not in active state, nothing to stop.
                         break;
                     case CMD_START_AP_FAILURE:
-                        Log.e(TAG, "Failed to start SoftApMode.  Wait for next mode command.");
+                        // with interface management in softapmanager, no setup failures can be seen
+                        // here
                         break;
                     case CMD_AP_STOPPED:
                         Log.d(TAG, "SoftApModeActiveState stopped.  Wait for next mode command.");
@@ -288,7 +293,9 @@
 
             @Override
             public void exit() {
-                cleanup();
+                // while in transition, cleanup is done on entering states.  in the future, each
+                // mode will clean up their own state on exit
+                //cleanup();
             }
 
             private void initializationFailed(String message) {
@@ -300,8 +307,9 @@
         class WifiDisabledState extends State {
             @Override
             public void enter() {
-                // make sure everything is torn down
                 Log.d(TAG, "Entering WifiDisabledState");
+                // make sure everything is torn down
+                cleanup();
             }
 
             @Override
@@ -371,7 +379,7 @@
                 }
                 this.mActiveModeManager = mWifiInjector.makeSoftApManager(mNMService,
                         new SoftApListener(), softApModeConfig);
-                mActiveModeManager.start();
+                this.mActiveModeManager.start();
             }
 
             @Override
diff --git a/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java b/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java
index 4247e24..93db347 100644
--- a/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java
@@ -210,9 +210,8 @@
         when(mApInterface.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
         when(mWifiNative.setupForSoftApMode(eq(TEST_INTERFACE_NAME)))
                 .thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, mApInterface));
+        when(mApInterface.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
 
-        when(mApInterface.startHostapd(any())).thenReturn(true);
-        when(mApInterface.stopHostapd()).thenReturn(true);
         when(mWifiApConfigStore.getApConfiguration()).thenReturn(null);
         SoftApModeConfiguration nullApConfig =
                 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null);
@@ -579,8 +578,6 @@
         when(mWifiNative.setupForSoftApMode(eq(TEST_INTERFACE_NAME)))
                 .thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, mApInterface));
 
-        when(mApInterface.startHostapd(any())).thenReturn(true);
-        when(mApInterface.stopHostapd()).thenReturn(true);
         when(mWifiNative.isHalStarted()).thenReturn(true);
 
         SoftApManager newSoftApManager = new SoftApManager(mContext,
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiControllerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiControllerTest.java
index 8da09ca..9d5054e 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiControllerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiControllerTest.java
@@ -460,11 +460,13 @@
     public void testRestartWifiStackDoesNotExitAPMode() throws Exception {
         mWifiController.obtainMessage(CMD_SET_AP, 1).sendToTarget();
         mLooper.dispatchAll();
+        verify(mWifiStateMachinePrime).enterSoftAPMode(any());
         assertEquals("ApEnabledState", getCurrentState().getName());
 
         reset(mWifiStateMachine);
         mWifiController.sendMessage(CMD_RESTART_WIFI);
         mLooper.dispatchAll();
         verifyZeroInteractions(mWifiStateMachine);
+        verify(mWifiStateMachinePrime, never()).disableWifi();
     }
 }
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
index e1e4568..5208c74 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
@@ -40,7 +40,6 @@
 import android.net.NetworkRequest;
 import android.net.dhcp.DhcpClient;
 import android.net.ip.IpClient;
-import android.net.wifi.IApInterface;
 import android.net.wifi.IClientInterface;
 import android.net.wifi.IWificond;
 import android.net.wifi.ScanResult;
@@ -343,7 +342,6 @@
     @Mock PropertyService mPropertyService;
     @Mock BuildProperties mBuildProperties;
     @Mock IWificond mWificond;
-    @Mock IApInterface mApInterface;
     @Mock IClientInterface mClientInterface;
     @Mock IBinder mPackageManagerBinder;
     @Mock WifiConfigManager mWifiConfigManager;
@@ -395,10 +393,10 @@
         when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner);
         when(mWifiInjector.makeWifiConnectivityManager(any(WifiInfo.class), anyBoolean()))
                 .thenReturn(mWifiConnectivityManager);
-        when(mWifiInjector.makeSoftApManager(any(INetworkManagementService.class),
-                                             mSoftApManagerListenerCaptor.capture(),
-                                             any(SoftApModeConfiguration.class)))
-                .thenReturn(mSoftApManager);
+        //when(mWifiInjector.makeSoftApManager(any(INetworkManagementService.class),
+        //                                     mSoftApManagerListenerCaptor.capture(),
+        //                                     any(SoftApModeConfiguration.class)))
+        //        .thenReturn(mSoftApManager);
         when(mWifiInjector.getPasspointManager()).thenReturn(mPasspointManager);
         when(mWifiInjector.getWifiStateTracker()).thenReturn(mWifiStateTracker);
         when(mWifiInjector.getWifiMonitor()).thenReturn(mWifiMonitor);
@@ -414,7 +412,9 @@
 
         when(mWifiNative.setupForClientMode(WIFI_IFACE_NAME))
                 .thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, mClientInterface));
-        when(mApInterface.getInterfaceName()).thenReturn(WIFI_IFACE_NAME);
+        //when(mWifiNative.setupForSoftApMode(WIFI_IFACE_NAME))
+        //        .thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, mApInterface));
+        //when(mApInterface.getInterfaceName()).thenReturn(WIFI_IFACE_NAME);
         when(mWifiNative.getInterfaceName()).thenReturn(WIFI_IFACE_NAME);
         when(mWifiNative.enableSupplicant()).thenReturn(true);
         when(mWifiNative.disableSupplicant()).thenReturn(true);
@@ -570,7 +570,8 @@
 
         assertEquals("SoftApState", getCurrentState().getName());
 
-        verify(mSoftApManager).start();
+        verify(mWifiNative, never()).setupForSoftApMode(WIFI_IFACE_NAME);
+        verify(mSoftApManager, never()).start();
     }
 
     private void setupMockWpsPbc() throws Exception {