Merge "Disable partial scan if firmware roaming control is enabled"
diff --git a/service/java/com/android/server/wifi/SoftApManager.java b/service/java/com/android/server/wifi/SoftApManager.java
index 2200618..6d5fd27 100644
--- a/service/java/com/android/server/wifi/SoftApManager.java
+++ b/service/java/com/android/server/wifi/SoftApManager.java
@@ -38,6 +38,7 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.Pair;
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
@@ -74,8 +75,8 @@
 
     private final Listener mListener;
 
-    private final IApInterface mApInterface;
-    private final String mApInterfaceName;
+    private IApInterface mApInterface;
+    private String mApInterfaceName;
 
     private final INetworkManagementService mNwService;
     private final WifiApConfigStore mWifiApConfigStore;
@@ -114,8 +115,6 @@
                          WifiNative wifiNative,
                          String countryCode,
                          Listener listener,
-                         @NonNull IApInterface apInterface,
-                         @NonNull String ifaceName,
                          INetworkManagementService nms,
                          WifiApConfigStore wifiApConfigStore,
                          @NonNull SoftApModeConfiguration apConfig,
@@ -125,8 +124,6 @@
         mWifiNative = wifiNative;
         mCountryCode = countryCode;
         mListener = listener;
-        mApInterface = apInterface;
-        mApInterfaceName = ifaceName;
         mNwService = nms;
         mWifiApConfigStore = wifiApConfigStore;
         mMode = apConfig.getTargetMode();
@@ -181,6 +178,17 @@
     }
 
     /**
+     * Helper function to increment the appropriate setup failure metrics.
+     */
+    private void incrementMetricsForSetupFailure(int failureReason) {
+        if (failureReason == WifiNative.SETUP_FAILURE_HAL) {
+            mWifiMetrics.incrementNumWifiOnFailureDueToHal();
+        } else if (failureReason == WifiNative.SETUP_FAILURE_WIFICOND) {
+            mWifiMetrics.incrementNumWifiOnFailureDueToWificond();
+        }
+    }
+
+    /**
      * Start a soft AP instance with the given configuration.
      * @param config AP configuration
      * @return integer result code
@@ -227,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");
     }
@@ -293,6 +300,39 @@
             public boolean processMessage(Message message) {
                 switch (message.what) {
                     case CMD_START:
+                        // need to create our interface
+                        mApInterface = null;
+                        Pair<Integer, IApInterface> statusAndInterface =
+                                mWifiNative.setupForSoftApMode(mWifiNative.getInterfaceName());
+                        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);
+                            mWifiMetrics.incrementSoftApStartResult(
+                                    false, WifiManager.SAP_START_FAILURE_GENERAL);
+                            break;
+                        }
+                        try {
+                            mApInterfaceName = mApInterface.getInterfaceName();
+                        } 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);
+                            mWifiMetrics.incrementSoftApStartResult(
+                                    false, WifiManager.SAP_START_FAILURE_GENERAL);
+                            break;
+                        }
+
                         // first a sanity check on the interface name.  If we failed to retrieve it,
                         // we are going to have a hard time setting up routing.
                         if (TextUtils.isEmpty(mApInterfaceName)) {
diff --git a/service/java/com/android/server/wifi/WifiController.java b/service/java/com/android/server/wifi/WifiController.java
index 494ce86..dc98595 100644
--- a/service/java/com/android/server/wifi/WifiController.java
+++ b/service/java/com/android/server/wifi/WifiController.java
@@ -93,6 +93,7 @@
 
     /* References to values tracked in WifiService */
     private final WifiStateMachine mWifiStateMachine;
+    private final WifiStateMachinePrime mWifiStateMachinePrime;
     private final WifiSettingsStore mSettingsStore;
     private final WifiLockManager mWifiLockManager;
 
@@ -143,11 +144,13 @@
     private EcmState mEcmState = new EcmState();
 
     WifiController(Context context, WifiStateMachine wsm, WifiSettingsStore wss,
-            WifiLockManager wifiLockManager, Looper looper, FrameworkFacade f) {
+            WifiLockManager wifiLockManager, Looper looper, FrameworkFacade f,
+            WifiStateMachinePrime wsmp) {
         super(TAG, looper);
         mFacade = f;
         mContext = context;
         mWifiStateMachine = wsm;
+        mWifiStateMachinePrime = wsmp;
         mSettingsStore = wss;
         mWifiLockManager = wifiLockManager;
 
@@ -435,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;
@@ -481,6 +485,7 @@
                         }
                         mWifiStateMachine.setHostApRunning((SoftApModeConfiguration) msg.obj,
                                 true);
+                        mWifiStateMachinePrime.enterSoftAPMode((SoftApModeConfiguration) msg.obj);
                         transitionTo(mApEnabledState);
                     }
                     break;
@@ -565,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:
@@ -630,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:
@@ -701,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
@@ -736,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/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index dc48163..9c9622c 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -21,7 +21,6 @@
 import android.content.Context;
 import android.net.NetworkKey;
 import android.net.NetworkScoreManager;
-import android.net.wifi.IApInterface;
 import android.net.wifi.IWifiScanner;
 import android.net.wifi.IWificond;
 import android.net.wifi.WifiInfo;
@@ -84,6 +83,7 @@
     private final SupplicantP2pIfaceHal mSupplicantP2pIfaceHal;
     private final WifiVendorHal mWifiVendorHal;
     private final WifiStateMachine mWifiStateMachine;
+    private final WifiStateMachinePrime mWifiStateMachinePrime;
     private final WifiSettingsStore mSettingsStore;
     private final OpenNetworkNotifier mOpenNetworkNotifier;
     private final WifiLockManager mLockManager;
@@ -224,6 +224,11 @@
                 wifiStateMachineLooper, UserManager.get(mContext),
                 this, mBackupManagerProxy, mCountryCode, mWifiNative,
                 new WrongPasswordNotifier(mContext, mFrameworkFacade));
+        IBinder b = mFrameworkFacade.getService(Context.NETWORKMANAGEMENT_SERVICE);
+        INetworkManagementService networkManagementService =
+                INetworkManagementService.Stub.asInterface(b);
+        mWifiStateMachinePrime = new WifiStateMachinePrime(this, wifiStateMachineLooper,
+                mWifiNative, networkManagementService);
         mOpenNetworkNotifier = new OpenNetworkNotifier(mContext,
                 mWifiStateMachineHandlerThread.getLooper(), mFrameworkFacade, mClock, mWifiMetrics,
                 mWifiConfigManager, mWifiConfigStore, mWifiStateMachine,
@@ -234,7 +239,8 @@
                 mWifiConfigManager, mWifiConfigStore, mFrameworkFacade);
         mLockManager = new WifiLockManager(mContext, BatteryStatsService.getService());
         mWifiController = new WifiController(mContext, mWifiStateMachine, mSettingsStore,
-                mLockManager, mWifiServiceHandlerThread.getLooper(), mFrameworkFacade);
+                mLockManager, mWifiServiceHandlerThread.getLooper(), mFrameworkFacade,
+                mWifiStateMachinePrime);
         mSelfRecovery = new SelfRecovery(mWifiController, mClock);
         mWifiLastResortWatchdog = new WifiLastResortWatchdog(mSelfRecovery, mWifiMetrics);
         mWifiMulticastLockManager = new WifiMulticastLockManager(mWifiStateMachine,
@@ -299,6 +305,10 @@
         return mWifiStateMachine;
     }
 
+    public WifiStateMachinePrime getWifiStateMachinePrime() {
+        return mWifiStateMachinePrime;
+    }
+
     public WifiSettingsStore getWifiSettingsStore() {
         return mSettingsStore;
     }
@@ -371,19 +381,15 @@
      * @param nmService NetworkManagementService allowing SoftApManager to listen for interface
      * changes
      * @param listener listener for SoftApManager
-     * @param apInterface network interface to start hostapd against
-     * @param ifaceName name of the ap interface
      * @param config SoftApModeConfiguration object holding the config and mode
      * @return an instance of SoftApManager
      */
     public SoftApManager makeSoftApManager(INetworkManagementService nmService,
                                            SoftApManager.Listener listener,
-                                           @NonNull IApInterface apInterface,
-                                           @NonNull String ifaceName,
                                            @NonNull SoftApModeConfiguration config) {
         return new SoftApManager(mContext, mWifiStateMachineHandlerThread.getLooper(),
-                mFrameworkFacade, mWifiNative, mCountryCode.getCountryCode(), listener, apInterface,
-                ifaceName, nmService, mWifiApConfigStore, config, mWifiMetrics);
+                mFrameworkFacade, mWifiNative, mCountryCode.getCountryCode(), listener,
+                nmService, mWifiApConfigStore, config, mWifiMetrics);
     }
 
     /**
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index 0fb4bfb..2724cb5 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -97,6 +97,7 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
+import android.util.MutableInt;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
@@ -199,6 +200,18 @@
     private final ConcurrentHashMap<String, Integer> mIfaceIpModes;
 
     /**
+     * One of:  {@link WifiManager#WIFI_AP_STATE_DISABLED},
+     *          {@link WifiManager#WIFI_AP_STATE_DISABLING},
+     *          {@link WifiManager#WIFI_AP_STATE_ENABLED},
+     *          {@link WifiManager#WIFI_AP_STATE_ENABLING},
+     *          {@link WifiManager#WIFI_AP_STATE_FAILED}
+     *
+     * Access/maintenance MUST be done on the wifi service thread
+     */
+    private int mWifiApState = WifiManager.WIFI_AP_STATE_DISABLED;
+
+
+    /**
      * Callback for use with LocalOnlyHotspot to unregister requesting applications upon death.
      *
      * @hide
@@ -787,8 +800,7 @@
         }
 
         // If SoftAp is enabled, only Settings is allowed to toggle wifi
-        boolean apEnabled =
-                mWifiStateMachine.syncGetWifiApState() != WifiManager.WIFI_AP_STATE_DISABLED;
+        boolean apEnabled = mWifiApState != WifiManager.WIFI_AP_STATE_DISABLED;
 
         if (apEnabled && !isFromSettings) {
             mLog.info("setWifiEnabled SoftAp not disabled: only Settings can enable wifi").flush();
@@ -860,7 +872,13 @@
     public int getWifiApEnabledState() {
         enforceAccessPermission();
         mLog.info("getWifiApEnabledState uid=%").c(Binder.getCallingUid()).flush();
-        return mWifiStateMachine.syncGetWifiApState();
+
+        // hand off work to our handler thread
+        MutableInt apState = new MutableInt(WifiManager.WIFI_AP_STATE_DISABLED);
+        mClientHandler.runWithScissors(() -> {
+            apState.value = mWifiApState;
+        }, 0);
+        return apState.value;
     }
 
     /**
@@ -1021,6 +1039,8 @@
 
     /**
      * Private method to handle SoftAp state changes
+     *
+     * <p> MUST be called from the WifiStateMachine thread.
      */
     private void handleWifiApStateChange(
             int currentState, int previousState, int errorCode, String ifaceName, int mode) {
@@ -1029,6 +1049,9 @@
                 + " previousState=" + previousState + " errorCode= " + errorCode
                 + " ifaceName=" + ifaceName + " mode=" + mode);
 
+        // update the tracking ap state variable
+        mWifiApState = currentState;
+
         // check if we have a failure - since it is possible (worst case scenario where
         // WifiController and WifiStateMachine are out of sync wrt modes) to get two FAILED
         // notifications in a row, we need to handle this first.
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index 1521bb9..505a09b 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -57,7 +57,6 @@
 import android.net.TrafficStats;
 import android.net.dhcp.DhcpClient;
 import android.net.ip.IpClient;
-import android.net.wifi.IApInterface;
 import android.net.wifi.IClientInterface;
 import android.net.wifi.RssiPacketCountInfo;
 import android.net.wifi.ScanResult;
@@ -1676,9 +1675,9 @@
     /**
      * TODO: doc
      */
-    public int syncGetWifiApState() {
-        return mWifiApState.get();
-    }
+    //public int syncGetWifiApState() {
+    //    return mWifiApState.get();
+    //}
 
     /**
      * TODO: doc
@@ -2920,6 +2919,7 @@
         // Update state
         mWifiApState.set(wifiApState);
 
+        // TODO: when this code is removed, also remove syncGetWifiApStateByName()
         if (mVerboseLoggingEnabled) log("setWifiApState: " + syncGetWifiApStateByName());
     }
 
@@ -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,6 +6975,7 @@
             if (message.what != CMD_START_AP) {
                 throw new RuntimeException("Illegal transition to SoftApState: " + message);
             }
+            /*
             SoftApModeConfiguration config = (SoftApModeConfiguration) message.obj;
             mMode = config.getTargetMode();
 
@@ -6997,11 +7009,10 @@
             checkAndSetConnectivityInstance();
             mSoftApManager = mWifiInjector.makeSoftApManager(mNwService,
                                                              new SoftApListener(),
-                                                             apInterface,
-                                                             mIfaceName,
                                                              config);
             mSoftApManager.start();
             mWifiStateTracker.updateState(WifiStateTracker.SOFT_AP);
+            */
         }
 
         @Override
@@ -7020,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 de970ee..2d3aaba 100644
--- a/service/java/com/android/server/wifi/WifiStateMachinePrime.java
+++ b/service/java/com/android/server/wifi/WifiStateMachinePrime.java
@@ -17,15 +17,12 @@
 package com.android.server.wifi;
 
 import android.annotation.NonNull;
-import android.net.wifi.IApInterface;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
 import android.os.INetworkManagementService;
 import android.os.Looper;
 import android.os.Message;
-import android.os.RemoteException;
 import android.util.Log;
-import android.util.Pair;
 
 import com.android.internal.util.Protocol;
 import com.android.internal.util.State;
@@ -208,6 +205,7 @@
         }
 
         private void cleanup() {
+            mWifiNative.disableSupplicant();
             mWifiNative.tearDown();
         }
 
@@ -252,43 +250,18 @@
         }
 
         class SoftAPModeState extends State {
-            IApInterface mApInterface = null;
-            String mIfaceName = null;
 
             @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)");
                     return;
                 }
 
-                // Continue with setup since we are changing modes
-                mApInterface = null;
-
-                Pair<Integer, IApInterface> statusAndInterface =
-                        mWifiNative.setupForSoftApMode(mInterfaceName);
-                if (statusAndInterface.first == WifiNative.SETUP_SUCCESS) {
-                    mApInterface = statusAndInterface.second;
-                } else {
-                    // TODO: incorporate metrics - or this particular one will be done in WifiNative
-                    //incrementMetricsForSetupFailure(statusAndInterface.first);
-                }
-                if (mApInterface == null) {
-                    // TODO: update battery stats that a failure occured - best to do in
-                    // initialization Failed.  Keeping line copied from WSM for a reference
-                    //setWifiApState(WIFI_AP_STATE_FAILED,
-                    //        WifiManager.SAP_START_FAILURE_GENERAL, null, mMode);
-                    initializationFailed("Could not get IApInterface instance");
-                    return;
-                }
-
-                try {
-                    mIfaceName = mApInterface.getInterfaceName();
-                } catch (RemoteException e) {
-                    initializationFailed("Could not get IApInterface name");
-                    return;
-                }
                 mModeStateMachine.transitionTo(mSoftAPModeActiveState);
             }
 
@@ -306,9 +279,8 @@
                         // not in active state, nothing to stop.
                         break;
                     case CMD_START_AP_FAILURE:
-                        // remove the saved config for the start attempt
-                        mApConfigQueue.poll();
-                        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.");
@@ -321,15 +293,9 @@
 
             @Override
             public void exit() {
-                cleanup();
-            }
-
-            protected IApInterface getInterface() {
-                return mApInterface;
-            }
-
-            protected String getInterfaceName() {
-                return mIfaceName;
+                // 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) {
@@ -341,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
@@ -411,9 +378,8 @@
                     config = null;
                 }
                 this.mActiveModeManager = mWifiInjector.makeSoftApManager(mNMService,
-                        new SoftApListener(), ((SoftAPModeState) mSoftAPModeState).getInterface(),
-                        ((SoftAPModeState) mSoftAPModeState).getInterfaceName(), softApModeConfig);
-                mActiveModeManager.start();
+                        new SoftApListener(), softApModeConfig);
+                this.mActiveModeManager.start();
             }
 
             @Override
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java b/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java
index 62cc3ec..e609c86 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java
@@ -242,7 +242,8 @@
         if (publishConfig == null) {
             throw new IllegalArgumentException("PublishConfig must not be null");
         }
-        publishConfig.assertValid(mStateManager.getCharacteristics());
+        publishConfig.assertValid(mStateManager.getCharacteristics(),
+                mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT));
 
         int uid = getMockableCallingUid();
         enforceClientValidity(uid, clientId);
@@ -262,7 +263,8 @@
         if (publishConfig == null) {
             throw new IllegalArgumentException("PublishConfig must not be null");
         }
-        publishConfig.assertValid(mStateManager.getCharacteristics());
+        publishConfig.assertValid(mStateManager.getCharacteristics(),
+                mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT));
 
         int uid = getMockableCallingUid();
         enforceClientValidity(uid, clientId);
@@ -287,7 +289,8 @@
         if (subscribeConfig == null) {
             throw new IllegalArgumentException("SubscribeConfig must not be null");
         }
-        subscribeConfig.assertValid(mStateManager.getCharacteristics());
+        subscribeConfig.assertValid(mStateManager.getCharacteristics(),
+                mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT));
 
         int uid = getMockableCallingUid();
         enforceClientValidity(uid, clientId);
@@ -307,7 +310,8 @@
         if (subscribeConfig == null) {
             throw new IllegalArgumentException("SubscribeConfig must not be null");
         }
-        subscribeConfig.assertValid(mStateManager.getCharacteristics());
+        subscribeConfig.assertValid(mStateManager.getCharacteristics(),
+                mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT));
 
         int uid = getMockableCallingUid();
         enforceClientValidity(uid, clientId);
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointConfigStoreData.java b/service/java/com/android/server/wifi/hotspot2/PasspointConfigStoreData.java
index 38401d2..553a38b 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointConfigStoreData.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointConfigStoreData.java
@@ -307,6 +307,7 @@
         String clientCertificateAlias = null;
         String clientPrivateKeyAlias = null;
         boolean hasEverConnected = false;
+        boolean shared = false;
         PasspointConfiguration config = null;
         while (XmlUtils.nextElementWithin(in, outerTagDepth)) {
             if (in.getAttributeValue(null, "name") != null) {
@@ -351,7 +352,7 @@
         }
         return new PasspointProvider(config, mKeyStore, mSimAccessor, providerId, creatorUid,
                 caCertificateAlias, clientCertificateAlias, clientPrivateKeyAlias,
-                hasEverConnected);
+                hasEverConnected, shared);
     }
 
     /**
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
index fec3dd8..d29d00a 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
@@ -720,7 +720,7 @@
                 mSimAccessor, mProviderIndex++, wifiConfig.creatorUid,
                 enterpriseConfig.getCaCertificateAlias(),
                 enterpriseConfig.getClientCertificateAlias(),
-                enterpriseConfig.getClientCertificateAlias(), false);
+                enterpriseConfig.getClientCertificateAlias(), false, false);
         mProviders.put(passpointConfig.getHomeSp().getFqdn(), provider);
         return true;
     }
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java b/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java
index c7943ed..23ab57f 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java
@@ -88,16 +88,17 @@
     private final AuthParam mAuthParam;
 
     private boolean mHasEverConnected;
+    private boolean mIsShared;
 
     public PasspointProvider(PasspointConfiguration config, WifiKeyStore keyStore,
             SIMAccessor simAccessor, long providerId, int creatorUid) {
-        this(config, keyStore, simAccessor, providerId, creatorUid, null, null, null, false);
+        this(config, keyStore, simAccessor, providerId, creatorUid, null, null, null, false, false);
     }
 
     public PasspointProvider(PasspointConfiguration config, WifiKeyStore keyStore,
             SIMAccessor simAccessor, long providerId, int creatorUid, String caCertificateAlias,
             String clientCertificateAlias, String clientPrivateKeyAlias,
-            boolean hasEverConnected) {
+            boolean hasEverConnected, boolean isShared) {
         // Maintain a copy of the configuration to avoid it being updated by others.
         mConfig = new PasspointConfiguration(config);
         mKeyStore = keyStore;
@@ -107,6 +108,7 @@
         mClientCertificateAlias = clientCertificateAlias;
         mClientPrivateKeyAlias = clientPrivateKeyAlias;
         mHasEverConnected = hasEverConnected;
+        mIsShared = isShared;
 
         // Setup EAP method and authentication parameter based on the credential.
         if (mConfig.getCredential().getUserCredential() != null) {
@@ -311,6 +313,7 @@
                     mConfig.getCredential().getSimCredential());
         }
         wifiConfig.enterpriseConfig = enterpriseConfig;
+        wifiConfig.shared = mIsShared;
         return wifiConfig;
     }
 
diff --git a/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java b/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java
index 0c35904..93db347 100644
--- a/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java
@@ -44,10 +44,12 @@
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
 import android.os.INetworkManagementService;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.test.TestLooper;
 import android.provider.Settings;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Pair;
 
 import com.android.internal.R;
 import com.android.internal.util.WakeupMessage;
@@ -143,8 +145,6 @@
                                                            mWifiNative,
                                                            TEST_COUNTRY_CODE,
                                                            mListener,
-                                                           mApInterface,
-                                                           TEST_INTERFACE_NAME,
                                                            mNmService,
                                                            mWifiApConfigStore,
                                                            config,
@@ -206,6 +206,12 @@
     /** Tests softap startup if default config fails to load. **/
     @Test
     public void startSoftApDefaultConfigFailedToLoad() throws Exception {
+        when(mWifiNative.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
+        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(mWifiApConfigStore.getApConfiguration()).thenReturn(null);
         SoftApModeConfiguration nullApConfig =
                 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null);
@@ -215,8 +221,6 @@
                                                            mWifiNative,
                                                            TEST_COUNTRY_CODE,
                                                            mListener,
-                                                           mApInterface,
-                                                           TEST_INTERFACE_NAME,
                                                            mNmService,
                                                            mWifiApConfigStore,
                                                            nullApConfig,
@@ -240,6 +244,324 @@
     }
 
     /**
+     * Test that failure to create the SoftApInterface increments the corresponding metrics and
+     * proper state updates are sent out.
+     */
+    @Test
+    public void testSetupForSoftApModeHalFailureIncrementsMetrics() throws Exception {
+        when(mWifiNative.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
+        when(mWifiNative.setupForSoftApMode(TEST_INTERFACE_NAME))
+                .thenReturn(Pair.create(WifiNative.SETUP_FAILURE_HAL, null));
+
+        SoftApModeConfiguration config = new SoftApModeConfiguration(
+                WifiManager.IFACE_IP_MODE_TETHERED, new WifiConfiguration());
+
+        when(mWifiApConfigStore.getApConfiguration()).thenReturn(null);
+        SoftApModeConfiguration nullApConfig =
+                new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null);
+        SoftApManager newSoftApManager = new SoftApManager(mContext,
+                                                           mLooper.getLooper(),
+                                                           mFrameworkFacade,
+                                                           mWifiNative,
+                                                           TEST_COUNTRY_CODE,
+                                                           mListener,
+                                                           mNmService,
+                                                           mWifiApConfigStore,
+                                                           nullApConfig,
+                                                           mWifiMetrics);
+        mLooper.dispatchAll();
+        newSoftApManager.start();
+        mLooper.dispatchAll();
+        verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED,
+                WifiManager.SAP_START_FAILURE_GENERAL);
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContext).sendStickyBroadcastAsUser(intentCaptor.capture(),
+                eq(UserHandle.ALL));
+
+        checkApStateChangedBroadcast(intentCaptor.getValue(), WIFI_AP_STATE_FAILED,
+                WIFI_AP_STATE_DISABLED, WifiManager.SAP_START_FAILURE_GENERAL, null,
+                nullApConfig.getTargetMode());
+
+        verify(mWifiMetrics).incrementNumWifiOnFailureDueToHal();
+    }
+
+    /**
+     * Test that failure to create the SoftApInterface due to a wificond error increments
+     * the corresponding metrics and proper state updates are sent out.
+     */
+    @Test
+    public void testSetupForSoftApModeWificondFailureIncrementsMetrics() throws Exception {
+        when(mWifiNative.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
+        when(mWifiNative.setupForSoftApMode(TEST_INTERFACE_NAME))
+                .thenReturn(Pair.create(WifiNative.SETUP_FAILURE_WIFICOND, null));
+
+        SoftApModeConfiguration config = new SoftApModeConfiguration(
+                WifiManager.IFACE_IP_MODE_TETHERED, new WifiConfiguration());
+
+        when(mWifiApConfigStore.getApConfiguration()).thenReturn(null);
+        SoftApModeConfiguration nullApConfig =
+                new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null);
+        SoftApManager newSoftApManager = new SoftApManager(mContext,
+                                                           mLooper.getLooper(),
+                                                           mFrameworkFacade,
+                                                           mWifiNative,
+                                                           TEST_COUNTRY_CODE,
+                                                           mListener,
+                                                           mNmService,
+                                                           mWifiApConfigStore,
+                                                           nullApConfig,
+                                                           mWifiMetrics);
+        mLooper.dispatchAll();
+        newSoftApManager.start();
+        mLooper.dispatchAll();
+        verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED,
+                WifiManager.SAP_START_FAILURE_GENERAL);
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContext).sendStickyBroadcastAsUser(intentCaptor.capture(),
+                eq(UserHandle.ALL));
+
+        checkApStateChangedBroadcast(intentCaptor.getValue(), WIFI_AP_STATE_FAILED,
+                WIFI_AP_STATE_DISABLED, WifiManager.SAP_START_FAILURE_GENERAL, null,
+                nullApConfig.getTargetMode());
+
+        verify(mWifiMetrics).incrementNumWifiOnFailureDueToWificond();
+    }
+
+    /**
+     * Test that failure to retrieve the SoftApInterface increments the corresponding metrics
+     * and proper state updates are sent out.
+     */
+    @Test
+    public void testSetupForSoftApModeNullApInterfaceFailureIncrementsMetrics() throws Exception {
+        when(mWifiNative.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
+        when(mWifiNative.setupForSoftApMode(eq(TEST_INTERFACE_NAME)))
+                .thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, null));
+
+        SoftApModeConfiguration config = new SoftApModeConfiguration(
+                WifiManager.IFACE_IP_MODE_TETHERED, new WifiConfiguration());
+
+        when(mWifiApConfigStore.getApConfiguration()).thenReturn(null);
+        SoftApModeConfiguration nullApConfig =
+                new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null);
+        SoftApManager newSoftApManager = new SoftApManager(mContext,
+                                                           mLooper.getLooper(),
+                                                           mFrameworkFacade,
+                                                           mWifiNative,
+                                                           TEST_COUNTRY_CODE,
+                                                           mListener,
+                                                           mNmService,
+                                                           mWifiApConfigStore,
+                                                           nullApConfig,
+                                                           mWifiMetrics);
+        mLooper.dispatchAll();
+        newSoftApManager.start();
+        mLooper.dispatchAll();
+        verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED,
+                WifiManager.SAP_START_FAILURE_GENERAL);
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContext).sendStickyBroadcastAsUser(intentCaptor.capture(),
+                eq(UserHandle.ALL));
+
+        checkApStateChangedBroadcast(intentCaptor.getValue(), WIFI_AP_STATE_FAILED,
+                WIFI_AP_STATE_DISABLED, WifiManager.SAP_START_FAILURE_GENERAL, null,
+                nullApConfig.getTargetMode());
+
+        verify(mWifiMetrics).incrementSoftApStartResult(false,
+                WifiManager.SAP_START_FAILURE_GENERAL);
+    }
+
+    /**
+     * Test that an empty SoftApInterface name is detected as a failure and increments the
+     * corresponding metrics and proper state updates are sent out.
+     */
+    @Test
+    public void testSetupForSoftApModeEmptyInterfaceNameFailureIncrementsMetrics()
+            throws Exception {
+        when(mWifiNative.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
+        when(mApInterface.getInterfaceName()).thenReturn("");
+        when(mWifiNative.setupForSoftApMode(eq(TEST_INTERFACE_NAME)))
+                .thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, mApInterface));
+
+        SoftApModeConfiguration config = new SoftApModeConfiguration(
+                WifiManager.IFACE_IP_MODE_TETHERED, new WifiConfiguration());
+
+        when(mWifiApConfigStore.getApConfiguration()).thenReturn(null);
+        SoftApModeConfiguration nullApConfig =
+                new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null);
+        SoftApManager newSoftApManager = new SoftApManager(mContext,
+                                                           mLooper.getLooper(),
+                                                           mFrameworkFacade,
+                                                           mWifiNative,
+                                                           TEST_COUNTRY_CODE,
+                                                           mListener,
+                                                           mNmService,
+                                                           mWifiApConfigStore,
+                                                           nullApConfig,
+                                                           mWifiMetrics);
+        mLooper.dispatchAll();
+        newSoftApManager.start();
+        mLooper.dispatchAll();
+        verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED,
+                WifiManager.SAP_START_FAILURE_GENERAL);
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContext).sendStickyBroadcastAsUser(intentCaptor.capture(),
+                eq(UserHandle.ALL));
+
+        checkApStateChangedBroadcast(intentCaptor.getValue(), WIFI_AP_STATE_FAILED,
+                WIFI_AP_STATE_DISABLED, WifiManager.SAP_START_FAILURE_GENERAL, "",
+                nullApConfig.getTargetMode());
+
+        verify(mWifiMetrics).incrementSoftApStartResult(false,
+                WifiManager.SAP_START_FAILURE_GENERAL);
+    }
+
+    /**
+     * Test that catching a RemoteException when retrieving the SoftApInterface name
+     * is detected as a failure and increments the corresponding metrics and proper
+     * state updates are sent out.
+     */
+    @Test
+    public void testSetupForSoftApModeInterfaceNameRemoteExceptionFailureIncrementsMetrics()
+            throws Exception {
+        when(mWifiNative.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
+        doThrow(new RemoteException()).when(mApInterface).getInterfaceName();
+        when(mWifiNative.setupForSoftApMode(eq(TEST_INTERFACE_NAME)))
+                .thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, mApInterface));
+
+        SoftApModeConfiguration config = new SoftApModeConfiguration(
+                WifiManager.IFACE_IP_MODE_TETHERED, new WifiConfiguration());
+
+        when(mWifiApConfigStore.getApConfiguration()).thenReturn(null);
+        SoftApModeConfiguration nullApConfig =
+                new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null);
+        SoftApManager newSoftApManager = new SoftApManager(mContext,
+                                                           mLooper.getLooper(),
+                                                           mFrameworkFacade,
+                                                           mWifiNative,
+                                                           TEST_COUNTRY_CODE,
+                                                           mListener,
+                                                           mNmService,
+                                                           mWifiApConfigStore,
+                                                           nullApConfig,
+                                                           mWifiMetrics);
+        mLooper.dispatchAll();
+        newSoftApManager.start();
+        mLooper.dispatchAll();
+        verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED,
+                WifiManager.SAP_START_FAILURE_GENERAL);
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContext).sendStickyBroadcastAsUser(intentCaptor.capture(),
+                eq(UserHandle.ALL));
+
+        checkApStateChangedBroadcast(intentCaptor.getValue(), WIFI_AP_STATE_FAILED,
+                WIFI_AP_STATE_DISABLED, WifiManager.SAP_START_FAILURE_GENERAL, null,
+                nullApConfig.getTargetMode());
+
+        verify(mWifiMetrics).incrementSoftApStartResult(false,
+                WifiManager.SAP_START_FAILURE_GENERAL);
+    }
+
+
+    /**
+     * Tests that the generic error is propagated and properly reported when starting softap and we
+     * cannot register a wificond death handler.
+     */
+    @Test
+    public void startSoftApFailRegisterWificondDeathHandlerGeneralError() throws Exception {
+        WifiConfiguration config = new WifiConfiguration();
+        config.apBand = WifiConfiguration.AP_BAND_5GHZ;
+        config.SSID = TEST_SSID;
+        SoftApModeConfiguration softApConfig =
+                new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, config);
+
+        when(mWifiNative.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
+        when(mApInterface.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
+        when(mWifiNative.setupForSoftApMode(eq(TEST_INTERFACE_NAME)))
+                .thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, mApInterface));
+
+        when(mWifiNative.registerWificondDeathHandler(any())).thenReturn(false);
+
+        SoftApManager newSoftApManager = new SoftApManager(mContext,
+                                                           mLooper.getLooper(),
+                                                           mFrameworkFacade,
+                                                           mWifiNative,
+                                                           null,
+                                                           mListener,
+                                                           mNmService,
+                                                           mWifiApConfigStore,
+                                                           softApConfig,
+                                                           mWifiMetrics);
+        mLooper.dispatchAll();
+        newSoftApManager.start();
+        mLooper.dispatchAll();
+
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContext, times(2)).sendStickyBroadcastAsUser(intentCaptor.capture(),
+                eq(UserHandle.ALL));
+
+        List<Intent> capturedIntents = intentCaptor.getAllValues();
+        checkApStateChangedBroadcast(capturedIntents.get(0), WIFI_AP_STATE_ENABLING,
+                WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME,
+                softApConfig.getTargetMode());
+        checkApStateChangedBroadcast(capturedIntents.get(1), WIFI_AP_STATE_FAILED,
+                WIFI_AP_STATE_ENABLING, WifiManager.SAP_START_FAILURE_GENERAL, TEST_INTERFACE_NAME,
+                softApConfig.getTargetMode());
+        verify(mWifiMetrics).incrementSoftApStartResult(false,
+                WifiManager.SAP_START_FAILURE_GENERAL);
+    }
+
+    /**
+     * Tests that the generic error is propagated and properly reported when starting softap and we
+     * catch a RemoteException when attempting to register a NetworkObserver.
+     */
+    @Test
+    public void startSoftApFailNetworkObserverRemoteExceptionGeneralError() throws Exception {
+        WifiConfiguration config = new WifiConfiguration();
+        config.apBand = WifiConfiguration.AP_BAND_5GHZ;
+        config.SSID = TEST_SSID;
+        SoftApModeConfiguration softApConfig =
+                new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, config);
+
+        when(mWifiNative.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
+        when(mApInterface.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
+        when(mWifiNative.setupForSoftApMode(eq(TEST_INTERFACE_NAME)))
+                .thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, mApInterface));
+
+        doThrow(new RemoteException()).when(mNmService).registerObserver(any());
+
+        SoftApManager newSoftApManager = new SoftApManager(mContext,
+                                                           mLooper.getLooper(),
+                                                           mFrameworkFacade,
+                                                           mWifiNative,
+                                                           null,
+                                                           mListener,
+                                                           mNmService,
+                                                           mWifiApConfigStore,
+                                                           softApConfig,
+                                                           mWifiMetrics);
+        mLooper.dispatchAll();
+        newSoftApManager.start();
+        mLooper.dispatchAll();
+
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContext, times(2)).sendStickyBroadcastAsUser(intentCaptor.capture(),
+                eq(UserHandle.ALL));
+
+        List<Intent> capturedIntents = intentCaptor.getAllValues();
+        checkApStateChangedBroadcast(capturedIntents.get(0), WIFI_AP_STATE_ENABLING,
+                WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME,
+                softApConfig.getTargetMode());
+        checkApStateChangedBroadcast(capturedIntents.get(1), WIFI_AP_STATE_FAILED,
+                WIFI_AP_STATE_ENABLING, WifiManager.SAP_START_FAILURE_GENERAL, TEST_INTERFACE_NAME,
+                softApConfig.getTargetMode());
+        // we do once on enter of idle, and another after the failure
+        verify(mWifiNative, times(2)).deregisterWificondDeathHandler();
+        verify(mNmService).unregisterObserver(any());
+        verify(mWifiMetrics).incrementSoftApStartResult(false,
+                WifiManager.SAP_START_FAILURE_GENERAL);
+    }
+
+    /**
      * Tests that the generic error is propagated and properly reported when starting softap and the
      * specified channel cannot be used.
      */
@@ -251,6 +573,11 @@
         SoftApModeConfiguration softApConfig =
                 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, config);
 
+        when(mWifiNative.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
+        when(mApInterface.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
+        when(mWifiNative.setupForSoftApMode(eq(TEST_INTERFACE_NAME)))
+                .thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, mApInterface));
+
         when(mWifiNative.isHalStarted()).thenReturn(true);
 
         SoftApManager newSoftApManager = new SoftApManager(mContext,
@@ -259,8 +586,6 @@
                                                            mWifiNative,
                                                            null,
                                                            mListener,
-                                                           mApInterface,
-                                                           TEST_INTERFACE_NAME,
                                                            mNmService,
                                                            mWifiApConfigStore,
                                                            softApConfig,
@@ -297,14 +622,18 @@
 
         when(mWifiNative.isHalStarted()).thenReturn(true);
 
+        when(mWifiNative.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
+        when(mApInterface.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
+        when(mWifiNative.setupForSoftApMode(eq(TEST_INTERFACE_NAME)))
+                .thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, mApInterface));
+
+
         SoftApManager newSoftApManager = new SoftApManager(mContext,
                                                            mLooper.getLooper(),
                                                            mFrameworkFacade,
                                                            mWifiNative,
                                                            TEST_COUNTRY_CODE,
                                                            mListener,
-                                                           mApInterface,
-                                                           TEST_INTERFACE_NAME,
                                                            mNmService,
                                                            mWifiApConfigStore,
                                                            softApConfig,
@@ -332,6 +661,10 @@
     @Test
     public void startSoftApApInterfaceFailedToStart() throws Exception {
         when(mWifiNative.startSoftAp(any(), any())).thenReturn(false);
+        when(mWifiNative.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
+        when(mWifiNative.setupForSoftApMode(eq(TEST_INTERFACE_NAME)))
+                .thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, mApInterface));
+
         SoftApModeConfiguration softApModeConfig =
                 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, mDefaultApConfig);
 
@@ -341,8 +674,6 @@
                                                            mWifiNative,
                                                            TEST_COUNTRY_CODE,
                                                            mListener,
-                                                           mApInterface,
-                                                           TEST_INTERFACE_NAME,
                                                            mNmService,
                                                            mWifiApConfigStore,
                                                            softApModeConfig,
@@ -632,6 +963,11 @@
                 ContentObserver.class);
         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
 
+        when(mWifiNative.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
+        when(mApInterface.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
+        when(mWifiNative.setupForSoftApMode(eq(TEST_INTERFACE_NAME)))
+                .thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, mApInterface));
+
         mSoftApManager.start();
         mLooper.dispatchAll();
         order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLING, 0);
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiControllerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiControllerTest.java
index c7b6180..9d5054e 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiControllerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiControllerTest.java
@@ -88,6 +88,7 @@
     @Mock FrameworkFacade mFacade;
     @Mock WifiSettingsStore mSettingsStore;
     @Mock WifiStateMachine mWifiStateMachine;
+    @Mock WifiStateMachinePrime mWifiStateMachinePrime;
     @Mock WifiLockManager mWifiLockManager;
     @Mock ContentResolver mContentResolver;
 
@@ -110,7 +111,8 @@
                 ArgumentCaptor.forClass(ContentObserver.class);
 
         mWifiController = new WifiController(mContext, mWifiStateMachine,
-                mSettingsStore, mWifiLockManager, mLooper.getLooper(), mFacade);
+                mSettingsStore, mWifiLockManager, mLooper.getLooper(), mFacade,
+                mWifiStateMachinePrime);
         verify(mFacade, times(3)).registerContentObserver(eq(mContext), any(Uri.class), eq(false),
                 observerCaptor.capture());
 
@@ -367,7 +369,8 @@
         when(mContext.getContentResolver()).thenReturn(mock(ContentResolver.class));
 
         mWifiController = new WifiController(mContext, mWifiStateMachine,
-                mSettingsStore, mWifiLockManager, mLooper.getLooper(), mFacade);
+                mSettingsStore, mWifiLockManager, mLooper.getLooper(), mFacade,
+                mWifiStateMachinePrime);
 
         mWifiController.start();
         mLooper.dispatchAll();
@@ -457,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/WifiServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
index ea81d53..d0a482e 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
@@ -31,6 +31,7 @@
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING;
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
 import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
 import static android.provider.Settings.Secure.LOCATION_MODE_HIGH_ACCURACY;
@@ -45,6 +46,7 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
@@ -370,10 +372,11 @@
     /**
      * Verify that wifi can be enabled by a caller with WIFI_STATE_CHANGE permission when wifi is
      * off (no hotspot, no airplane mode).
+     *
+     * Note: hotspot is disabled by default
      */
     @Test
     public void testSetWifiEnabledSuccess() throws Exception {
-        when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED);
         when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true);
         when(mSettingsStore.isAirplaneModeOn()).thenReturn(false);
         assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
@@ -385,7 +388,6 @@
      */
     @Test
     public void testSetWifiEnabledNoToggle() throws Exception {
-        when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED);
         when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(false);
         assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
         verify(mWifiController, never()).sendMessage(eq(CMD_WIFI_TOGGLED));
@@ -402,7 +404,6 @@
                                                 eq("WifiService"));
         when(mSettingsStore.isAirplaneModeOn()).thenReturn(false);
         mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true);
-        verify(mWifiStateMachine, never()).syncGetWifiApState();
     }
 
     /**
@@ -441,7 +442,17 @@
      */
     @Test
     public void testSetWifiEnabledFromNetworkSettingsHolderWhenApEnabled() throws Exception {
-        when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_ENABLED);
+        when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
+        when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
+        mWifiServiceImpl.checkAndStartWifi();
+
+        verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+                (IntentFilter) argThat(new IntentFilterMatcher()));
+
+        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
+                WIFI_AP_STATE_ENABLED, WIFI_AP_STATE_ENABLING, SAP_START_FAILURE_GENERAL,
+                WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
+
         when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true);
         when(mContext.checkPermission(
                 eq(android.Manifest.permission.NETWORK_SETTINGS), anyInt(), anyInt()))
@@ -456,7 +467,17 @@
      */
     @Test
     public void testSetWifiEnabledFromAppFailsWhenApEnabled() throws Exception {
-        when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_ENABLED);
+        when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
+        when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
+        mWifiServiceImpl.checkAndStartWifi();
+
+        verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+                (IntentFilter) argThat(new IntentFilterMatcher()));
+
+        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
+                WIFI_AP_STATE_ENABLED, WIFI_AP_STATE_ENABLING, SAP_START_FAILURE_GENERAL,
+                WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
+
         when(mContext.checkPermission(
                 eq(android.Manifest.permission.NETWORK_SETTINGS), anyInt(), anyInt()))
                         .thenReturn(PackageManager.PERMISSION_DENIED);
@@ -472,7 +493,6 @@
      */
     @Test
     public void testSetWifiDisabledSuccess() throws Exception {
-        when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED);
         when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(true);
         assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false));
         verify(mWifiController).sendMessage(eq(CMD_WIFI_TOGGLED));
@@ -483,7 +503,6 @@
      */
     @Test
     public void testSetWifiDisabledNoToggle() throws Exception {
-        when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED);
         when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(false);
         assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false));
         verify(mWifiController, never()).sendMessage(eq(CMD_WIFI_TOGGLED));
@@ -495,7 +514,6 @@
      */
     @Test(expected = SecurityException.class)
     public void testSetWifiDisabledWithoutPermission() throws Exception {
-        when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED);
         doThrow(new SecurityException()).when(mContext)
                 .enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE),
                                                 eq("WifiService"));
@@ -560,6 +578,58 @@
     }
 
     /**
+     * Ensure we return the proper variable for the softap state after getting an AP state change
+     * broadcast.
+     */
+    @Test
+    public void testGetWifiApEnabled() {
+        // set up WifiServiceImpl with a live thread for testing
+        HandlerThread serviceHandlerThread = new HandlerThread("ServiceHandlerThreadForTest");
+        serviceHandlerThread.start();
+        when(mWifiInjector.getWifiServiceHandlerThread()).thenReturn(serviceHandlerThread);
+        mWifiServiceImpl = new WifiServiceImpl(mContext, mWifiInjector, mAsyncChannel);
+        mWifiServiceImpl.setWifiHandlerLogForTest(mLog);
+
+        // ap should be disabled when wifi hasn't been started
+        assertEquals(WifiManager.WIFI_AP_STATE_DISABLED, mWifiServiceImpl.getWifiApEnabledState());
+
+        when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
+        when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
+        mWifiServiceImpl.checkAndStartWifi();
+        mLooper.dispatchAll();
+
+        // ap should be disabled initially
+        assertEquals(WifiManager.WIFI_AP_STATE_DISABLED, mWifiServiceImpl.getWifiApEnabledState());
+
+        // send an ap state change to verify WifiServiceImpl is updated
+        verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+                (IntentFilter) argThat(new IntentFilterMatcher()));
+
+        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
+                WIFI_AP_STATE_FAILED, WIFI_AP_STATE_DISABLED, SAP_START_FAILURE_GENERAL,
+                WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
+        mLooper.dispatchAll();
+
+        assertEquals(WifiManager.WIFI_AP_STATE_FAILED, mWifiServiceImpl.getWifiApEnabledState());
+    }
+
+    /**
+     * Ensure we do not allow unpermitted callers to get the wifi ap state.
+     */
+    @Test
+    public void testGetWifiApEnabledPermissionDenied() {
+        // we should not be able to get the state
+        doThrow(new SecurityException()).when(mContext)
+                .enforceCallingOrSelfPermission(eq(android.Manifest.permission.ACCESS_WIFI_STATE),
+                                                eq("WifiService"));
+
+        try {
+            mWifiServiceImpl.getWifiApEnabledState();
+            fail("expected SecurityException");
+        } catch (SecurityException expected) { }
+    }
+
+    /**
      * Make sure we do not start wifi if System services have to be restarted to decrypt the device.
      */
     @Test
@@ -591,7 +661,6 @@
         when(mSettingsStore.handleWifiToggled(true)).thenReturn(true);
         when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true);
         when(mWifiStateMachine.syncGetWifiState()).thenReturn(WIFI_STATE_DISABLED);
-        when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED);
         when(mContext.getPackageName()).thenReturn(ANDROID_SYSTEM_PACKAGE);
         mWifiServiceImpl.checkAndStartWifi();
         verify(mWifiController).start();
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiStateMachinePrimeTest.java b/tests/wifitests/src/com/android/server/wifi/WifiStateMachinePrimeTest.java
index f2d6cc6..0c5db44 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiStateMachinePrimeTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiStateMachinePrimeTest.java
@@ -19,14 +19,12 @@
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Mockito.*;
 
-import android.net.wifi.IApInterface;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
 import android.os.INetworkManagementService;
 import android.os.test.TestLooper;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
-import android.util.Pair;
 
 import org.junit.After;
 import org.junit.Before;
@@ -56,7 +54,6 @@
     @Mock WifiNative mWifiNative;
     @Mock WifiApConfigStore mWifiApConfigStore;
     TestLooper mLooper;
-    @Mock IApInterface mApInterface;
     @Mock INetworkManagementService mNMService;
     @Mock SoftApManager mSoftApManager;
     SoftApManager.Listener mSoftApListener;
@@ -106,24 +103,17 @@
      */
     private void enterSoftApActiveMode(SoftApModeConfiguration softApConfig) throws Exception {
         String fromState = mWifiStateMachinePrime.getCurrentMode();
-        when(mWifiNative.setupForSoftApMode(WIFI_IFACE_NAME))
-                .thenReturn(new Pair(WifiNative.SETUP_SUCCESS, mApInterface));
-        when(mApInterface.getInterfaceName()).thenReturn(WIFI_IFACE_NAME);
         doAnswer(
                 new Answer<Object>() {
                     public SoftApManager answer(InvocationOnMock invocation) {
                         Object[] args = invocation.getArguments();
                         assertEquals(mNMService, (INetworkManagementService) args[0]);
                         mSoftApListener = (SoftApManager.Listener) args[1];
-                        assertEquals(mApInterface, (IApInterface) args[2]);
-                        assertEquals(WIFI_IFACE_NAME, (String) args[3]);
-                        assertEquals(softApConfig, (SoftApModeConfiguration) args[4]);
+                        assertEquals(softApConfig, (SoftApModeConfiguration) args[2]);
                         return mSoftApManager;
                     }
                 }).when(mWifiInjector).makeSoftApManager(any(INetworkManagementService.class),
                                                          any(SoftApManager.Listener.class),
-                                                         any(IApInterface.class),
-                                                         anyString(),
                                                          any());
         mWifiStateMachinePrime.enterSoftAPMode(softApConfig);
         mLooper.dispatchAll();
@@ -138,7 +128,7 @@
     private void verifyCleanupCalled() {
         // for now, this is a single call, but make a helper to avoid adding any additional cleanup
         // checks
-        verify(mWifiNative).tearDown();
+        verify(mWifiNative, atLeastOnce()).tearDown();
     }
 
     /**
@@ -195,12 +185,9 @@
      */
     @Test
     public void testDisableWifiFromSoftApModeState() throws Exception {
-        // Use a failure getting the interface to stay in SoftApMode
-        when(mWifiNative.setupForSoftApMode(WIFI_IFACE_NAME))
-                            .thenReturn(new Pair(WifiNative.SETUP_FAILURE_HAL, null));
-
-        mWifiStateMachinePrime.enterSoftAPMode(
-                new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null));
+        enterSoftApActiveMode();
+        // now inject failure through the SoftApManager.Listener
+        mSoftApListener.onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, 0);
         mLooper.dispatchAll();
         assertEquals(SOFT_AP_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
 
@@ -227,34 +214,19 @@
     }
 
     /**
-     * Test that we do not attempt to enter SoftApModeActiveState when we cannot get an ApInterface
-     * from wificond.
-     * Expectations: After a failed attempt to get an ApInterface from WifiInjector, we should
-     * remain in the SoftApModeState.
-     */
-    @Test
-    public void testAPInterfaceFailedWhenSwitchingToApMode() throws Exception {
-        when(mWifiNative.setupForSoftApMode(WIFI_IFACE_NAME))
-                .thenReturn(new Pair(WifiNative.SETUP_FAILURE_HAL, null));
-        mWifiStateMachinePrime.enterSoftAPMode(
-                new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null));
-        mLooper.dispatchAll();
-        assertEquals(SOFT_AP_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
-    }
-
-    /**
      * Test that we do enter the SoftApModeActiveState if we are already in the SoftApModeState.
      * Expectations: We should exit the current SoftApModeState and re-enter before successfully
      * entering the SoftApModeActiveState.
      */
     @Test
     public void testEnterSoftApModeActiveWhenAlreadyInSoftApMode() throws Exception {
-        when(mWifiNative.setupForSoftApMode(WIFI_IFACE_NAME))
-                .thenReturn(new Pair(WifiNative.SETUP_SUCCESS, null));
-        mWifiStateMachinePrime.enterSoftAPMode(
-                new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null));
+        enterSoftApActiveMode();
+        // now inject failure through the SoftApManager.Listener
+        mSoftApListener.onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, 0);
         mLooper.dispatchAll();
         assertEquals(SOFT_AP_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
+        // clear the first call to start SoftApManager
+        reset(mSoftApManager);
 
         enterSoftApActiveMode();
     }
@@ -318,57 +290,12 @@
     }
 
     /**
-     * Test that the proper config is used if a prior attempt fails without using the config.
-     * Expectations: A call to start softap with a null config fails, but a second call has a set
-     * config - this second call should use the correct config.
-     */
-    @Test
-    public void testNullApModeConfigFails() throws Exception {
-        when(mWifiNative.setupForSoftApMode(WIFI_IFACE_NAME))
-                .thenReturn(new Pair(WifiNative.SETUP_SUCCESS, null));
-        mWifiStateMachinePrime.enterSoftAPMode(
-                new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null));
-        mLooper.dispatchAll();
-        assertEquals(SOFT_AP_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
-        WifiConfiguration config = new WifiConfiguration();
-        config.SSID = "ThisIsAConfig";
-        SoftApModeConfiguration softApConfig =
-                new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, config);
-        enterSoftApActiveMode(softApConfig);
-    }
-
-    /**
-     * Test that a failed call to start softap with a valid config does not persist the ap
-     * configuration to the WifiApConfigStore.
-     *
-     * Expectations: A call to start SoftAPMode with a config should not write out the config if we
-     * did not create a SoftApManager.
-     */
-    @Test
-    public void testValidConfigIsSavedOnFailureToStart() throws Exception {
-        when(mWifiNative.setupForSoftApMode(WIFI_IFACE_NAME))
-                .thenReturn(new Pair(WifiNative.SETUP_SUCCESS, null));
-        when(mWifiInjector.getWifiApConfigStore()).thenReturn(mWifiApConfigStore);
-        WifiConfiguration config = new WifiConfiguration();
-        config.SSID = "ThisIsAConfig";
-        SoftApModeConfiguration softApConfig =
-                new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, config);
-        mWifiStateMachinePrime.enterSoftAPMode(softApConfig);
-        mLooper.dispatchAll();
-        assertEquals(SOFT_AP_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode());
-        verify(mWifiApConfigStore, never()).setApConfiguration(eq(config));
-    }
-
-    /**
      * Test that two calls to switch to SoftAPMode in succession ends up with the correct config.
      *
      * Expectation: we should end up in SoftAPMode state configured with the second config.
      */
     @Test
     public void testStartSoftApModeTwiceWithTwoConfigs() throws Exception {
-        when(mWifiNative.setupForSoftApMode(WIFI_IFACE_NAME))
-                .thenReturn(new Pair(WifiNative.SETUP_SUCCESS, mApInterface));
-        when(mApInterface.getInterfaceName()).thenReturn(WIFI_IFACE_NAME);
         when(mWifiInjector.getWifiApConfigStore()).thenReturn(mWifiApConfigStore);
         WifiConfiguration config1 = new WifiConfiguration();
         config1.SSID = "ThisIsAConfig";
@@ -381,14 +308,10 @@
 
         when(mWifiInjector.makeSoftApManager(any(INetworkManagementService.class),
                                              any(SoftApManager.Listener.class),
-                                             any(IApInterface.class),
-                                             anyString(),
                                              eq(softApConfig1)))
                 .thenReturn(mSoftApManager);
         when(mWifiInjector.makeSoftApManager(any(INetworkManagementService.class),
                                              any(SoftApManager.Listener.class),
-                                             any(IApInterface.class),
-                                             anyString(),
                                              eq(softApConfig2)))
                 .thenReturn(mSoftApManager);
 
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
index e6972ea..5208c74 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
@@ -16,18 +16,6 @@
 
 package com.android.server.wifi;
 
-import static android.net.wifi.WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE;
-import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_FAILURE_REASON;
-import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
-import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
-import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
-import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
-import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
-import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
-import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING;
-
-import static com.android.server.wifi.LocalOnlyHotspotRequestInfo.HOTSPOT_NO_ERROR;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
@@ -52,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;
@@ -355,7 +342,6 @@
     @Mock PropertyService mPropertyService;
     @Mock BuildProperties mBuildProperties;
     @Mock IWificond mWificond;
-    @Mock IApInterface mApInterface;
     @Mock IClientInterface mClientInterface;
     @Mock IBinder mPackageManagerBinder;
     @Mock WifiConfigManager mWifiConfigManager;
@@ -407,11 +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(IApInterface.class), anyString(),
-                                             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);
@@ -427,9 +412,9 @@
 
         when(mWifiNative.setupForClientMode(WIFI_IFACE_NAME))
                 .thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, mClientInterface));
-        when(mWifiNative.setupForSoftApMode(WIFI_IFACE_NAME))
-                .thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, mApInterface));
-        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);
@@ -578,21 +563,6 @@
         assertEquals("DisconnectedState", getCurrentState().getName());
     }
 
-    private void checkApStateChangedBroadcast(Intent intent, int expectedCurrentState,
-            int expectedPrevState, int expectedErrorCode, String expectedIfaceName,
-            int expectedMode) {
-        int currentState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
-        int prevState = intent.getIntExtra(EXTRA_PREVIOUS_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
-        int errorCode = intent.getIntExtra(EXTRA_WIFI_AP_FAILURE_REASON, HOTSPOT_NO_ERROR);
-        String ifaceName = intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME);
-        int mode = intent.getIntExtra(EXTRA_WIFI_AP_MODE, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
-        assertEquals(expectedCurrentState, currentState);
-        assertEquals(expectedPrevState, prevState);
-        assertEquals(expectedErrorCode, errorCode);
-        assertEquals(expectedIfaceName, ifaceName);
-        assertEquals(expectedMode, mode);
-    }
-
     private void loadComponentsInApMode(int mode) throws Exception {
         SoftApModeConfiguration config = new SoftApModeConfiguration(mode, new WifiConfiguration());
         mWsm.setHostApRunning(config, true);
@@ -600,20 +570,8 @@
 
         assertEquals("SoftApState", getCurrentState().getName());
 
-        verify(mWifiNative).setupForSoftApMode(WIFI_IFACE_NAME);
-        verify(mSoftApManager).start();
-
-        // get the SoftApManager.Listener and trigger some updates
-        SoftApManager.Listener listener = mSoftApManagerListenerCaptor.getValue();
-        listener.onStateChanged(WIFI_AP_STATE_ENABLING, 0);
-        assertEquals(WIFI_AP_STATE_ENABLING, mWsm.syncGetWifiApState());
-        listener.onStateChanged(WIFI_AP_STATE_ENABLED, 0);
-        assertEquals(WIFI_AP_STATE_ENABLED, mWsm.syncGetWifiApState());
-        listener.onStateChanged(WIFI_AP_STATE_DISABLING, 0);
-        assertEquals(WIFI_AP_STATE_DISABLING, mWsm.syncGetWifiApState());
-        // note, this will trigger a mode change when TestLooper is dispatched
-        listener.onStateChanged(WIFI_AP_STATE_DISABLED, 0);
-        assertEquals(WIFI_AP_STATE_DISABLED, mWsm.syncGetWifiApState());
+        verify(mWifiNative, never()).setupForSoftApMode(WIFI_IFACE_NAME);
+        verify(mSoftApManager, never()).start();
     }
 
     private void setupMockWpsPbc() throws Exception {
@@ -2481,40 +2439,6 @@
     }
 
     /**
-     * Test that failure to start HAL in AP mode increments the corresponding metrics.
-     */
-    @Test
-    public void testSetupForSoftApModeHalFailureIncrementsMetrics() throws Exception {
-        when(mWifiNative.setupForSoftApMode(WIFI_IFACE_NAME))
-                .thenReturn(Pair.create(WifiNative.SETUP_FAILURE_HAL, null));
-
-        SoftApModeConfiguration config = new SoftApModeConfiguration(
-                WifiManager.IFACE_IP_MODE_TETHERED, new WifiConfiguration());
-        mWsm.setHostApRunning(config, true);
-        mLooper.dispatchAll();
-
-        verify(mWifiNative).setupForSoftApMode(WIFI_IFACE_NAME);
-        verify(mWifiMetrics).incrementNumWifiOnFailureDueToHal();
-    }
-
-    /**
-     * Test that failure to start HAL in AP mode increments the corresponding metrics.
-     */
-    @Test
-    public void testSetupForSoftApModeWificondFailureIncrementsMetrics() throws Exception {
-        when(mWifiNative.setupForSoftApMode(WIFI_IFACE_NAME))
-                .thenReturn(Pair.create(WifiNative.SETUP_FAILURE_WIFICOND, null));
-
-        SoftApModeConfiguration config = new SoftApModeConfiguration(
-                WifiManager.IFACE_IP_MODE_TETHERED, new WifiConfiguration());
-        mWsm.setHostApRunning(config, true);
-        mLooper.dispatchAll();
-
-        verify(mWifiNative).setupForSoftApMode(WIFI_IFACE_NAME);
-        verify(mWifiMetrics).incrementNumWifiOnFailureDueToWificond();
-    }
-
-    /**
      * Test that failure to start HAL in client mode increments the corresponding metrics.
      */
     @Test
diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareServiceImplTest.java
index f323110..a0abf16 100644
--- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareServiceImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareServiceImplTest.java
@@ -120,6 +120,8 @@
         when(mContextMock.getPackageManager()).thenReturn(mPackageManagerMock);
         when(mPackageManagerMock.hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE))
                 .thenReturn(true);
+        when(mPackageManagerMock.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT))
+                .thenReturn(true);
         when(mAwareStateManagerMock.getCharacteristics()).thenReturn(getCharacteristics());
 
         mDut = new WifiAwareServiceImplSpy(mContextMock);
@@ -238,6 +240,41 @@
     }
 
     /**
+     * Validate that the RTT feature support is checked when attempting a Publish with ranging.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testFailOnPublishRangingWithoutRttFeature() throws Exception {
+        when(mPackageManagerMock.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)).thenReturn(
+                false);
+
+        PublishConfig publishConfig = new PublishConfig.Builder().setServiceName("something.valid")
+                .setRangingEnabled(true).build();
+        int clientId = doConnect();
+        IWifiAwareDiscoverySessionCallback mockCallback = mock(
+                IWifiAwareDiscoverySessionCallback.class);
+
+        mDut.publish(clientId, publishConfig, mockCallback);
+    }
+
+    /**
+     * Validate that the RTT feature support is checked when attempting a Subscribe with ranging.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testFailOnSubscribeRangingWithoutRttFeature() throws Exception {
+        when(mPackageManagerMock.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)).thenReturn(
+                false);
+
+        SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(
+                "something.valid").setMaxDistanceMm(100).build();
+        int clientId = doConnect();
+        IWifiAwareDiscoverySessionCallback mockCallback = mock(
+                IWifiAwareDiscoverySessionCallback.class);
+
+        mDut.subscribe(clientId, subscribeConfig, mockCallback);
+    }
+
+
+    /**
      * Validates that on binder death we get a disconnect().
      */
     @Test
@@ -295,7 +332,7 @@
     @Test
     public void testPublish() {
         PublishConfig publishConfig = new PublishConfig.Builder().setServiceName("something.valid")
-                .build();
+                .setRangingEnabled(true).build();
         int clientId = doConnect();
         IWifiAwareDiscoverySessionCallback mockCallback = mock(
                 IWifiAwareDiscoverySessionCallback.class);
@@ -390,7 +427,7 @@
     @Test
     public void testSubscribe() {
         SubscribeConfig subscribeConfig = new SubscribeConfig.Builder()
-                .setServiceName("something.valid").build();
+                .setServiceName("something.valid").setMaxDistanceMm(100).build();
         int clientId = doConnect();
         IWifiAwareDiscoverySessionCallback mockCallback = mock(
                 IWifiAwareDiscoverySessionCallback.class);
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigStoreDataTest.java
index 7e05c3d..8441eb0 100644
--- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigStoreDataTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigStoreDataTest.java
@@ -61,6 +61,7 @@
     private static final long TEST_PROVIDER_ID = 1;
     private static final int TEST_CREATOR_UID = 1234;
     private static final boolean TEST_HAS_EVER_CONNECTED = true;
+    private static final boolean TEST_SHARED = false;
 
     @Mock WifiKeyStore mKeyStore;
     @Mock SIMAccessor mSimAccessor;
@@ -239,7 +240,7 @@
         providerList.add(new PasspointProvider(createFullPasspointConfiguration(),
                 mKeyStore, mSimAccessor, TEST_PROVIDER_ID, TEST_CREATOR_UID,
                 TEST_CA_CERTIFICATE_ALIAS, TEST_CLIENT_CERTIFICATE_ALIAS,
-                TEST_CLIENT_PRIVATE_KEY_ALIAS, TEST_HAS_EVER_CONNECTED));
+                TEST_CLIENT_PRIVATE_KEY_ALIAS, TEST_HAS_EVER_CONNECTED, TEST_SHARED));
 
         // Serialize data for user store.
         when(mDataSource.getProviders()).thenReturn(providerList);
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java
index 9ee9fc6..355c252 100644
--- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java
@@ -650,6 +650,7 @@
         assertTrue(Arrays.equals(rcOIs, wifiConfig.roamingConsortiumIds));
         assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP));
         assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X));
+        assertFalse(wifiConfig.shared);
         assertEquals(realm, wifiEnterpriseConfig.getRealm());
         assertEquals(fqdn, wifiEnterpriseConfig.getDomainSuffixMatch());
         assertEquals("anonymous@" + realm, wifiEnterpriseConfig.getAnonymousIdentity());
@@ -712,6 +713,7 @@
         assertTrue(Arrays.equals(rcOIs, wifiConfig.roamingConsortiumIds));
         assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP));
         assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X));
+        assertFalse(wifiConfig.shared);
         assertEquals(realm, wifiEnterpriseConfig.getRealm());
         assertEquals(fqdn, wifiEnterpriseConfig.getDomainSuffixMatch());
         assertEquals("anonymous@" + realm, wifiEnterpriseConfig.getAnonymousIdentity());
@@ -761,6 +763,7 @@
         assertTrue(Arrays.equals(rcOIs, wifiConfig.roamingConsortiumIds));
         assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP));
         assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X));
+        assertFalse(wifiConfig.shared);
         assertEquals(realm, wifiEnterpriseConfig.getRealm());
         assertEquals(fqdn, wifiEnterpriseConfig.getDomainSuffixMatch());
         assertEquals(WifiEnterpriseConfig.Eap.SIM, wifiEnterpriseConfig.getEapMethod());
diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java
index 4ffc66d..5b797e8 100644
--- a/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java
@@ -16,12 +16,35 @@
 
 package com.android.server.wifi.scanner;
 
-import static com.android.server.wifi.ScanTestUtil.*;
+import static com.android.server.wifi.ScanTestUtil.NativeScanSettingsBuilder;
+import static com.android.server.wifi.ScanTestUtil.assertNativePnoSettingsEquals;
+import static com.android.server.wifi.ScanTestUtil.assertNativeScanSettingsEquals;
+import static com.android.server.wifi.ScanTestUtil.assertScanDatasEquals;
+import static com.android.server.wifi.ScanTestUtil.assertScanResultsEquals;
+import static com.android.server.wifi.ScanTestUtil.channelsToSpec;
+import static com.android.server.wifi.ScanTestUtil.computeSingleScanNativeSettings;
+import static com.android.server.wifi.ScanTestUtil.createRequest;
+import static com.android.server.wifi.ScanTestUtil.createSingleScanNativeSettingsForChannels;
 import static com.android.server.wifi.scanner.WifiScanningServiceImpl.WifiSingleScanStateMachine
         .CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS;
 
-import static org.junit.Assert.*;
-import static org.mockito.Mockito.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.argThat;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.validateMockitoUsage;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
 
 import android.app.test.MockAnswerUtil.AnswerWithArguments;
 import android.app.test.TestAlarmManager;
@@ -63,11 +86,11 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatcher;
 import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.mockito.Spy;
-import org.mockito.compat.CapturingMatcher;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -161,14 +184,35 @@
         return messageCaptor.getValue();
     }
 
+    private static class ConditionalMessageCaptor implements ArgumentMatcher<Message> {
+        private Message mLastValue;
+        private final int mWhat;
+
+        private ConditionalMessageCaptor(int what) {
+            mWhat = what;
+        }
+
+        public Message getLastValue() {
+            assertNotNull("Nothing captured yet", mLastValue);
+
+            return mLastValue;
+        }
+
+        public boolean matches(Message message) {
+            boolean isMatch = message.what == mWhat;
+
+            if (isMatch) {
+                mLastValue = message;
+            }
+
+            return isMatch;
+        }
+    }
+
     private static Message verifyHandleMessageAndGetMessage(InOrder order, Handler handler,
             final int what) {
-        CapturingMatcher<Message> messageMatcher = new CapturingMatcher<Message>() {
-            public boolean matchesObject(Object argument) {
-                Message message = (Message) argument;
-                return message.what == what;
-            }
-        };
+        ConditionalMessageCaptor messageMatcher = new ConditionalMessageCaptor(what);
+
         order.verify(handler).handleMessage(argThat(messageMatcher));
         return messageMatcher.getLastValue();
     }