diff options
14 files changed, 819 insertions, 1406 deletions
diff --git a/service/java/com/android/server/wifi/ActiveModeManager.java b/service/java/com/android/server/wifi/ActiveModeManager.java index 00ae7b3c2..6669e32f7 100644 --- a/service/java/com/android/server/wifi/ActiveModeManager.java +++ b/service/java/com/android/server/wifi/ActiveModeManager.java @@ -16,6 +16,12 @@ package com.android.server.wifi; +import android.content.Context; +import android.content.Intent; +import android.net.wifi.WifiManager; +import android.os.UserHandle; +import android.util.Log; + /** * Base class for available WiFi operating modes. * @@ -33,4 +39,22 @@ public interface ActiveModeManager { * Method used to stop the Manager for a give Wifi operational mode. */ void stop(); + + /** + * Method that allows Mode Managers to update WifiScanner about the current state. + * + * @param context Context to use for the notification + * @param available boolean indicating if scanning is available + */ + default void sendScanAvailableBroadcast(Context context, boolean available) { + Log.d(TAG, "sending scan available broadcast: " + available); + final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + if (available) { + intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WifiManager.WIFI_STATE_ENABLED); + } else { + intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WifiManager.WIFI_STATE_DISABLED); + } + context.sendStickyBroadcastAsUser(intent, UserHandle.ALL); + } } diff --git a/service/java/com/android/server/wifi/ClientModeManager.java b/service/java/com/android/server/wifi/ClientModeManager.java index 14d55de1e..bd82876df 100644 --- a/service/java/com/android/server/wifi/ClientModeManager.java +++ b/service/java/com/android/server/wifi/ClientModeManager.java @@ -26,6 +26,7 @@ import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; +import com.android.internal.util.IState; import com.android.internal.util.State; import com.android.internal.util.StateMachine; import com.android.server.wifi.WifiNative.InterfaceCallback; @@ -44,17 +45,20 @@ public class ClientModeManager implements ActiveModeManager { private final WifiMetrics mWifiMetrics; private final Listener mListener; private final ScanRequestProxy mScanRequestProxy; + private final WifiStateMachine mWifiStateMachine; private String mClientInterfaceName; - + private boolean mIfaceIsUp; ClientModeManager(Context context, @NonNull Looper looper, WifiNative wifiNative, - Listener listener, WifiMetrics wifiMetrics, ScanRequestProxy scanRequestProxy) { + Listener listener, WifiMetrics wifiMetrics, ScanRequestProxy scanRequestProxy, + WifiStateMachine wifiStateMachine) { mContext = context; mWifiNative = wifiNative; mListener = listener; mWifiMetrics = wifiMetrics; mScanRequestProxy = scanRequestProxy; + mWifiStateMachine = wifiStateMachine; mStateMachine = new ClientModeStateMachine(looper); } @@ -69,7 +73,20 @@ public class ClientModeManager implements ActiveModeManager { * Disconnect from any currently connected networks and stop client mode. */ public void stop() { - mStateMachine.sendMessage(ClientModeStateMachine.CMD_STOP); + IState currentState = mStateMachine.getCurrentState(); + Log.d(TAG, " currentstate: " + currentState); + if (mClientInterfaceName != null) { + if (mIfaceIsUp) { + updateWifiState(WifiManager.WIFI_STATE_DISABLING, + WifiManager.WIFI_STATE_ENABLED); + } else { + updateWifiState(WifiManager.WIFI_STATE_DISABLING, + WifiManager.WIFI_STATE_ENABLING); + } + } + if (currentState != null) { + currentState.exit(); + } } /** @@ -106,37 +123,35 @@ public class ClientModeManager implements ActiveModeManager { private class ClientModeStateMachine extends StateMachine { // Commands for the state machine. public static final int CMD_START = 0; - public static final int CMD_STOP = 1; - public static final int CMD_WIFINATIVE_FAILURE = 2; public static final int CMD_INTERFACE_STATUS_CHANGED = 3; public static final int CMD_INTERFACE_DESTROYED = 4; + public static final int CMD_INTERFACE_DOWN = 5; private final State mIdleState = new IdleState(); private final State mStartedState = new StartedState(); - private WifiNative.StatusListener mWifiNativeStatusListener = (boolean isReady) -> { - if (!isReady) { - sendMessage(CMD_WIFINATIVE_FAILURE); - } - }; private final InterfaceCallback mWifiNativeInterfaceCallback = new InterfaceCallback() { @Override public void onDestroyed(String ifaceName) { - sendMessage(CMD_INTERFACE_DESTROYED); + if (mClientInterfaceName != null && mClientInterfaceName.equals(ifaceName)) { + sendMessage(CMD_INTERFACE_DESTROYED); + } } @Override public void onUp(String ifaceName) { - sendMessage(CMD_INTERFACE_STATUS_CHANGED, 1); + if (mClientInterfaceName != null && mClientInterfaceName.equals(ifaceName)) { + sendMessage(CMD_INTERFACE_STATUS_CHANGED, 1); + } } @Override public void onDown(String ifaceName) { - sendMessage(CMD_INTERFACE_STATUS_CHANGED, 0); + if (mClientInterfaceName != null && mClientInterfaceName.equals(ifaceName)) { + sendMessage(CMD_INTERFACE_STATUS_CHANGED, 0); + } } }; - private boolean mIfaceIsUp = false; - ClientModeStateMachine(Looper looper) { super(TAG, looper); @@ -152,8 +167,8 @@ public class ClientModeManager implements ActiveModeManager { @Override public void enter() { Log.d(TAG, "entering IdleState"); - mWifiNative.registerStatusListener(mWifiNativeStatusListener); mClientInterfaceName = null; + mIfaceIsUp = false; } @Override @@ -167,17 +182,15 @@ public class ClientModeManager implements ActiveModeManager { false /* not low priority */, mWifiNativeInterfaceCallback); if (TextUtils.isEmpty(mClientInterfaceName)) { Log.e(TAG, "Failed to create ClientInterface. Sit in Idle"); - sendScanAvailableBroadcast(false); updateWifiState(WifiManager.WIFI_STATE_UNKNOWN, WifiManager.WIFI_STATE_ENABLING); + updateWifiState(WifiManager.WIFI_STATE_DISABLED, + WifiManager.WIFI_STATE_UNKNOWN); break; } + sendScanAvailableBroadcast(false); transitionTo(mStartedState); break; - case CMD_STOP: - // This should be safe to ignore. - Log.d(TAG, "received CMD_STOP when idle, ignoring"); - break; default: Log.d(TAG, "received an invalid message: " + message); return NOT_HANDLED; @@ -196,14 +209,21 @@ public class ClientModeManager implements ActiveModeManager { if (isUp) { Log.d(TAG, "Wifi is ready to use for client mode"); sendScanAvailableBroadcast(true); + mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE, + mClientInterfaceName); updateWifiState(WifiManager.WIFI_STATE_ENABLED, WifiManager.WIFI_STATE_ENABLING); } else { + if (mWifiStateMachine.isConnectedMacRandomizationEnabled()) { + // Handle the error case where our underlying interface went down if we + // do not have mac randomization enabled (b/72459123). + return; + } // if the interface goes down we should exit and go back to idle state. - Log.d(TAG, "interface down! may need to restart ClientMode"); + Log.d(TAG, "interface down!"); updateWifiState(WifiManager.WIFI_STATE_UNKNOWN, - WifiManager.WIFI_STATE_UNKNOWN); - mStateMachine.sendMessage(CMD_STOP); + WifiManager.WIFI_STATE_ENABLED); + mStateMachine.sendMessage(CMD_INTERFACE_DOWN); } } @@ -221,25 +241,18 @@ public class ClientModeManager implements ActiveModeManager { case CMD_START: // Already started, ignore this command. break; - case CMD_STOP: - Log.d(TAG, "Stopping client mode."); + case CMD_INTERFACE_DOWN: + Log.e(TAG, "Detected an interface down, reporting failure to SelfRecovery"); + mWifiStateMachine.failureDetected(SelfRecovery.REASON_STA_IFACE_DOWN); + updateWifiState(WifiManager.WIFI_STATE_DISABLING, - WifiManager.WIFI_STATE_ENABLED); - mWifiNative.teardownInterface(mClientInterfaceName); + WifiManager.WIFI_STATE_UNKNOWN); transitionTo(mIdleState); break; case CMD_INTERFACE_STATUS_CHANGED: boolean isUp = message.arg1 == 1; onUpChanged(isUp); break; - case CMD_WIFINATIVE_FAILURE: - Log.d(TAG, "WifiNative failure - may need to restart ClientMode!"); - updateWifiState(WifiManager.WIFI_STATE_UNKNOWN, - WifiManager.WIFI_STATE_UNKNOWN); - updateWifiState(WifiManager.WIFI_STATE_DISABLING, - WifiManager.WIFI_STATE_ENABLED); - transitionTo(mIdleState); - break; case CMD_INTERFACE_DESTROYED: Log.d(TAG, "interface destroyed - client mode stopping"); @@ -259,12 +272,19 @@ public class ClientModeManager implements ActiveModeManager { */ @Override public void exit() { + if (mClientInterfaceName == null) { + return; + } + mWifiStateMachine.setOperationalMode(WifiStateMachine.DISABLED_MODE, null); + mWifiNative.teardownInterface(mClientInterfaceName); // let WifiScanner know that wifi is down. sendScanAvailableBroadcast(false); updateWifiState(WifiManager.WIFI_STATE_DISABLED, WifiManager.WIFI_STATE_DISABLING); mScanRequestProxy.enableScanningForHiddenNetworks(false); mScanRequestProxy.clearScanResults(); + mClientInterfaceName = null; + mIfaceIsUp = false; } } diff --git a/service/java/com/android/server/wifi/ScanOnlyModeManager.java b/service/java/com/android/server/wifi/ScanOnlyModeManager.java index f1351b24f..4973de53d 100644 --- a/service/java/com/android/server/wifi/ScanOnlyModeManager.java +++ b/service/java/com/android/server/wifi/ScanOnlyModeManager.java @@ -18,14 +18,13 @@ package com.android.server.wifi; import android.annotation.NonNull; import android.content.Context; -import android.content.Intent; import android.net.wifi.WifiManager; import android.os.Looper; import android.os.Message; -import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; +import com.android.internal.util.IState; import com.android.internal.util.State; import com.android.internal.util.StateMachine; import com.android.server.wifi.WifiNative.InterfaceCallback; @@ -49,7 +48,6 @@ public class ScanOnlyModeManager implements ActiveModeManager { private String mClientInterfaceName; - ScanOnlyModeManager(@NonNull Context context, @NonNull Looper looper, @NonNull WifiNative wifiNative, @NonNull Listener listener, @NonNull WifiMetrics wifiMetrics, @@ -75,7 +73,11 @@ public class ScanOnlyModeManager implements ActiveModeManager { * Cancel any pending scans and stop scan mode. */ public void stop() { - mStateMachine.sendMessage(ScanOnlyModeStateMachine.CMD_STOP); + IState currentState = mStateMachine.getCurrentState(); + Log.d(TAG, " currentstate: " + currentState); + if (currentState != null) { + currentState.exit(); + } } /** @@ -100,8 +102,6 @@ public class ScanOnlyModeManager implements ActiveModeManager { private class ScanOnlyModeStateMachine extends StateMachine { // Commands for the state machine. public static final int CMD_START = 0; - public static final int CMD_STOP = 1; - public static final int CMD_WIFINATIVE_FAILURE = 2; public static final int CMD_INTERFACE_STATUS_CHANGED = 3; public static final int CMD_INTERFACE_DESTROYED = 4; public static final int CMD_INTERFACE_DOWN = 5; @@ -109,12 +109,6 @@ public class ScanOnlyModeManager implements ActiveModeManager { private final State mIdleState = new IdleState(); private final State mStartedState = new StartedState(); - private final WifiNative.StatusListener mWifiNativeStatusListener = (boolean isReady) -> { - if (!isReady) { - sendMessage(CMD_WIFINATIVE_FAILURE); - } - }; - private final InterfaceCallback mWifiNativeInterfaceCallback = new InterfaceCallback() { @Override public void onDestroyed(String ifaceName) { @@ -154,7 +148,6 @@ public class ScanOnlyModeManager implements ActiveModeManager { @Override public void enter() { Log.d(TAG, "entering IdleState"); - mWifiNative.registerStatusListener(mWifiNativeStatusListener); mClientInterfaceName = null; } @@ -166,16 +159,14 @@ public class ScanOnlyModeManager implements ActiveModeManager { mWifiNativeInterfaceCallback); if (TextUtils.isEmpty(mClientInterfaceName)) { Log.e(TAG, "Failed to create ClientInterface. Sit in Idle"); - sendScanAvailableBroadcast(false); updateWifiState(WifiManager.WIFI_STATE_UNKNOWN); break; } + // we have a new scanning interface, make sure scanner knows we aren't + // ready yet + sendScanAvailableBroadcast(false); transitionTo(mStartedState); break; - case CMD_STOP: - // This should be safe to ignore. - Log.d(TAG, "received CMD_STOP when idle, ignoring"); - break; default: Log.d(TAG, "received an invalid message: " + message); return NOT_HANDLED; @@ -218,12 +209,9 @@ public class ScanOnlyModeManager implements ActiveModeManager { case CMD_START: // Already started, ignore this command. break; - case CMD_STOP: - Log.d(TAG, "Stopping scan mode."); - transitionTo(mIdleState); - break; case CMD_INTERFACE_DESTROYED: Log.d(TAG, "Interface cleanly destroyed, report scan mode stop."); + mClientInterfaceName = null; transitionTo(mIdleState); break; case CMD_INTERFACE_STATUS_CHANGED: @@ -231,8 +219,7 @@ public class ScanOnlyModeManager implements ActiveModeManager { onUpChanged(isUp); break; case CMD_INTERFACE_DOWN: - case CMD_WIFINATIVE_FAILURE: - Log.d(TAG, "native/interface failure! restart services?"); + Log.d(TAG, "interface down! stop mode"); updateWifiState(WifiManager.WIFI_STATE_UNKNOWN); transitionTo(mIdleState); break; @@ -249,24 +236,18 @@ public class ScanOnlyModeManager implements ActiveModeManager { @Override public void exit() { mWakeupController.stop(); - //mWifiNative.teardownInterface(mClientInterfaceName); - // let WifiScanner know that wifi is down. - sendScanAvailableBroadcast(false); + if (mClientInterfaceName == null) { + return; + } + mWifiNative.teardownInterface(mClientInterfaceName); + mClientInterfaceName = null; updateWifiState(WifiManager.WIFI_STATE_DISABLED); mScanRequestProxy.clearScanResults(); } } + } - private void sendScanAvailableBroadcast(boolean available) { - Log.d(TAG, "sending scan available broadcast: " + available); - final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - if (available) { - intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WifiManager.WIFI_STATE_ENABLED); - } else { - intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WifiManager.WIFI_STATE_DISABLED); - } - mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); - } + private void sendScanAvailableBroadcast(boolean available) { + sendScanAvailableBroadcast(mContext, available); } } diff --git a/service/java/com/android/server/wifi/SoftApManager.java b/service/java/com/android/server/wifi/SoftApManager.java index d2d0c4a37..77c217ab2 100644 --- a/service/java/com/android/server/wifi/SoftApManager.java +++ b/service/java/com/android/server/wifi/SoftApManager.java @@ -37,12 +37,12 @@ import android.util.Log; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.IState; import com.android.internal.util.State; import com.android.internal.util.StateMachine; import com.android.internal.util.WakeupMessage; import com.android.server.wifi.WifiNative.InterfaceCallback; import com.android.server.wifi.WifiNative.SoftApListener; -import com.android.server.wifi.WifiNative.StatusListener; import com.android.server.wifi.util.ApConfigUtil; import java.util.Locale; @@ -72,6 +72,7 @@ public class SoftApManager implements ActiveModeManager { private final WifiManager.SoftApCallback mCallback; private String mApInterfaceName; + private boolean mIfaceIsUp; private final WifiApConfigStore mWifiApConfigStore; @@ -134,7 +135,20 @@ public class SoftApManager implements ActiveModeManager { * Stop soft AP. */ public void stop() { - mStateMachine.sendMessage(SoftApStateMachine.CMD_STOP); + IState currentState = mStateMachine.getCurrentState(); + Log.d(TAG, " currentstate: " + currentState); + if (mApInterfaceName != null) { + if (mIfaceIsUp) { + updateApState(WifiManager.WIFI_AP_STATE_DISABLING, + WifiManager.WIFI_AP_STATE_ENABLED, 0); + } else { + updateApState(WifiManager.WIFI_AP_STATE_DISABLING, + WifiManager.WIFI_AP_STATE_ENABLING, 0); + } + } + if (currentState != null) { + currentState.exit(); + } } /** @@ -219,8 +233,6 @@ public class SoftApManager implements ActiveModeManager { private class SoftApStateMachine extends StateMachine { // Commands for the state machine. public static final int CMD_START = 0; - public static final int CMD_STOP = 1; - public static final int CMD_WIFINATIVE_FAILURE = 2; public static final int CMD_INTERFACE_STATUS_CHANGED = 3; public static final int CMD_NUM_ASSOCIATED_STATIONS_CHANGED = 4; public static final int CMD_NO_ASSOCIATED_STATIONS_TIMEOUT = 5; @@ -232,12 +244,6 @@ public class SoftApManager implements ActiveModeManager { private final State mIdleState = new IdleState(); private final State mStartedState = new StartedState(); - private final StatusListener mWifiNativeStatusListener = (boolean isReady) -> { - if (!isReady) { - sendMessage(CMD_WIFINATIVE_FAILURE); - } - }; - private final InterfaceCallback mWifiNativeInterfaceCallback = new InterfaceCallback() { @Override public void onDestroyed(String ifaceName) { @@ -274,8 +280,8 @@ public class SoftApManager implements ActiveModeManager { private class IdleState extends State { @Override public void enter() { - mWifiNative.registerStatusListener(mWifiNativeStatusListener); mApInterfaceName = null; + mIfaceIsUp = false; } @Override @@ -320,8 +326,6 @@ public class SoftApManager implements ActiveModeManager { } private class StartedState extends State { - private boolean mIfaceIsUp; - private int mNumAssociatedStations; private boolean mTimeoutEnabled; @@ -454,8 +458,10 @@ public class SoftApManager implements ActiveModeManager { @Override public void exit() { - // will trigger interface teardown when interface management is dynamic - // stopSoftAp(); + if (mApInterfaceName == null) { + return; + } + stopSoftAp(); if (mSettingObserver != null) { mSettingObserver.unregister(); } @@ -467,6 +473,8 @@ public class SoftApManager implements ActiveModeManager { mWifiMetrics.addSoftApUpChangedEvent(false, mMode); updateApState(WifiManager.WIFI_AP_STATE_DISABLED, WifiManager.WIFI_AP_STATE_DISABLING, 0); + mApInterfaceName = null; + mIfaceIsUp = false; } @Override @@ -517,12 +525,6 @@ public class SoftApManager implements ActiveModeManager { break; } Log.i(TAG, "Timeout message received. Stopping soft AP."); - stopSoftAp(); - updateApState(WifiManager.WIFI_AP_STATE_DISABLING, - WifiManager.WIFI_AP_STATE_ENABLED, 0); - transitionTo(mIdleState); - break; - case CMD_STOP: updateApState(WifiManager.WIFI_AP_STATE_DISABLING, WifiManager.WIFI_AP_STATE_ENABLED, 0); transitionTo(mIdleState); @@ -533,9 +535,8 @@ public class SoftApManager implements ActiveModeManager { WifiManager.WIFI_AP_STATE_ENABLED, 0); transitionTo(mIdleState); break; - case CMD_WIFINATIVE_FAILURE: case CMD_INTERFACE_DOWN: - Log.w(TAG, "native/interface error, stop and report failure"); + Log.w(TAG, "interface error, stop and report failure"); updateApState(WifiManager.WIFI_AP_STATE_FAILED, WifiManager.WIFI_AP_STATE_ENABLED, WifiManager.SAP_START_FAILURE_GENERAL); diff --git a/service/java/com/android/server/wifi/WifiController.java b/service/java/com/android/server/wifi/WifiController.java index 76b44c82f..7fb223535 100644 --- a/service/java/com/android/server/wifi/WifiController.java +++ b/service/java/com/android/server/wifi/WifiController.java @@ -30,6 +30,7 @@ import android.os.Message; import android.os.SystemClock; import android.os.WorkSource; import android.provider.Settings; +import android.util.Log; import com.android.internal.util.Protocol; import com.android.internal.util.State; @@ -93,6 +94,8 @@ public class WifiController extends StateMachine { private static final int CMD_RECOVERY_RESTART_WIFI_CONTINUE = BASE + 18; // Command to disable wifi when SelfRecovery is throttled or otherwise not doing full recovery static final int CMD_RECOVERY_DISABLE_WIFI = BASE + 19; + static final int CMD_STA_STOPPED = BASE + 20; + static final int CMD_SCANNING_STOPPED = BASE + 21; private DefaultState mDefaultState = new DefaultState(); private StaEnabledState mStaEnabledState = new StaEnabledState(); @@ -102,6 +105,9 @@ public class WifiController extends StateMachine { private DeviceActiveState mDeviceActiveState = new DeviceActiveState(); private EcmState mEcmState = new EcmState(); + private ScanOnlyModeManager.Listener mScanOnlyModeCallback = new ScanOnlyCallback(); + private ClientModeManager.Listener mClientModeCallback = new ClientModeCallback(); + WifiController(Context context, WifiStateMachine wsm, Looper wifiStateMachineLooper, WifiSettingsStore wss, Looper wifiServiceLooper, FrameworkFacade f, WifiStateMachinePrime wsmp) { @@ -113,6 +119,7 @@ public class WifiController extends StateMachine { mWifiStateMachinePrime = wsmp; mSettingsStore = wss; + // CHECKSTYLE:OFF IndentationCheck addState(mDefaultState); addState(mApStaDisabledState, mDefaultState); addState(mStaEnabledState, mDefaultState); @@ -120,6 +127,7 @@ public class WifiController extends StateMachine { addState(mStaDisabledWithScanState, mDefaultState); addState(mApEnabledState, mDefaultState); addState(mEcmState, mDefaultState); + // CHECKSTYLE:ON IndentationCheck boolean isAirplaneModeOn = mSettingsStore.isAirplaneModeOn(); boolean isWifiEnabled = mSettingsStore.isWifiToggleEnabled(); @@ -142,6 +150,10 @@ public class WifiController extends StateMachine { setLogRecSize(100); setLogOnlyTransitions(false); + // register for state updates via callbacks (vs the intents registered below) + mWifiStateMachinePrime.registerScanOnlyCallback(mScanOnlyModeCallback); + mWifiStateMachinePrime.registerClientModeCallback(mClientModeCallback); + IntentFilter filter = new IntentFilter(); filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); @@ -160,19 +172,11 @@ public class WifiController extends StateMachine { WifiManager.EXTRA_WIFI_AP_STATE, WifiManager.WIFI_AP_STATE_FAILED); if (state == WifiManager.WIFI_AP_STATE_FAILED) { - loge(TAG + "SoftAP start failed"); + Log.e(TAG, "SoftAP start failed"); sendMessage(CMD_AP_START_FAILURE); } else if (state == WifiManager.WIFI_AP_STATE_DISABLED) { sendMessage(CMD_AP_STOPPED); } - } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { - int state = intent.getIntExtra( - WifiManager.EXTRA_WIFI_STATE, - WifiManager.WIFI_STATE_UNKNOWN); - if (state == WifiManager.WIFI_STATE_UNKNOWN) { - loge(TAG + "Wifi turn on failed"); - sendMessage(CMD_STA_START_FAILURE); - } } else if (action.equals(LocationManager.MODE_CHANGED_ACTION)) { // Location mode has been toggled... trigger with the scan change // update to make sure we are in the correct mode @@ -194,6 +198,48 @@ public class WifiController extends StateMachine { return mSettingsStore.isScanAlwaysAvailable(); } + /** + * Listener used to receive scan mode updates - really needed for disabled updates to trigger + * mode changes. + */ + private class ScanOnlyCallback implements ScanOnlyModeManager.Listener { + @Override + public void onStateChanged(int state) { + if (state == WifiManager.WIFI_STATE_UNKNOWN) { + Log.d(TAG, "ScanOnlyMode unexpected failure: state unknown"); + } else if (state == WifiManager.WIFI_STATE_DISABLED) { + Log.d(TAG, "ScanOnlyMode stopped"); + sendMessage(CMD_SCANNING_STOPPED); + } else if (state == WifiManager.WIFI_STATE_ENABLED) { + // scan mode is ready to go + Log.d(TAG, "scan mode active"); + } else { + Log.d(TAG, "unexpected state update: " + state); + } + } + } + + /** + * Listener used to receive client mode updates + */ + private class ClientModeCallback implements ClientModeManager.Listener { + @Override + public void onStateChanged(int state) { + if (state == WifiManager.WIFI_STATE_UNKNOWN) { + logd("ClientMode unexpected failure: state unknown"); + sendMessage(CMD_STA_START_FAILURE); + } else if (state == WifiManager.WIFI_STATE_DISABLED) { + logd("ClientMode stopped"); + sendMessage(CMD_STA_STOPPED); + } else if (state == WifiManager.WIFI_STATE_ENABLED) { + // scan mode is ready to go + logd("client mode active"); + } else { + logd("unexpected state update: " + state); + } + } + } + private void readWifiReEnableDelay() { mReEnableDelayMillis = mFacade.getLongSetting(mContext, Settings.Global.WIFI_REENABLE_DELAY_MS, DEFAULT_REENABLE_DELAY_MS); @@ -216,11 +262,18 @@ public class WifiController extends StateMachine { case CMD_EMERGENCY_CALL_STATE_CHANGED: case CMD_AP_START_FAILURE: case CMD_AP_STOPPED: + case CMD_SCANNING_STOPPED: + case CMD_STA_STOPPED: case CMD_STA_START_FAILURE: - case CMD_RECOVERY_RESTART_WIFI: case CMD_RECOVERY_RESTART_WIFI_CONTINUE: case CMD_RECOVERY_DISABLE_WIFI: break; + case CMD_RECOVERY_RESTART_WIFI: + // TODO:b/72850700 : when softap is split out, we need to fully disable wifi + // here (like airplane mode toggle). + deferMessage(obtainMessage(CMD_RECOVERY_RESTART_WIFI_CONTINUE)); + transitionTo(mApStaDisabledState); + break; case CMD_USER_PRESENT: mFirstUserSignOnSeen = true; break; @@ -242,7 +295,6 @@ public class WifiController extends StateMachine { @Override public void enter() { - mWifiStateMachine.setOperationalMode(WifiStateMachine.DISABLED_MODE); mWifiStateMachinePrime.disableWifi(); // Supplicant can't restart right away, so note the time we switched off mDisabledTimestamp = SystemClock.elapsedRealtime(); @@ -264,11 +316,6 @@ public class WifiController extends StateMachine { mHaveDeferredEnable = !mHaveDeferredEnable; break; } - // wifi is toggled, we need to explicitly tell WifiStateMachine that we - // are headed to connect mode before going to the DeviceActiveState - // since that will start supplicant and WifiStateMachine may not know - // what state to head to (it might go to scan mode). - mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE); transitionTo(mDeviceActiveState); } else if (checkScanOnlyModeAvailable()) { transitionTo(mStaDisabledWithScanState); @@ -279,15 +326,17 @@ public class WifiController extends StateMachine { transitionTo(mStaDisabledWithScanState); break; } - mWifiStateMachine.setOperationalMode(WifiStateMachine.DISABLED_MODE); break; case CMD_SET_AP: + // first make sure we aren't in airplane mode + if (mSettingsStore.isAirplaneModeOn()) { + log("drop softap requests when in airplane mode"); + break; + } if (msg.arg1 == 1) { if (msg.arg2 == 0) { // previous wifi state has not been saved yet mSettingsStore.setWifiSavedState(WifiSettingsStore.WIFI_DISABLED); } - mWifiStateMachine.setHostApRunning((SoftApModeConfiguration) msg.obj, - true); mWifiStateMachinePrime.enterSoftAPMode((SoftApModeConfiguration) msg.obj); transitionTo(mApEnabledState); } @@ -301,7 +350,15 @@ public class WifiController extends StateMachine { sendMessage((Message)(msg.obj)); break; case CMD_RECOVERY_RESTART_WIFI_CONTINUE: - transitionTo(mDeviceActiveState); + if (mSettingsStore.isWifiToggleEnabled()) { + // wifi is currently disabled but the toggle is on, must have had an + // interface down before the recovery triggered + transitionTo(mDeviceActiveState); + break; + } else if (checkScanOnlyModeAvailable()) { + transitionTo(mStaDisabledWithScanState); + break; + } break; default: return NOT_HANDLED; @@ -372,15 +429,14 @@ public class WifiController extends StateMachine { break; case CMD_SET_AP: if (msg.arg1 == 1) { - // remeber that we were enabled + // remember that we were enabled mSettingsStore.setWifiSavedState(WifiSettingsStore.WIFI_ENABLED); - mWifiStateMachine.setHostApRunning((SoftApModeConfiguration) msg.obj, true); + // since softap is not split out in WifiController, need to explicitly + // disable client and scan modes + mWifiStateMachinePrime.disableWifi(); + 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: @@ -398,9 +454,6 @@ public class WifiController extends StateMachine { @Override public void enter() { - // first send the message to WSM to trigger the transition and act as a shadow - mWifiStateMachine.setOperationalMode(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE); - // now trigger the actual mode switch in WifiStateMachinePrime mWifiStateMachinePrime.enterScanOnlyMode(); @@ -424,8 +477,6 @@ public class WifiController extends StateMachine { mHaveDeferredEnable = !mHaveDeferredEnable; break; } - // transition from scan mode to initial state in WifiStateMachine - mWifiStateMachine.setOperationalMode(WifiStateMachine.DISABLED_MODE); transitionTo(mDeviceActiveState); } break; @@ -445,14 +496,12 @@ public class WifiController extends StateMachine { // Before starting tethering, turn off supplicant for scan mode if (msg.arg1 == 1) { mSettingsStore.setWifiSavedState(WifiSettingsStore.WIFI_DISABLED); + // since softap is not split out in WifiController, need to explicitly + // disable client and scan modes + mWifiStateMachinePrime.disableWifi(); - 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: @@ -517,31 +566,29 @@ public class WifiController extends StateMachine { } @Override + public void exit() { + mWifiStateMachinePrime.stopSoftAPMode(); + } + + @Override public boolean processMessage(Message msg) { switch (msg.what) { case CMD_AIRPLANE_TOGGLED: if (mSettingsStore.isAirplaneModeOn()) { - mWifiStateMachine.setHostApRunning(null, false); - mWifiStateMachinePrime.disableWifi(); - mPendingState = mApStaDisabledState; + transitionTo(mApStaDisabledState); } break; case CMD_WIFI_TOGGLED: if (mSettingsStore.isWifiToggleEnabled()) { - mWifiStateMachine.setHostApRunning(null, false); - mWifiStateMachinePrime.disableWifi(); - mPendingState = mDeviceActiveState; + transitionTo(mDeviceActiveState); } break; case CMD_SET_AP: if (msg.arg1 == 0) { - mWifiStateMachine.setHostApRunning(null, false); - mWifiStateMachinePrime.disableWifi(); - mPendingState = getNextWifiState(); + transitionTo(getNextWifiState()); } break; case CMD_AP_STOPPED: - mWifiStateMachine.setHostApRunning(null, false); if (mPendingState == null) { /** * Stop triggered internally, either tether notification @@ -554,13 +601,18 @@ public class WifiController extends StateMachine { case CMD_EMERGENCY_CALL_STATE_CHANGED: case CMD_EMERGENCY_MODE_CHANGED: if (msg.arg1 == 1) { - mWifiStateMachine.setHostApRunning(null, false); - mWifiStateMachinePrime.disableWifi(); - mPendingState = mEcmState; + transitionTo(mEcmState); } break; case CMD_AP_START_FAILURE: - mWifiStateMachine.setHostApRunning(null, false); + transitionTo(getNextWifiState()); + break; + case CMD_RECOVERY_RESTART_WIFI: + case CMD_RECOVERY_DISABLE_WIFI: + // note: this will need to fully shutdown wifi when softap mode is removed from + // the state machine + loge("Recovery triggered while in softap active, disable"); + mWifiStateMachinePrime.disableWifi(); transitionTo(getNextWifiState()); break; default: @@ -578,7 +630,6 @@ public class WifiController extends StateMachine { private int mEcmEntryCount; @Override public void enter() { - mWifiStateMachine.setOperationalMode(WifiStateMachine.DISABLED_MODE); mWifiStateMachinePrime.disableWifi(); mWifiStateMachine.clearANQPCache(); mEcmEntryCount = 1; @@ -605,6 +656,10 @@ public class WifiController extends StateMachine { decrementCountAndReturnToAppropriateState(); } return HANDLED; + } else if (msg.what == CMD_RECOVERY_RESTART_WIFI + || msg.what == CMD_RECOVERY_DISABLE_WIFI) { + // do not want to restart wifi if we are in emergency mode + return HANDLED; } else { return NOT_HANDLED; } @@ -636,7 +691,6 @@ public class WifiController extends StateMachine { class DeviceActiveState extends State { @Override public void enter() { - mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE); mWifiStateMachinePrime.enterClientMode(); mWifiStateMachine.setHighPerfModeEnabled(false); } diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java index 82f7d6cb2..cdde22268 100644 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ b/service/java/com/android/server/wifi/WifiInjector.java @@ -257,7 +257,7 @@ public class WifiInjector { this, mBackupManagerProxy, mCountryCode, mWifiNative, new WrongPasswordNotifier(mContext, mFrameworkFacade)); IBinder b = mFrameworkFacade.getService(Context.NETWORKMANAGEMENT_SERVICE); - mWifiStateMachinePrime = new WifiStateMachinePrime(this, wifiStateMachineLooper, + mWifiStateMachinePrime = new WifiStateMachinePrime(this, mContext, wifiStateMachineLooper, mWifiNative, new DefaultModeManager(mContext, wifiStateMachineLooper), mBatteryStats); mOpenNetworkNotifier = new OpenNetworkNotifier(mContext, @@ -474,7 +474,7 @@ public class WifiInjector { */ public ClientModeManager makeClientModeManager(ClientModeManager.Listener listener) { return new ClientModeManager(mContext, mWifiStateMachineHandlerThread.getLooper(), - mWifiNative, listener, mWifiMetrics, mScanRequestProxy); + mWifiNative, listener, mWifiMetrics, mScanRequestProxy, mWifiStateMachine); } /** diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index dbb83609b..32427c92c 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -96,8 +96,6 @@ import com.android.internal.util.MessageUtils; import com.android.internal.util.Protocol; import com.android.internal.util.State; import com.android.internal.util.StateMachine; -import com.android.server.wifi.WifiNative.InterfaceCallback; -import com.android.server.wifi.WifiNative.StatusListener; import com.android.server.wifi.hotspot2.AnqpEvent; import com.android.server.wifi.hotspot2.IconEvent; import com.android.server.wifi.hotspot2.NetworkDetail; @@ -130,17 +128,12 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; /** - * TODO: - * Deprecate WIFI_STATE_UNKNOWN - */ - -/** * Track the state of Wifi connectivity. All event handling is done here, * and all changes in connectivity state are initiated here. * * Wi-Fi now supports three modes of operation: Client, SoftAp and p2p * In the current implementation, we support concurrent wifi p2p and wifi operation. - * The WifiStateMachine handles SoftAp and Client operations while WifiP2pService + * The WifiStateMachine handles Client operations while WifiP2pService * handles p2p operation. * * @hide @@ -196,7 +189,6 @@ public class WifiStateMachine extends StateMachine { private ConnectivityManager mCm; private BaseWifiDiagnostics mWifiDiagnostics; private ScanRequestProxy mScanRequestProxy; - private WifiApConfigStore mWifiApConfigStore; private final boolean mP2pSupported; private final AtomicBoolean mP2pConnected = new AtomicBoolean(false); private boolean mTemporarilyDisconnectWifi = false; @@ -221,45 +213,8 @@ public class WifiStateMachine extends StateMachine { private String mLastBssid; private int mLastNetworkId; // The network Id we successfully joined - private final StatusListener mWifiNativeStatusListener = (boolean isReady) -> { - if (!isReady) { - sendMessage(CMD_WIFINATIVE_FAILURE); - } - }; - - private final InterfaceCallback mWifiNativeInterfaceCallback = new InterfaceCallback() { - @Override - public void onDestroyed(String ifaceName) { - if (mInterfaceName != null && mInterfaceName.equals(ifaceName)) { - sendMessage(CMD_INTERFACE_DESTROYED); - } - } - - @Override - public void onUp(String ifaceName) { - if (mInterfaceName != null && mInterfaceName.equals(ifaceName)) { - sendMessage(CMD_INTERFACE_STATUS_CHANGED, 1); - } - } - - @Override - public void onDown(String ifaceName) { - if (mInterfaceName != null && mInterfaceName.equals(ifaceName)) { - sendMessage(CMD_INTERFACE_STATUS_CHANGED, 0); - } - } - }; private boolean mIpReachabilityDisconnectEnabled = true; - private WifiManager.SoftApCallback mSoftApCallback; - - /** - * Called from WifiServiceImpl to register a callback for notifications from SoftApManager - */ - public void registerSoftApCallback(WifiManager.SoftApCallback callback) { - mSoftApCallback = callback; - } - private void processRssiThreshold(byte curRssi, int reason, WifiNative.WifiRssiEventHandler rssiHandler) { if (curRssi == Byte.MAX_VALUE || curRssi == Byte.MIN_VALUE) { @@ -303,6 +258,8 @@ public class WifiStateMachine extends StateMachine { // variable indicating we are expecting a mode switch - do not attempt recovery for failures private boolean mModeChange = false; + private ClientModeManager.Listener mClientModeCallback = null; + private boolean mBluetoothConnectionActive = false; private PowerManager.WakeLock mSuspendWakeLock; @@ -460,29 +417,10 @@ public class WifiStateMachine extends StateMachine { /* The base for wifi message types */ static final int BASE = Protocol.BASE_WIFI; - /* Start the STA interface */ - static final int CMD_START_SUPPLICANT = BASE + 11; - /* Stop the STA interface */ - static final int CMD_STOP_SUPPLICANT = BASE + 12; - /* STA interface destroyed */ - static final int CMD_INTERFACE_DESTROYED = BASE + 13; - /* STA interface down */ - static final int CMD_INTERFACE_DOWN = BASE + 14; /* Indicates Static IP succeeded */ static final int CMD_STATIC_IP_SUCCESS = BASE + 15; /* Indicates Static IP failed */ static final int CMD_STATIC_IP_FAILURE = BASE + 16; - /* Interface status change */ - static final int CMD_INTERFACE_STATUS_CHANGED = BASE + 20; - - /* Start the soft access point */ - static final int CMD_START_AP = BASE + 21; - /* Indicates soft ap start failed */ - static final int CMD_START_AP_FAILURE = BASE + 22; - /* Stop the soft access point */ - static final int CMD_STOP_AP = BASE + 23; - /* Soft access point teardown is completed. */ - static final int CMD_AP_STOPPED = BASE + 24; static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 31; @@ -698,9 +636,6 @@ public class WifiStateMachine extends StateMachine { /* used to indicate that the foreground user was switched */ static final int CMD_USER_STOP = BASE + 207; - /* Signals that one of the native daemons is dead. */ - private static final int CMD_WIFINATIVE_FAILURE = BASE + 250; - /* Indicates that diagnostics should time out a connection start event. */ private static final int CMD_DIAGS_CONNECT_TIMEOUT = BASE + 252; @@ -776,12 +711,6 @@ public class WifiStateMachine extends StateMachine { /* Default parent state */ private State mDefaultState = new DefaultState(); - /* Temporary initial state */ - private State mInitialState = new InitialState(); - /* Driver loaded and supplicant ready */ - private State mSupplicantStartedState = new SupplicantStartedState(); - /* Scan for networks, no connection will be established */ - private State mScanModeState = new ScanModeState(); /* Connecting to an access point */ private State mConnectModeState = new ConnectModeState(); /* Connected at 802.11 (L2) level */ @@ -796,8 +725,6 @@ public class WifiStateMachine extends StateMachine { private State mDisconnectingState = new DisconnectingState(); /* Network is not connected, supplicant assoc+auth is not complete */ private State mDisconnectedState = new DisconnectedState(); - /* Soft ap state */ - private State mSoftApState = new SoftApState(); /** * One of {@link WifiManager#WIFI_STATE_DISABLED}, @@ -998,17 +925,13 @@ public class WifiStateMachine extends StateMachine { // CHECKSTYLE:OFF IndentationCheck addState(mDefaultState); - addState(mInitialState, mDefaultState); - addState(mSupplicantStartedState, mInitialState); - addState(mConnectModeState, mSupplicantStartedState); - addState(mL2ConnectedState, mConnectModeState); - addState(mObtainingIpState, mL2ConnectedState); - addState(mConnectedState, mL2ConnectedState); - addState(mRoamingState, mL2ConnectedState); - addState(mDisconnectingState, mConnectModeState); - addState(mDisconnectedState, mConnectModeState); - addState(mScanModeState, mDefaultState); - addState(mSoftApState, mDefaultState); + addState(mConnectModeState, mDefaultState); + addState(mL2ConnectedState, mConnectModeState); + addState(mObtainingIpState, mL2ConnectedState); + addState(mConnectedState, mL2ConnectedState); + addState(mRoamingState, mL2ConnectedState); + addState(mDisconnectingState, mConnectModeState); + addState(mDisconnectedState, mConnectModeState); // CHECKSTYLE:ON IndentationCheck setInitialState(mDefaultState); @@ -1022,13 +945,6 @@ public class WifiStateMachine extends StateMachine { // Learn the initial state of whether the screen is on. // We update this field when we receive broadcasts from the system. handleScreenStateChanged(powerManager.isInteractive()); - - final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED); - mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); - - sendWifiScanAvailable(false); } private void registerForWifiMonitorEvents() { @@ -1457,28 +1373,6 @@ public class WifiStateMachine extends StateMachine { /** * TODO: doc */ - public void setSupplicantRunning(boolean enable) { - if (enable) { - sendMessage(CMD_START_SUPPLICANT); - } else { - sendMessage(CMD_STOP_SUPPLICANT); - } - } - - /** - * TODO: doc - */ - public void setHostApRunning(SoftApModeConfiguration wifiConfig, boolean enable) { - if (enable) { - sendMessage(CMD_START_AP, wifiConfig); - } else { - sendMessage(CMD_STOP_AP); - } - } - - /** - * TODO: doc - */ public int syncGetWifiState() { return mWifiState.get(); } @@ -1554,9 +1448,12 @@ public class WifiStateMachine extends StateMachine { /** * TODO: doc */ - public void setOperationalMode(int mode) { - if (mVerboseLoggingEnabled) log("setting operational mode to " + String.valueOf(mode)); + public void setOperationalMode(int mode, String ifaceName) { + if (mVerboseLoggingEnabled) { + log("setting operational mode to " + String.valueOf(mode) + " for iface: " + ifaceName); + } mModeChange = true; + mInterfaceName = ifaceName; sendMessage(CMD_SET_OPERATIONAL_MODE, mode, 0); } @@ -2532,17 +2429,6 @@ public class WifiStateMachine extends StateMachine { if (mVerboseLoggingEnabled) log("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled); } - private void sendWifiScanAvailable(boolean available) { - int state = WIFI_STATE_DISABLED; - if (available) { - state = WIFI_STATE_ENABLED; - } - final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, state); - mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); - } - private void setWifiState(int wifiState) { final int previousWifiState = mWifiState.get(); @@ -2550,6 +2436,17 @@ public class WifiStateMachine extends StateMachine { if (mVerboseLoggingEnabled) log("setWifiState: " + syncGetWifiStateByName()); + // first let WifiController know what is going on + if (mClientModeCallback != null) { + mClientModeCallback.onStateChanged(wifiState); + // once this instance of client mode is complete, remove the callback so we don't + // confuse ourselves + if (wifiState == WifiManager.WIFI_STATE_UNKNOWN + || wifiState == WifiManager.WIFI_STATE_DISABLED) { + mClientModeCallback = null; + } + } + final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState); @@ -3373,20 +3270,22 @@ public class WifiStateMachine extends StateMachine { } /** - * Handle the error case where our underlying interface went down (if we do not have mac - * randomization enabled (b/72459123). + * Helper method to check if Connected MAC Randomization is enabled - onDown events are skipped + * if this feature is enabled (b/72459123). * - * This method triggers SelfRecovery with the error of REASON_STA_IFACE_DOWN. SelfRecovery then - * decides if wifi should be restarted or disabled. + * @return boolean true if Connected MAC randomization is enabled, false otherwise */ - private void handleInterfaceDown() { - if (mEnableConnectedMacRandomization.get()) { - // interface will go down when mac randomization is active, skip - Log.d(TAG, "MacRandomization enabled, ignoring iface down"); - return; - } + public boolean isConnectedMacRandomizationEnabled() { + return mEnableConnectedMacRandomization.get(); + } - Log.e(TAG, "Detected an interface down, report failure to SelfRecovery"); + /** + * Helper method allowing ClientModeManager to report an error (interface went down) and trigger + * recovery. + * + * @param reason int indicating the SelfRecovery failure type. + */ + public void failureDetected(int reason) { // report a failure mWifiInjector.getSelfRecovery().trigger(SelfRecovery.REASON_STA_IFACE_DOWN); } @@ -3497,11 +3396,6 @@ public class WifiStateMachine extends StateMachine { case CMD_SCREEN_STATE_CHANGED: handleScreenStateChanged(message.arg1 != 0); break; - case CMD_START_SUPPLICANT: - case CMD_STOP_SUPPLICANT: - case CMD_START_AP_FAILURE: - case CMD_STOP_AP: - case CMD_AP_STOPPED: case CMD_DISCONNECT: case CMD_RECONNECT: case CMD_REASSOCIATE: @@ -3530,15 +3424,8 @@ public class WifiStateMachine extends StateMachine { case CMD_DISABLE_P2P_WATCHDOG_TIMER: case CMD_DISABLE_EPHEMERAL_NETWORK: case CMD_SELECT_TX_POWER_SCENARIO: - case CMD_WIFINATIVE_FAILURE: - case CMD_INTERFACE_DESTROYED: - case CMD_INTERFACE_DOWN: - case CMD_INTERFACE_STATUS_CHANGED: messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; break; - case CMD_START_AP: - transitionTo(mSoftApState); - break; case CMD_SET_OPERATIONAL_MODE: mOperationalMode = message.arg1; // now processing the mode change - we will start setting up new state and want @@ -3549,10 +3436,7 @@ public class WifiStateMachine extends StateMachine { transitionTo(mDefaultState); break; } else if (mOperationalMode == CONNECT_MODE) { - transitionTo(mInitialState); - } else if (mOperationalMode == SCAN_ONLY_MODE - || mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { - transitionTo(mScanModeState); + transitionTo(mDisconnectedState); } else { Log.e(TAG, "set operational mode with invalid mode: " + mOperationalMode); mOperationalMode = DISABLED_MODE; @@ -3721,337 +3605,6 @@ public class WifiStateMachine extends StateMachine { } } - class InitialState extends State { - private boolean mIfaceIsUp; - - private void onUpChanged(boolean isUp) { - if (isUp == mIfaceIsUp) { - return; // no change - } - mIfaceIsUp = isUp; - if (isUp) { - Log.d(TAG, "Client mode interface is up"); - // for now, do nothing - client mode has never waited for iface up - } else { - // A driver/firmware hang can now put the interface in a down state. - // We detect the interface going down and recover from it - handleInterfaceDown(); - } - } - - private void cleanup() { - // tell scanning service that scans are not available - about to kill the interface and - // supplicant - sendWifiScanAvailable(false); - - mWifiNative.registerStatusListener(mWifiNativeStatusListener); - // TODO: This teardown should ideally be handled in STOP_SUPPLICANT to be consistent - // with other mode managers. But, client mode is not yet controlled by - // WifiStateMachinePrime. - // TODO: Remove this big hammer. We cannot support concurrent interfaces with this! - mWifiNative.teardownAllInterfaces(); - mInterfaceName = null; - mIfaceIsUp = false; - } - - @Override - public void enter() { - mIfaceIsUp = false; - mWifiStateTracker.updateState(WifiStateTracker.INVALID); - cleanup(); - sendMessage(CMD_START_SUPPLICANT); - setWifiState(WIFI_STATE_ENABLING); - } - - @Override - public boolean processMessage(Message message) { - logStateAndMessage(message, this); - switch (message.what) { - case CMD_START_SUPPLICANT: - mInterfaceName = mWifiNative.setupInterfaceForClientMode(false, - mWifiNativeInterfaceCallback); - if (TextUtils.isEmpty(mInterfaceName)) { - Log.e(TAG, "setup failure when creating client interface."); - setWifiState(WifiManager.WIFI_STATE_UNKNOWN); - transitionTo(mDefaultState); - break; - } - // now that we have the interface, initialize our up/down status - onUpChanged(mWifiNative.isInterfaceUp(mInterfaceName)); - - mIpClient = mFacade.makeIpClient( - mContext, mInterfaceName, new IpClientCallback()); - mIpClient.setMulticastFilter(true); - if (mVerboseLoggingEnabled) log("Supplicant start successful"); - registerForWifiMonitorEvents(); - mWifiInjector.getWifiLastResortWatchdog().clearAllFailureCounts(); - setSupplicantLogLevel(); - transitionTo(mSupplicantStartedState); - break; - case CMD_SET_OPERATIONAL_MODE: - if (message.arg1 == CONNECT_MODE) { - break; - } else { - return NOT_HANDLED; - } - case CMD_WIFINATIVE_FAILURE: - Log.e(TAG, "One of the native daemons died unexpectedly. Triggering recovery"); - mWifiDiagnostics.captureBugReportData( - WifiDiagnostics.REPORT_REASON_WIFINATIVE_FAILURE); - mWifiInjector.getSelfRecovery().trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE); - break; - case CMD_INTERFACE_STATUS_CHANGED: - boolean isUp = message.arg1 == 1; - // For now, this message can be triggered due to link state and/or interface - // status changes (b/77218676). First check if we really see an iface down by - // consulting our view of supplicant state. - if (!isUp && SupplicantState.isDriverActive(mWifiInfo.getSupplicantState())) { - // the driver is active, so this could just be part of normal operation, do - // not disable wifi in these cases (ex, a network was removed) or worry - // about the link status - break; - } - - onUpChanged(isUp); - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class SupplicantStartedState extends State { - @Override - public void enter() { - if (mVerboseLoggingEnabled) { - logd("SupplicantStartedState enter"); - } - - // reset state related to supplicant starting - mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); - // Initialize data structures - mLastBssid = null; - mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; - mLastSignalLevel = -1; - mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName)); - // Attempt to migrate data out of legacy store. - if (!mWifiConfigManager.migrateFromLegacyStore()) { - Log.e(TAG, "Failed to migrate from legacy config store"); - } - sendSupplicantConnectionChangedBroadcast(true); - - mWifiNative.setExternalSim(mInterfaceName, true); - - setRandomMacOui(); - mCountryCode.setReadyForChange(true); - - if (mWifiConnectivityManager == null) { - synchronized (mWifiReqCountLock) { - mWifiConnectivityManager = - mWifiInjector.makeWifiConnectivityManager(mWifiInfo, - hasConnectionRequests()); - mWifiConnectivityManager.setUntrustedConnectionAllowed(mUntrustedReqCount > 0); - mWifiConnectivityManager.handleScreenStateChanged(mScreenOn); - } - } - - mWifiDiagnostics.startLogging(mVerboseLoggingEnabled); - mIsRunning = true; - updateBatteryWorkSource(null); - /** - * Enable bluetooth coexistence scan mode when bluetooth connection is active. - * When this mode is on, some of the low-level scan parameters used by the - * driver are changed to reduce interference with bluetooth - */ - mWifiNative.setBluetoothCoexistenceScanMode(mInterfaceName, mBluetoothConnectionActive); - // Check if there is a voice call on-going and set/reset the tx power limit - // appropriately. - if (mEnableVoiceCallSarTxPowerLimit) { - if (getTelephonyManager().isOffhook()) { - sendMessage(CMD_SELECT_TX_POWER_SCENARIO, - WifiNative.TX_POWER_SCENARIO_VOICE_CALL); - } else { - sendMessage(CMD_SELECT_TX_POWER_SCENARIO, - WifiNative.TX_POWER_SCENARIO_NORMAL); - } - } - - // initialize network state - setNetworkDetailedState(DetailedState.DISCONNECTED); - - // Disable legacy multicast filtering, which on some chipsets defaults to enabled. - // Legacy IPv6 multicast filtering blocks ICMPv6 router advertisements which breaks IPv6 - // provisioning. Legacy IPv4 multicast filtering may be re-enabled later via - // IpClient.Callback.setFallbackMulticastFilter() - mWifiNative.stopFilteringMulticastV4Packets(mInterfaceName); - mWifiNative.stopFilteringMulticastV6Packets(mInterfaceName); - - // Transitioning to Disconnected state will trigger a scan and subsequently AutoJoin - transitionTo(mDisconnectedState); - - // Set the right suspend mode settings - mWifiNative.setSuspendOptimizations(mInterfaceName, mSuspendOptNeedsDisabled == 0 - && mUserWantsSuspendOpt.get()); - - mWifiNative.setPowerSave(mInterfaceName, true); - - if (mP2pSupported) { - p2pSendMessage(WifiStateMachine.CMD_ENABLE_P2P); - } - - // Disable wpa_supplicant from auto reconnecting. - mWifiNative.enableStaAutoReconnect(mInterfaceName, false); - // STA has higher priority over P2P - mWifiNative.setConcurrencyPriority(true); - } - - @Override - public boolean processMessage(Message message) { - logStateAndMessage(message, this); - - switch(message.what) { - case CMD_TARGET_BSSID: - // Trying to associate to this BSSID - if (message.obj != null) { - mTargetRoamBSSID = (String) message.obj; - } - break; - case CMD_GET_LINK_LAYER_STATS: - WifiLinkLayerStats stats = getWifiLinkLayerStats(); - replyToMessage(message, message.what, stats); - break; - case CMD_RESET_SIM_NETWORKS: - log("resetting EAP-SIM/AKA/AKA' networks since SIM was changed"); - mWifiConfigManager.resetSimNetworks(message.arg1 == 1); - break; - case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: - mBluetoothConnectionActive = (message.arg1 != - BluetoothAdapter.STATE_DISCONNECTED); - mWifiNative.setBluetoothCoexistenceScanMode( - mInterfaceName, mBluetoothConnectionActive); - break; - case CMD_SET_SUSPEND_OPT_ENABLED: - if (message.arg1 == 1) { - setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, true); - if (message.arg2 == 1) { - mSuspendWakeLock.release(); - } - } else { - setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, false); - } - break; - case CMD_SET_HIGH_PERF_MODE: - if (message.arg1 == 1) { - setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, false); - } else { - setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true); - } - break; - case CMD_ENABLE_TDLS: - if (message.obj != null) { - String remoteAddress = (String) message.obj; - boolean enable = (message.arg1 == 1); - mWifiNative.startTdls(mInterfaceName, remoteAddress, enable); - } - break; - case WifiMonitor.ANQP_DONE_EVENT: - // TODO(zqiu): remove this when switch over to wificond for ANQP requests. - mPasspointManager.notifyANQPDone((AnqpEvent) message.obj); - break; - case CMD_STOP_IP_PACKET_OFFLOAD: { - int slot = message.arg1; - int ret = stopWifiIPPacketOffload(slot); - if (mNetworkAgent != null) { - mNetworkAgent.onPacketKeepaliveEvent(slot, ret); - } - break; - } - case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: - // TODO(zqiu): remove this when switch over to wificond for icon requests. - mPasspointManager.notifyIconDone((IconEvent) message.obj); - break; - case WifiMonitor.HS20_REMEDIATION_EVENT: - // TODO(zqiu): remove this when switch over to wificond for WNM frames - // monitoring. - mPasspointManager.receivedWnmFrame((WnmData) message.obj); - break; - case CMD_CONFIG_ND_OFFLOAD: - final boolean enabled = (message.arg1 > 0); - mWifiNative.configureNeighborDiscoveryOffload(mInterfaceName, enabled); - break; - case CMD_ENABLE_WIFI_CONNECTIVITY_MANAGER: - mWifiConnectivityManager.enable(message.arg1 == 1 ? true : false); - break; - case CMD_SELECT_TX_POWER_SCENARIO: - int txPowerScenario = message.arg1; - logd("Setting Tx power scenario to " + txPowerScenario); - if (!mWifiNative.selectTxPowerScenario(txPowerScenario)) { - loge("Failed to set TX power scenario"); - } - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - - @Override - public void exit() { - setWifiState(WIFI_STATE_DISABLING); - // when client mode is moved to WSMP, cleanup will be done on exit. For now, cleanup is - // done when entering a mode. - - // exiting supplicant started state is now only applicable to client mode - mWifiDiagnostics.stopLogging(); - - if (mP2pSupported) { - // we are not going to wait for a response - will still temporarily send the - // disable command until p2p can detect the interface up/down on its own. - p2pSendMessage(WifiStateMachine.CMD_DISABLE_P2P_REQ); - } - - handleNetworkDisconnect(); - - mIsRunning = false; - updateBatteryWorkSource(null); - - mNetworkInfo.setIsAvailable(false); - if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo); - mCountryCode.setReadyForChange(false); - setWifiState(WIFI_STATE_DISABLED); - } - } - - class ScanModeState extends State { - private int mLastOperationMode; - @Override - public void enter() { - logd("entering ScanModeState"); - mWifiStateTracker.updateState(WifiStateTracker.SCAN_MODE); - } - - @Override - public void exit() {} - - @Override - public boolean processMessage(Message message) { - logStateAndMessage(message, this); - - if (message.what == CMD_SET_OPERATIONAL_MODE) { - int operationMode = message.arg1; - if (operationMode == SCAN_ONLY_MODE - || operationMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { - // nothing to do, stay here... - return HANDLED; - } - return NOT_HANDLED; - } - return NOT_HANDLED; - } - } - - String smToString(Message message) { return smToString(message.what); } @@ -4141,6 +3694,113 @@ public class WifiStateMachine extends StateMachine { return s; } + /** + * Helper method to start other services and get state ready for client mode + */ + private void setupClientMode() { + mWifiStateTracker.updateState(WifiStateTracker.INVALID); + + if (mWifiConnectivityManager == null) { + synchronized (mWifiReqCountLock) { + mWifiConnectivityManager = + mWifiInjector.makeWifiConnectivityManager(mWifiInfo, + hasConnectionRequests()); + mWifiConnectivityManager.setUntrustedConnectionAllowed(mUntrustedReqCount > 0); + mWifiConnectivityManager.handleScreenStateChanged(mScreenOn); + } + } + + mIpClient = mFacade.makeIpClient(mContext, mInterfaceName, new IpClientCallback()); + mIpClient.setMulticastFilter(true); + registerForWifiMonitorEvents(); + mWifiInjector.getWifiLastResortWatchdog().clearAllFailureCounts(); + setSupplicantLogLevel(); + + // reset state related to supplicant starting + mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); + // Initialize data structures + mLastBssid = null; + mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; + mLastSignalLevel = -1; + mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName)); + // Attempt to migrate data out of legacy store. + if (!mWifiConfigManager.migrateFromLegacyStore()) { + Log.e(TAG, "Failed to migrate from legacy config store"); + } + sendSupplicantConnectionChangedBroadcast(true); + + mWifiNative.setExternalSim(mInterfaceName, true); + + setRandomMacOui(); + mCountryCode.setReadyForChange(true); + + mWifiDiagnostics.startLogging(mVerboseLoggingEnabled); + mIsRunning = true; + updateBatteryWorkSource(null); + + /** + * Enable bluetooth coexistence scan mode when bluetooth connection is active. + * When this mode is on, some of the low-level scan parameters used by the + * driver are changed to reduce interference with bluetooth + */ + mWifiNative.setBluetoothCoexistenceScanMode(mInterfaceName, mBluetoothConnectionActive); + // Check if there is a voice call on-going and set/reset the tx power limit appropriately. + if (mEnableVoiceCallSarTxPowerLimit) { + if (getTelephonyManager().isOffhook()) { + sendMessage(CMD_SELECT_TX_POWER_SCENARIO, WifiNative.TX_POWER_SCENARIO_VOICE_CALL); + } else { + sendMessage(CMD_SELECT_TX_POWER_SCENARIO, WifiNative.TX_POWER_SCENARIO_NORMAL); + } + } + + // initialize network state + setNetworkDetailedState(DetailedState.DISCONNECTED); + + // Disable legacy multicast filtering, which on some chipsets defaults to enabled. + // Legacy IPv6 multicast filtering blocks ICMPv6 router advertisements which breaks IPv6 + // provisioning. Legacy IPv4 multicast filtering may be re-enabled later via + // IpClient.Callback.setFallbackMulticastFilter() + mWifiNative.stopFilteringMulticastV4Packets(mInterfaceName); + mWifiNative.stopFilteringMulticastV6Packets(mInterfaceName); + + // Set the right suspend mode settings + mWifiNative.setSuspendOptimizations(mInterfaceName, mSuspendOptNeedsDisabled == 0 + && mUserWantsSuspendOpt.get()); + + mWifiNative.setPowerSave(mInterfaceName, true); + + if (mP2pSupported) { + p2pSendMessage(WifiStateMachine.CMD_ENABLE_P2P); + } + + // Disable wpa_supplicant from auto reconnecting. + mWifiNative.enableStaAutoReconnect(mInterfaceName, false); + // STA has higher priority over P2P + mWifiNative.setConcurrencyPriority(true); + } + + /** + * Helper method to stop external services and clean up state from client mode. + */ + private void stopClientMode() { + // exiting supplicant started state is now only applicable to client mode + mWifiDiagnostics.stopLogging(); + + if (mP2pSupported) { + // we are not going to wait for a response - will still temporarily send the + // disable command until p2p can detect the interface up/down on its own. + p2pSendMessage(WifiStateMachine.CMD_DISABLE_P2P_REQ); + } + + mIsRunning = false; + updateBatteryWorkSource(null); + + mNetworkInfo.setIsAvailable(false); + if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo); + mCountryCode.setReadyForChange(false); + setWifiState(WIFI_STATE_DISABLED); + } + void registerConnected() { if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { mWifiConfigManager.updateNetworkAfterConnect(mLastNetworkId); @@ -4201,13 +3861,13 @@ public class WifiStateMachine extends StateMachine { @Override public void enter() { + setupClientMode(); if (!mWifiNative.removeAllNetworks(mInterfaceName)) { loge("Failed to remove networks on entering connect mode"); } mScanRequestProxy.enableScanningForHiddenNetworks(true); mWifiInfo.reset(); mWifiInfo.setSupplicantState(SupplicantState.DISCONNECTED); - sendWifiScanAvailable(true); // Let the system know that wifi is available in client mode. setWifiState(WIFI_STATE_ENABLED); @@ -4247,6 +3907,7 @@ public class WifiStateMachine extends StateMachine { mWifiInfo.reset(); mWifiInfo.setSupplicantState(SupplicantState.DISCONNECTED); setWifiState(WIFI_STATE_DISABLED); + stopClientMode(); } @Override @@ -4264,6 +3925,12 @@ public class WifiStateMachine extends StateMachine { logStateAndMessage(message, this); switch (message.what) { + case CMD_SET_OPERATIONAL_MODE: + if (message.arg1 == CONNECT_MODE) { + break; + } else { + return NOT_HANDLED; + } case WifiMonitor.ASSOCIATION_REJECTION_EVENT: mWifiDiagnostics.captureBugReportData( WifiDiagnostics.REPORT_REASON_ASSOC_FAILURE); @@ -4355,18 +4022,6 @@ public class WifiStateMachine extends StateMachine { mIpClient.confirmConfiguration(); mWifiScoreReport.noteIpCheck(); } - - if (!SupplicantState.isDriverActive(state)) { - // still use supplicant to detect interface down while work to - // mitigate b/77218676 is in progress - // note: explicitly using this command to dedup iface down notification - // paths (onUpChanged filters out duplicate updates) - sendMessage(CMD_INTERFACE_STATUS_CHANGED, 0); - if (mVerboseLoggingEnabled) { - Log.d(TAG, "detected interface down via supplicant"); - } - } - break; case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: if (message.arg1 == 1) { @@ -4791,6 +4446,86 @@ public class WifiStateMachine extends StateMachine { replyToMessage(message, message.what, mPasspointManager.getAllMatchingWifiConfigs((ScanResult) message.obj)); break; + case CMD_TARGET_BSSID: + // Trying to associate to this BSSID + if (message.obj != null) { + mTargetRoamBSSID = (String) message.obj; + } + break; + case CMD_GET_LINK_LAYER_STATS: + WifiLinkLayerStats stats = getWifiLinkLayerStats(); + replyToMessage(message, message.what, stats); + break; + case CMD_RESET_SIM_NETWORKS: + log("resetting EAP-SIM/AKA/AKA' networks since SIM was changed"); + mWifiConfigManager.resetSimNetworks(message.arg1 == 1); + break; + case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: + mBluetoothConnectionActive = (message.arg1 + != BluetoothAdapter.STATE_DISCONNECTED); + mWifiNative.setBluetoothCoexistenceScanMode( + mInterfaceName, mBluetoothConnectionActive); + break; + case CMD_SET_SUSPEND_OPT_ENABLED: + if (message.arg1 == 1) { + setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, true); + if (message.arg2 == 1) { + mSuspendWakeLock.release(); + } + } else { + setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, false); + } + break; + case CMD_SET_HIGH_PERF_MODE: + if (message.arg1 == 1) { + setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, false); + } else { + setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true); + } + break; + case CMD_ENABLE_TDLS: + if (message.obj != null) { + String remoteAddress = (String) message.obj; + boolean enable = (message.arg1 == 1); + mWifiNative.startTdls(mInterfaceName, remoteAddress, enable); + } + break; + case WifiMonitor.ANQP_DONE_EVENT: + // TODO(zqiu): remove this when switch over to wificond for ANQP requests. + mPasspointManager.notifyANQPDone((AnqpEvent) message.obj); + break; + case CMD_STOP_IP_PACKET_OFFLOAD: { + int slot = message.arg1; + int ret = stopWifiIPPacketOffload(slot); + if (mNetworkAgent != null) { + mNetworkAgent.onPacketKeepaliveEvent(slot, ret); + } + break; + } + case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: + // TODO(zqiu): remove this when switch over to wificond for icon requests. + mPasspointManager.notifyIconDone((IconEvent) message.obj); + break; + case WifiMonitor.HS20_REMEDIATION_EVENT: + // TODO(zqiu): remove this when switch over to wificond for WNM frames + // monitoring. + mPasspointManager.receivedWnmFrame((WnmData) message.obj); + break; + case CMD_CONFIG_ND_OFFLOAD: + final boolean enabled = (message.arg1 > 0); + mWifiNative.configureNeighborDiscoveryOffload(mInterfaceName, enabled); + break; + case CMD_ENABLE_WIFI_CONNECTIVITY_MANAGER: + mWifiConnectivityManager.enable(message.arg1 == 1 ? true : false); + break; + case CMD_SELECT_TX_POWER_SCENARIO: + int txPowerScenario = message.arg1; + logd("Setting Tx power scenario to " + txPowerScenario); + if (!mWifiNative.selectTxPowerScenario(txPowerScenario)) { + loge("Failed to set TX power scenario"); + } + break; + default: return NOT_HANDLED; } @@ -5900,115 +5635,6 @@ public class WifiStateMachine extends StateMachine { } } - class SoftApState extends State { - private SoftApManager mSoftApManager; - private String mIfaceName; - private int mMode; - - /* - private class SoftApCallbackImpl implements WifiManager.SoftApCallback { - @Override - public void onStateChanged(int state, int reason) { - if (state == WIFI_AP_STATE_DISABLED) { - sendMessage(CMD_AP_STOPPED); - } else if (state == WIFI_AP_STATE_FAILED) { - sendMessage(CMD_START_AP_FAILURE); - } - - setWifiApState(state, reason, mIfaceName, mMode); - - if (mSoftApCallback != null) { - mSoftApCallback.onStateChanged(state, reason); - } - } - - @Override - public void onNumClientsChanged(int numClients) { - if (mSoftApCallback != null) { - mSoftApCallback.onNumClientsChanged(numClients); - } - } - } - */ - - @Override - public void enter() { - final Message message = getCurrentMessage(); - if (message.what != CMD_START_AP) { - throw new RuntimeException("Illegal transition to SoftApState: " + message); - } - /* - SoftApModeConfiguration config = (SoftApModeConfiguration) message.obj; - mMode = config.getTargetMode(); - - IApInterface apInterface = null; - Pair<Integer, IApInterface> statusAndInterface = - mWifiNative.setupForSoftApMode(mInterfaceName); - if (statusAndInterface.first == WifiNative.SETUP_SUCCESS) { - apInterface = statusAndInterface.second; - } else { - incrementMetricsForSetupFailure(statusAndInterface.first); - } - if (apInterface == null) { - setWifiApState(WIFI_AP_STATE_FAILED, - WifiManager.SAP_START_FAILURE_GENERAL, null, mMode); - // Transition to InitialState to reset the driver/HAL back to the initial state. - transitionTo(mInitialState); - return; - } - - try { - mIfaceName = apInterface.getInterfaceName(); - } catch (RemoteException e) { - // Failed to get the interface name. This is not a good sign and we should report - // a failure and switch back to the initial state to reset the driver and HAL. - setWifiApState(WIFI_AP_STATE_FAILED, - WifiManager.SAP_START_FAILURE_GENERAL, null, mMode); - transitionTo(mInitialState); - return; - } - - checkAndSetConnectivityInstance(); - mSoftApManager = mWifiInjector.makeSoftApManager(mNwService, - new SoftApCallbackImpl(), - config); - mSoftApManager.start(); - mWifiStateTracker.updateState(WifiStateTracker.SOFT_AP); - */ - } - - @Override - public void exit() { - mSoftApManager = null; - mIfaceName = null; - mMode = WifiManager.IFACE_IP_MODE_UNSPECIFIED; - } - - @Override - public boolean processMessage(Message message) { - logStateAndMessage(message, this); - - switch(message.what) { - case CMD_START_AP: - /* Ignore start command when it is starting/started. */ - break; - case CMD_STOP_AP: - //mSoftApManager.stop(); - transitionTo(mDefaultState); - break; - case CMD_START_AP_FAILURE: - transitionTo(mDefaultState); - break; - case CMD_AP_STOPPED: - transitionTo(mDefaultState); - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - /** * State machine initiated requests can have replyTo set to null indicating * there are no recepients, we ignore those reply actions. diff --git a/service/java/com/android/server/wifi/WifiStateMachinePrime.java b/service/java/com/android/server/wifi/WifiStateMachinePrime.java index 8eb521cbb..fea191614 100644 --- a/service/java/com/android/server/wifi/WifiStateMachinePrime.java +++ b/service/java/com/android/server/wifi/WifiStateMachinePrime.java @@ -17,8 +17,11 @@ package com.android.server.wifi; import android.annotation.NonNull; +import android.content.Context; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; +import android.os.BatteryStats; +import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.RemoteException; @@ -29,9 +32,7 @@ import com.android.internal.app.IBatteryStats; import com.android.internal.util.Protocol; import com.android.internal.util.State; import com.android.internal.util.StateMachine; - -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; +import com.android.server.wifi.WifiNative.StatusListener; /** * This class provides the implementation for different WiFi operating modes. @@ -50,11 +51,13 @@ public class WifiStateMachinePrime { private DefaultModeManager mDefaultModeManager; private final WifiInjector mWifiInjector; + private final Context mContext; private final Looper mLooper; + private final Handler mHandler; private final WifiNative mWifiNative; private final IBatteryStats mBatteryStats; - - private Queue<SoftApModeConfiguration> mApConfigQueue = new ConcurrentLinkedQueue<>(); + private final SelfRecovery mSelfRecovery; + private BaseWifiDiagnostics mWifiDiagnostics; // The base for wifi message types static final int BASE = Protocol.BASE_WIFI; @@ -91,27 +94,52 @@ public class WifiStateMachinePrime { // Client mode failed static final int CMD_CLIENT_MODE_FAILED = BASE + 304; + private StatusListener mWifiNativeStatusListener; + private WifiManager.SoftApCallback mSoftApCallback; + private ScanOnlyModeManager.Listener mScanOnlyCallback; + private ClientModeManager.Listener mClientModeCallback; /** * Called from WifiServiceImpl to register a callback for notifications from SoftApManager */ - public void registerSoftApCallback(WifiManager.SoftApCallback callback) { + public void registerSoftApCallback(@NonNull WifiManager.SoftApCallback callback) { mSoftApCallback = callback; } + /** + * Called from WifiController to register a callback for notifications from ScanOnlyModeManager + */ + public void registerScanOnlyCallback(@NonNull ScanOnlyModeManager.Listener callback) { + mScanOnlyCallback = callback; + } + + /** + * Called from WifiController to register a callback for notifications from ClientModeManager + */ + public void registerClientModeCallback(@NonNull ClientModeManager.Listener callback) { + mClientModeCallback = callback; + } + WifiStateMachinePrime(WifiInjector wifiInjector, + Context context, Looper looper, WifiNative wifiNative, DefaultModeManager defaultModeManager, IBatteryStats batteryStats) { mWifiInjector = wifiInjector; + mContext = context; mLooper = looper; + mHandler = new Handler(looper); mWifiNative = wifiNative; mActiveModeManagers = new ArraySet(); mDefaultModeManager = defaultModeManager; mBatteryStats = batteryStats; + mSelfRecovery = mWifiInjector.getSelfRecovery(); + mWifiDiagnostics = mWifiInjector.makeWifiDiagnostics(mWifiNative); mModeStateMachine = new ModeStateMachine(); + mWifiNativeStatusListener = new WifiNativeStatusListener(); + mWifiNative.registerStatusListener(mWifiNativeStatusListener); } /** @@ -143,19 +171,50 @@ public class WifiStateMachinePrime { * @param wifiConfig SoftApModeConfiguration for the hostapd softap */ public void enterSoftAPMode(@NonNull SoftApModeConfiguration wifiConfig) { - mApConfigQueue.offer(wifiConfig); - changeMode(ModeStateMachine.CMD_START_SOFT_AP_MODE); + mHandler.post(() -> { + startSoftAp(wifiConfig); + }); } /** - * Method to fully disable wifi. + * Method to stop soft ap for wifi hotspot. * - * This mode will completely shut down wifi and will not perform any network scans. + * This method will stop any active softAp mode managers, if there is one. + */ + public void stopSoftAPMode() { + mHandler.post(() -> { + for (ActiveModeManager manager : mActiveModeManagers) { + if (manager instanceof SoftApManager) { + Log.d(TAG, "Stopping SoftApModeManager"); + manager.stop(); + mActiveModeManagers.remove(manager); + } + } + updateBatteryStatsWifiState(false); + }); + } + + /** + * Method to disable wifi in sta/client mode scenarios. + * + * This mode will stop any client/scan modes and will not perform any network scans. */ public void disableWifi() { changeMode(ModeStateMachine.CMD_DISABLE_WIFI); } + /** + * Method to stop all active modes, for example, when toggling airplane mode. + */ + public void shutdownWifi() { + mHandler.post(() -> { + for (ActiveModeManager manager : mActiveModeManagers) { + manager.stop(); + } + updateBatteryStatsWifiState(false); + }); + } + protected String getCurrentMode() { return mModeStateMachine.getCurrentMode(); } @@ -164,27 +223,38 @@ public class WifiStateMachinePrime { mModeStateMachine.sendMessage(newMode); } + /** + * Helper class to wrap the ActiveModeManager callback objects. + */ + private class ModeCallback { + ActiveModeManager mActiveManager; + + void setActiveModeManager(ActiveModeManager manager) { + mActiveManager = manager; + } + + ActiveModeManager getActiveModeManager() { + return mActiveManager; + } + } + private class ModeStateMachine extends StateMachine { - // Commands for the state machine. + // Commands for the state machine - these will be removed, + // along with the StateMachine itself public static final int CMD_START_CLIENT_MODE = 0; public static final int CMD_START_SCAN_ONLY_MODE = 1; - public static final int CMD_START_SOFT_AP_MODE = 2; public static final int CMD_DISABLE_WIFI = 3; private final State mWifiDisabledState = new WifiDisabledState(); private final State mClientModeActiveState = new ClientModeActiveState(); private final State mScanOnlyModeActiveState = new ScanOnlyModeActiveState(); - private final State mSoftAPModeActiveState = new SoftAPModeActiveState(); ModeStateMachine() { super(TAG, mLooper); - // CHECKSTYLE:OFF IndentationCheck addState(mClientModeActiveState); addState(mScanOnlyModeActiveState); - addState(mSoftAPModeActiveState); addState(mWifiDisabledState); - // CHECKSTYLE:ON IndentationCheck Log.d(TAG, "Starting Wifi in WifiDisabledState"); setInitialState(mWifiDisabledState); @@ -205,10 +275,6 @@ public class WifiStateMachinePrime { Log.d(TAG, "Switching from " + getCurrentMode() + " to ScanOnlyMode"); mModeStateMachine.transitionTo(mScanOnlyModeActiveState); break; - case ModeStateMachine.CMD_START_SOFT_AP_MODE: - Log.d(TAG, "Switching from " + getCurrentMode() + " to SoftApMode"); - mModeStateMachine.transitionTo(mSoftAPModeActiveState); - break; case ModeStateMachine.CMD_DISABLE_WIFI: Log.d(TAG, "Switching from " + getCurrentMode() + " to WifiDisabled"); mModeStateMachine.transitionTo(mWifiDisabledState); @@ -219,11 +285,6 @@ public class WifiStateMachinePrime { return HANDLED; } - private void cleanup() { - // TODO: Remove this big hammer. We cannot support concurrent interfaces with this! - mWifiNative.teardownAllInterfaces(); - } - class ModeActiveState extends State { ActiveModeManager mManager; @Override @@ -249,8 +310,7 @@ public class WifiStateMachinePrime { @Override public void enter() { Log.d(TAG, "Entering WifiDisabledState"); - // make sure everything is torn down - remove when client mode is moved here - cleanup(); + mDefaultModeManager.sendScanAvailableBroadcast(mContext, false); } @Override @@ -294,23 +354,13 @@ public class WifiStateMachinePrime { Log.d(TAG, "Entering ClientModeActiveState"); mManager = mWifiInjector.makeClientModeManager(new ClientListener()); - // DO NOT CALL START YET - // mActiveModemanager.start(); + mManager.start(); mActiveModeManagers.add(mManager); updateBatteryStatsWifiState(true); } @Override - public void exit() { - Log.d(TAG, "Exiting ClientModeActiveState"); - - // OVERRIDE exit() SO WE DO NOT CALL STOP (but we do need to report wifi off) - - updateBatteryStatsWifiState(false); - } - - @Override public boolean processMessage(Message message) { if (checkForAndHandleModeChange(message)) { return HANDLED; @@ -323,11 +373,12 @@ public class WifiStateMachinePrime { private class ScanOnlyListener implements ScanOnlyModeManager.Listener { @Override public void onStateChanged(int state) { - Log.d(TAG, "State changed from scan only mode."); if (state == WifiManager.WIFI_STATE_UNKNOWN) { + Log.d(TAG, "ScanOnlyMode mode failed"); // error while setting up scan mode or an unexpected failure. mModeStateMachine.sendMessage(CMD_SCAN_ONLY_MODE_FAILED); } else if (state == WifiManager.WIFI_STATE_DISABLED) { + Log.d(TAG, "ScanOnlyMode stopped"); //scan only mode stopped mModeStateMachine.sendMessage(CMD_SCAN_ONLY_MODE_STOPPED); } else if (state == WifiManager.WIFI_STATE_ENABLED) { @@ -343,13 +394,12 @@ public class WifiStateMachinePrime { public void enter() { Log.d(TAG, "Entering ScanOnlyModeActiveState"); - // make sure everything is torn down - remove when client mode is moved here - cleanup(); - mManager = mWifiInjector.makeScanOnlyModeManager(new ScanOnlyListener()); mManager.start(); mActiveModeManagers.add(mManager); + updateBatteryStatsWifiState(true); + updateBatteryStatsScanModeActive(); } @Override @@ -364,10 +414,14 @@ public class WifiStateMachinePrime { break; case CMD_SCAN_ONLY_MODE_FAILED: Log.d(TAG, "ScanOnlyMode failed, return to WifiDisabledState."); + // notify WifiController that ScanOnlyMode failed + mScanOnlyCallback.onStateChanged(WifiManager.WIFI_STATE_UNKNOWN); mModeStateMachine.transitionTo(mWifiDisabledState); break; case CMD_SCAN_ONLY_MODE_STOPPED: Log.d(TAG, "ScanOnlyMode stopped, return to WifiDisabledState."); + // notify WifiController that ScanOnlyMode stopped + mScanOnlyCallback.onStateChanged(WifiManager.WIFI_STATE_DISABLED); mModeStateMachine.transitionTo(mWifiDisabledState); break; default: @@ -376,101 +430,100 @@ public class WifiStateMachinePrime { return HANDLED; } } + } // class ModeStateMachine - class SoftAPModeActiveState extends ModeActiveState { - private class SoftApCallbackImpl implements WifiManager.SoftApCallback { - @Override - public void onStateChanged(int state, int reason) { - if (state == WifiManager.WIFI_AP_STATE_DISABLED) { - mModeStateMachine.sendMessage(CMD_AP_STOPPED); - } else if (state == WifiManager.WIFI_AP_STATE_FAILED) { - mModeStateMachine.sendMessage(CMD_START_AP_FAILURE); - } - - if (mSoftApCallback != null) { - mSoftApCallback.onStateChanged(state, reason); - } else { - Log.wtf(TAG, "SoftApCallback is null. Dropping StateChanged event."); - } - } + private class SoftApCallbackImpl extends ModeCallback implements WifiManager.SoftApCallback { + @Override + public void onStateChanged(int state, int reason) { + if (state == WifiManager.WIFI_AP_STATE_DISABLED) { + mActiveModeManagers.remove(getActiveModeManager()); + updateBatteryStatsWifiState(false); + } else if (state == WifiManager.WIFI_AP_STATE_FAILED) { + mActiveModeManagers.remove(getActiveModeManager()); + updateBatteryStatsWifiState(false); + } - @Override - public void onNumClientsChanged(int numClients) { - if (mSoftApCallback != null) { - mSoftApCallback.onNumClientsChanged(numClients); - } else { - Log.d(TAG, "SoftApCallback is null. Dropping NumClientsChanged event."); - } - } + if (mSoftApCallback != null) { + mSoftApCallback.onStateChanged(state, reason); } + } - @Override - public void enter() { - Log.d(TAG, "Entering SoftApModeActiveState"); - - // make sure everything is torn down - remove when client mode is moved here - cleanup(); - - SoftApModeConfiguration softApModeConfig = mApConfigQueue.poll(); - WifiConfiguration config = softApModeConfig.getWifiConfiguration(); - // TODO (b/67601382): add checks for valid softap configs - if (config != null && config.SSID != null) { - Log.d(TAG, "Passing config to SoftApManager! " + config); - } else { - config = null; - } - mManager = mWifiInjector.makeSoftApManager( - new SoftApCallbackImpl(), softApModeConfig); - mManager.start(); - mActiveModeManagers.add(mManager); - updateBatteryStatsWifiState(true); + @Override + public void onNumClientsChanged(int numClients) { + if (mSoftApCallback != null) { + mSoftApCallback.onNumClientsChanged(numClients); + } else { + Log.d(TAG, "SoftApCallback is null. Dropping NumClientsChanged event."); } + } + } - @Override - public boolean processMessage(Message message) { - if (checkForAndHandleModeChange(message)) { - return HANDLED; - } + private void startSoftAp(SoftApModeConfiguration softapConfig) { + Log.d(TAG, "Starting SoftApModeManager"); - switch(message.what) { - case CMD_START_AP: - Log.d(TAG, "Received CMD_START_AP when active - invalid message - drop"); - break; - case CMD_STOP_AP: - mManager.stop(); - break; - case CMD_START_AP_FAILURE: - Log.d(TAG, "Failed to start SoftApMode. Return to WifiDisabledState."); - mModeStateMachine.transitionTo(mWifiDisabledState); - break; - case CMD_AP_STOPPED: - Log.d(TAG, "SoftApModeActiveState stopped. Return to WifiDisabledState."); - mModeStateMachine.transitionTo(mWifiDisabledState); - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } + WifiConfiguration config = softapConfig.getWifiConfiguration(); + // TODO (b/67601382): add checks for valid softap configs + if (config != null && config.SSID != null) { + Log.d(TAG, "Passing config to SoftApManager! " + config); + } else { + config = null; } - } // class ModeStateMachine + SoftApCallbackImpl callback = new SoftApCallbackImpl(); + ActiveModeManager manager = mWifiInjector.makeSoftApManager(callback, softapConfig); + callback.setActiveModeManager(manager); + manager.start(); + mActiveModeManagers.add(manager); + updateBatteryStatsWifiState(true); + } /** * Helper method to report wifi state as on/off (doesn't matter which mode). * - * @param enabled boolean indicating if wifi is on or off + * @param enabled boolean indicating that some mode has been turned on or off */ private void updateBatteryStatsWifiState(boolean enabled) { try { if (enabled) { - mBatteryStats.noteWifiOn(); + if (mActiveModeManagers.size() == 1) { + // only report wifi on if we haven't already + mBatteryStats.noteWifiOn(); + } } else { - mBatteryStats.noteWifiOff(); + if (mActiveModeManagers.size() == 0) { + // only report if we don't have any active modes + mBatteryStats.noteWifiOff(); + } } } catch (RemoteException e) { Log.e(TAG, "Failed to note battery stats in wifi"); } } + private void updateBatteryStatsScanModeActive() { + try { + mBatteryStats.noteWifiState(BatteryStats.WIFI_STATE_OFF_SCANNING, null); + } catch (RemoteException e) { + Log.e(TAG, "Failed to note battery stats in wifi"); + } + } + + // callback used to receive callbacks about underlying native failures + private final class WifiNativeStatusListener implements StatusListener { + + @Override + public void onStatusChanged(boolean isReady) { + if (!isReady) { + mHandler.post(() -> { + Log.e(TAG, "One of the native daemons died. Triggering recovery"); + mWifiDiagnostics.captureBugReportData( + WifiDiagnostics.REPORT_REASON_WIFINATIVE_FAILURE); + + // immediately trigger SelfRecovery if we receive a notice about an + // underlying daemon failure + mWifiInjector.getSelfRecovery().trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE); + }); + } + } + }; } diff --git a/tests/wifitests/src/com/android/server/wifi/ClientModeManagerTest.java b/tests/wifitests/src/com/android/server/wifi/ClientModeManagerTest.java index 942ff1c8b..25987d305 100644 --- a/tests/wifitests/src/com/android/server/wifi/ClientModeManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/ClientModeManagerTest.java @@ -64,9 +64,8 @@ public class ClientModeManagerTest { @Mock ClientModeManager.Listener mListener; @Mock WifiMonitor mWifiMonitor; @Mock ScanRequestProxy mScanRequestProxy; + @Mock WifiStateMachine mWifiStateMachine; - final ArgumentCaptor<WifiNative.StatusListener> mStatusListenerCaptor = - ArgumentCaptor.forClass(WifiNative.StatusListener.class); final ArgumentCaptor<WifiNative.InterfaceCallback> mInterfaceCallbackCaptor = ArgumentCaptor.forClass(WifiNative.InterfaceCallback.class); @@ -81,7 +80,7 @@ public class ClientModeManagerTest { private ClientModeManager createClientModeManager() { return new ClientModeManager(mContext, mLooper.getLooper(), mWifiNative, mListener, - mWifiMetrics, mScanRequestProxy); + mWifiMetrics, mScanRequestProxy, mWifiStateMachine); } private void startClientModeAndVerifyEnabled() throws Exception { @@ -92,7 +91,6 @@ public class ClientModeManagerTest { mClientModeManager.start(); mLooper.dispatchAll(); - verify(mWifiNative).registerStatusListener(mStatusListenerCaptor.capture()); verify(mWifiNative).setupInterfaceForClientMode( eq(false), mInterfaceCallbackCaptor.capture()); @@ -104,11 +102,12 @@ public class ClientModeManagerTest { eq(UserHandle.ALL)); List<Intent> intents = intentCaptor.getAllValues(); - assertEquals(3, intents.size()); + assertEquals(4, intents.size()); Log.d(TAG, "captured intents: " + intents); checkWifiStateChangedBroadcast(intents.get(0), WIFI_STATE_ENABLING, WIFI_STATE_DISABLED); - checkWifiScanStateChangedBroadcast(intents.get(1), WIFI_STATE_ENABLED); - checkWifiStateChangedBroadcast(intents.get(2), WIFI_STATE_ENABLED, WIFI_STATE_ENABLING); + checkWifiScanStateChangedBroadcast(intents.get(1), WIFI_STATE_DISABLED); + checkWifiScanStateChangedBroadcast(intents.get(2), WIFI_STATE_ENABLED); + checkWifiStateChangedBroadcast(intents.get(3), WIFI_STATE_ENABLED, WIFI_STATE_ENABLING); checkWifiStateChangeListenerUpdate(WIFI_STATE_ENABLED); verify(mScanRequestProxy, atLeastOnce()).enableScanningForHiddenNetworks(true); @@ -157,7 +156,7 @@ public class ClientModeManagerTest { List<Intent> intents = intentCaptor.getAllValues(); assertEquals(3, intents.size()); - checkWifiStateChangedBroadcast(intents.get(0), WIFI_STATE_DISABLING, WIFI_STATE_ENABLED); + checkWifiStateChangedBroadcast(intents.get(0), WIFI_STATE_DISABLING, WIFI_STATE_UNKNOWN); checkWifiScanStateChangedBroadcast(intents.get(1), WIFI_STATE_DISABLED); checkWifiStateChangedBroadcast(intents.get(2), WIFI_STATE_DISABLED, WIFI_STATE_DISABLING); checkWifiStateChangeListenerUpdate(WIFI_STATE_DISABLED); @@ -185,7 +184,10 @@ public class ClientModeManagerTest { ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); verify(mContext, atLeastOnce()).sendStickyBroadcastAsUser(intentCaptor.capture(), eq(UserHandle.ALL)); - checkWifiScanStateChangedBroadcast(intentCaptor.getValue(), WIFI_STATE_DISABLED); + List<Intent> intents = intentCaptor.getAllValues(); + assertEquals(2, intents.size()); + checkWifiStateChangedBroadcast(intents.get(0), WIFI_STATE_ENABLING, WIFI_STATE_DISABLED); + checkWifiStateChangedBroadcast(intents.get(1), WIFI_STATE_DISABLED, WIFI_STATE_UNKNOWN); checkWifiStateChangeListenerUpdate(WIFI_STATE_UNKNOWN); } @@ -206,7 +208,7 @@ public class ClientModeManagerTest { List<Intent> intents = intentCaptor.getAllValues(); assertEquals(2, intents.size()); checkWifiStateChangedBroadcast(intents.get(0), WIFI_STATE_ENABLING, WIFI_STATE_DISABLED); - checkWifiScanStateChangedBroadcast(intents.get(1), WIFI_STATE_DISABLED); + checkWifiStateChangedBroadcast(intents.get(1), WIFI_STATE_DISABLED, WIFI_STATE_UNKNOWN); checkWifiStateChangeListenerUpdate(WIFI_STATE_UNKNOWN); } @@ -261,45 +263,29 @@ public class ClientModeManagerTest { public void clientModeStartedStopsWhenInterfaceDown() throws Exception { startClientModeAndVerifyEnabled(); reset(mContext, mScanRequestProxy); + when(mWifiStateMachine.isConnectedMacRandomizationEnabled()).thenReturn(false); mInterfaceCallbackCaptor.getValue().onDown(TEST_INTERFACE_NAME); mLooper.dispatchAll(); + verify(mWifiStateMachine).failureDetected(eq(SelfRecovery.REASON_STA_IFACE_DOWN)); verifyNotificationsForFailure(); } /** - * Testing the handling of a wifinative failure status change notification. - */ - @Test - public void clientModeStartedStopsOnNativeFailure() throws Exception { - startClientModeAndVerifyEnabled(); - reset(mContext, mScanRequestProxy, mListener); - mStatusListenerCaptor.getValue().onStatusChanged(false); - mLooper.dispatchNext(); - - checkWifiStateChangeListenerUpdate(WIFI_STATE_UNKNOWN); - - mLooper.dispatchAll(); - - verifyNotificationsForFailure(); - } - - /** - * Testing that handling of a wifinative callback that is not a failuer does not stop client - * mode. + * Triggering interface down when ClientMode is active and Connected MacRandomization is enabled + * does not exit the active state. */ @Test - public void clientModeStartedAndStaysUpOnNativeNonFailureCallback() throws Exception { + public void clientModeStartedWithConnectedMacRandDoesNotStopWhenInterfaceDown() + throws Exception { startClientModeAndVerifyEnabled(); - reset(mContext, mScanRequestProxy, mListener); - mStatusListenerCaptor.getValue().onStatusChanged(true); + reset(mContext, mScanRequestProxy); + when(mWifiStateMachine.isConnectedMacRandomizationEnabled()).thenReturn(true); + mInterfaceCallbackCaptor.getValue().onDown(TEST_INTERFACE_NAME); mLooper.dispatchAll(); - - verify(mListener, never()).onStateChanged(eq(WIFI_STATE_UNKNOWN)); - verify(mListener, never()).onStateChanged(eq(WIFI_STATE_DISABLING)); - verify(mListener, never()).onStateChanged(eq(WIFI_STATE_DISABLED)); + verify(mWifiStateMachine, never()).failureDetected(eq(SelfRecovery.REASON_STA_IFACE_DOWN)); + verify(mContext, never()).sendStickyBroadcastAsUser(any(), any()); } - /** * Testing the handling of an interface destroyed notification. */ diff --git a/tests/wifitests/src/com/android/server/wifi/ScanOnlyModeManagerTest.java b/tests/wifitests/src/com/android/server/wifi/ScanOnlyModeManagerTest.java index 2556dfcf4..3d70fa902 100644 --- a/tests/wifitests/src/com/android/server/wifi/ScanOnlyModeManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/ScanOnlyModeManagerTest.java @@ -31,6 +31,7 @@ import static org.mockito.Mockito.eq; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @@ -48,6 +49,8 @@ import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.List; + /** * Unit tests for {@link ScanOnlyModeManager}. */ @@ -69,8 +72,6 @@ public class ScanOnlyModeManagerTest { @Mock ScanRequestProxy mScanRequestProxy; @Mock WakeupController mWakeupController; - final ArgumentCaptor<WifiNative.StatusListener> mStatusListenerCaptor = - ArgumentCaptor.forClass(WifiNative.StatusListener.class); final ArgumentCaptor<WifiNative.InterfaceCallback> mInterfaceCallbackCaptor = ArgumentCaptor.forClass(WifiNative.InterfaceCallback.class); @@ -94,7 +95,6 @@ public class ScanOnlyModeManagerTest { mScanOnlyModeManager.start(); mLooper.dispatchAll(); - verify(mWifiNative).registerStatusListener(mStatusListenerCaptor.capture()); verify(mWifiNative).setupInterfaceForClientMode(eq(true), mInterfaceCallbackCaptor.capture()); @@ -103,10 +103,12 @@ public class ScanOnlyModeManagerTest { mLooper.dispatchAll(); ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext).sendStickyBroadcastAsUser(intentCaptor.capture(), + verify(mContext, times(2)).sendStickyBroadcastAsUser(intentCaptor.capture(), eq(UserHandle.ALL)); + List<Intent> intents = intentCaptor.getAllValues(); - checkWifiScanStateChangedBroadcast(intentCaptor.getValue(), WIFI_STATE_ENABLED); + checkWifiScanStateChangedBroadcast(intents.get(0), WIFI_STATE_DISABLED); + checkWifiScanStateChangedBroadcast(intents.get(1), WIFI_STATE_ENABLED); checkWifiStateChangeListenerUpdate(WIFI_STATE_ENABLED); verify(mScanRequestProxy, atLeastOnce()).enableScanningForHiddenNetworks(false); } @@ -131,37 +133,6 @@ public class ScanOnlyModeManagerTest { } /** - * ScanMode idle state does not crash when a native status update comes before entering the - * active state. - */ - @Test - public void scanModeNativeUpdateBeforeStartDoesNotCrash() throws Exception { - verify(mWifiNative).registerStatusListener(mStatusListenerCaptor.capture()); - - mStatusListenerCaptor.getValue().onStatusChanged(false); - mLooper.dispatchAll(); - verifyNoMoreInteractions(mContext, mListener); - - verify(mScanRequestProxy, never()).clearScanResults(); - } - - /** - * ScanMode increments failure metrics when failing to setup client mode. - */ - @Test - public void detectAndReportErrorWhenSetupForClientWifiNativeFailure() throws Exception { - when(mWifiNative.setupInterfaceForClientMode(anyBoolean(), any())).thenReturn(null); - mScanOnlyModeManager.start(); - mLooper.dispatchAll(); - - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext, atLeastOnce()).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - checkWifiScanStateChangedBroadcast(intentCaptor.getValue(), WIFI_STATE_DISABLED); - checkWifiStateChangeListenerUpdate(WIFI_STATE_UNKNOWN); - } - - /** * ScanMode start does not indicate scanning is available when the interface name is empty. */ @Test @@ -171,10 +142,7 @@ public class ScanOnlyModeManagerTest { mScanOnlyModeManager.start(); mLooper.dispatchAll(); - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext, atLeastOnce()).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - checkWifiScanStateChangedBroadcast(intentCaptor.getValue(), WIFI_STATE_DISABLED); + verify(mContext, never()).sendStickyBroadcastAsUser(any(), eq(UserHandle.ALL)); checkWifiStateChangeListenerUpdate(WIFI_STATE_UNKNOWN); } @@ -201,10 +169,7 @@ public class ScanOnlyModeManagerTest { mLooper.dispatchAll(); // check when interface management it dynamic //verify(mWifiNative).teardownInterface(TEST_INTERFACE_NAME); - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext, atLeastOnce()).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - checkWifiScanStateChangedBroadcast(intentCaptor.getValue(), WIFI_STATE_DISABLED); + verify(mContext, never()).sendStickyBroadcastAsUser(any(), eq(UserHandle.ALL)); checkWifiStateChangeListenerUpdate(WIFI_STATE_DISABLED); verify(mScanRequestProxy).clearScanResults(); } @@ -218,12 +183,7 @@ public class ScanOnlyModeManagerTest { reset(mContext); mInterfaceCallbackCaptor.getValue().onDestroyed(TEST_INTERFACE_NAME); mLooper.dispatchAll(); - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - checkWifiScanStateChangedBroadcast(intentCaptor.getValue(), WIFI_STATE_DISABLED); - checkWifiStateChangeListenerUpdate(WIFI_STATE_DISABLED); - verify(mScanRequestProxy).clearScanResults(); + verify(mContext, never()).sendStickyBroadcastAsUser(any(), eq(UserHandle.ALL)); } /** @@ -253,10 +213,7 @@ public class ScanOnlyModeManagerTest { reset(mContext); mInterfaceCallbackCaptor.getValue().onDown(TEST_INTERFACE_NAME); mLooper.dispatchAll(); - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - checkWifiScanStateChangedBroadcast(intentCaptor.getValue(), WIFI_STATE_DISABLED); + verify(mContext, never()).sendStickyBroadcastAsUser(any(), eq(UserHandle.ALL)); checkWifiStateChangeListenerUpdate(WIFI_STATE_UNKNOWN); checkWifiStateChangeListenerUpdate(WIFI_STATE_DISABLED); verify(mScanRequestProxy).clearScanResults(); @@ -278,41 +235,6 @@ public class ScanOnlyModeManagerTest { verify(mScanRequestProxy, never()).clearScanResults(); } - - /** - * Testing the handling of a WifiNative failure status change notification. - */ - @Test - public void scanModeStartedStopsOnNativeFailure() throws Exception { - startScanOnlyModeAndVerifyEnabled(); - reset(mContext); - mStatusListenerCaptor.getValue().onStatusChanged(false); - mLooper.dispatchAll(); - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - - checkWifiScanStateChangedBroadcast(intentCaptor.getValue(), WIFI_STATE_DISABLED); - checkWifiStateChangeListenerUpdate(WIFI_STATE_UNKNOWN); - checkWifiStateChangeListenerUpdate(WIFI_STATE_DISABLED); - verify(mScanRequestProxy).clearScanResults(); - } - - /** - * WifiNative callback that does not indicate failure should not stop Scan mode. - */ - @Test - public void scanModeStartedDoesNotStopOnNativeSuccessUpdate() throws Exception { - startScanOnlyModeAndVerifyEnabled(); - reset(mContext, mListener); - mStatusListenerCaptor.getValue().onStatusChanged(true); - mLooper.dispatchAll(); - - verifyNoMoreInteractions(mContext, mListener); - - verify(mScanRequestProxy, never()).clearScanResults(); - } - /** * Entering StartedState starts the WakeupController. */ diff --git a/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java b/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java index e41af6867..bce5e8e94 100644 --- a/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java @@ -93,8 +93,6 @@ public class SoftApManagerTest { @Mock FrameworkFacade mFrameworkFacade; @Mock WifiApConfigStore mWifiApConfigStore; @Mock WifiMetrics mWifiMetrics; - final ArgumentCaptor<WifiNative.StatusListener> mWifiNativeStatusListenerCaptor = - ArgumentCaptor.forClass(WifiNative.StatusListener.class); final ArgumentCaptor<WifiNative.InterfaceCallback> mWifiNativeInterfaceCallbackCaptor = ArgumentCaptor.forClass(WifiNative.InterfaceCallback.class); final ArgumentCaptor<WifiNative.SoftApListener> mSoftApListenerCaptor = @@ -140,7 +138,6 @@ public class SoftApManagerTest { config, mWifiMetrics); mLooper.dispatchAll(); - verify(mWifiNative).registerStatusListener(mWifiNativeStatusListenerCaptor.capture()); return newSoftApManager; } @@ -473,71 +470,6 @@ public class SoftApManagerTest { } /** - * Verify that SoftAp mode shuts down on wifinative failure. - */ - @Test - public void handlesWifiNativeFailure() throws Exception { - SoftApModeConfiguration softApModeConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null); - startSoftApAndVerifyEnabled(softApModeConfig); - - // reset to clear verified Intents for ap state change updates - reset(mContext); - - mWifiNativeStatusListenerCaptor.getValue().onStatusChanged(false); - mLooper.dispatchAll(); - InOrder order = inOrder(mCallback); - order.verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, - WifiManager.SAP_START_FAILURE_GENERAL); - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext, times(3)).sendStickyBroadcastAsUser(intentCaptor.capture(), - eq(UserHandle.ALL)); - - List<Intent> capturedIntents = intentCaptor.getAllValues(); - checkApStateChangedBroadcast(capturedIntents.get(0), WIFI_AP_STATE_FAILED, - WIFI_AP_STATE_ENABLED, WifiManager.SAP_START_FAILURE_GENERAL, TEST_INTERFACE_NAME, - softApModeConfig.getTargetMode()); - checkApStateChangedBroadcast(capturedIntents.get(1), WIFI_AP_STATE_DISABLING, - WIFI_AP_STATE_FAILED, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME, - softApModeConfig.getTargetMode()); - checkApStateChangedBroadcast(capturedIntents.get(2), WIFI_AP_STATE_DISABLED, - WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR, TEST_INTERFACE_NAME, - softApModeConfig.getTargetMode()); - } - - /** - * Verify that SoftAp does not crash on wifinative failure before it is started. - */ - @Test - public void handlesWifiNativeFailureBeforeStart() throws Exception { - SoftApModeConfiguration softApModeConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null); - - mSoftApManager = createSoftApManager(softApModeConfig); - - mWifiNativeStatusListenerCaptor.getValue().onStatusChanged(false); - mLooper.dispatchAll(); - } - - /** - * Verify that SoftAp mode does not shut down on wifinative success update. - */ - @Test - public void handlesWifiNativeSuccess() throws Exception { - SoftApModeConfiguration softApModeConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null); - startSoftApAndVerifyEnabled(softApModeConfig); - - // reset to clear verified Intents for ap state change updates - reset(mContext, mCallback); - - mWifiNativeStatusListenerCaptor.getValue().onStatusChanged(true); - mLooper.dispatchAll(); - - verifyNoMoreInteractions(mContext, mCallback); - } - - /** * Verify that onDestroyed properly reports softap stop. */ @Test diff --git a/tests/wifitests/src/com/android/server/wifi/WifiControllerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiControllerTest.java index 279fb670b..0698eef48 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiControllerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiControllerTest.java @@ -369,8 +369,8 @@ public class WifiControllerTest { mWifiController.obtainMessage(CMD_AP_STOPPED).sendToTarget(); mLooper.dispatchAll(); - InOrder inOrder = inOrder(mWifiStateMachine); - inOrder.verify(mWifiStateMachine).setOperationalMode(WifiStateMachine.CONNECT_MODE); + InOrder inOrder = inOrder(mWifiStateMachinePrime); + inOrder.verify(mWifiStateMachinePrime).enterClientMode(); assertEquals("DeviceActiveState", getCurrentState().getName()); } @@ -395,8 +395,8 @@ public class WifiControllerTest { mWifiController.obtainMessage(CMD_AP_STOPPED).sendToTarget(); mLooper.dispatchAll(); - InOrder inOrder = inOrder(mWifiStateMachine); - inOrder.verify(mWifiStateMachine).setOperationalMode(WifiStateMachine.CONNECT_MODE); + InOrder inOrder = inOrder(mWifiStateMachinePrime); + inOrder.verify(mWifiStateMachinePrime).enterClientMode(); assertEquals("DeviceActiveState", getCurrentState().getName()); } @@ -424,10 +424,10 @@ public class WifiControllerTest { @Test public void testRecoveryDisabledTurnsWifiOff() throws Exception { enableWifi(); - reset(mWifiStateMachine); + reset(mWifiStateMachinePrime); mWifiController.sendMessage(CMD_RECOVERY_DISABLE_WIFI); mLooper.dispatchAll(); - verify(mWifiStateMachine).setOperationalMode(WifiStateMachine.DISABLED_MODE); + verify(mWifiStateMachinePrime).disableWifi(); } /** @@ -466,9 +466,11 @@ public class WifiControllerTest { reset(mWifiStateMachine); assertEquals("ApStaDisabledState", getCurrentState().getName()); + + reset(mWifiStateMachinePrime); mWifiController.sendMessage(CMD_RECOVERY_RESTART_WIFI); mLooper.dispatchAll(); - verifyZeroInteractions(mWifiStateMachine); + verify(mWifiStateMachinePrime).disableWifi(); } /** @@ -484,9 +486,12 @@ public class WifiControllerTest { public void testRestartWifiStackInStaDisabledWithScanState() throws Exception { reset(mWifiStateMachine); assertEquals("StaDisabledWithScanState", getCurrentState().getName()); + reset(mWifiStateMachinePrime); mWifiController.sendMessage(CMD_RECOVERY_RESTART_WIFI); mLooper.dispatchAll(); - verifyZeroInteractions(mWifiStateMachine); + InOrder inOrder = inOrder(mWifiStateMachinePrime); + verify(mWifiStateMachinePrime).disableWifi(); + verify(mWifiStateMachinePrime).enterScanOnlyMode(); } /** @@ -507,8 +512,8 @@ public class WifiControllerTest { assertEquals("DeviceActiveState", getCurrentState().getName()); mWifiController.sendMessage(CMD_RECOVERY_RESTART_WIFI); mLooper.dispatchAll(); - InOrder inOrder = inOrder(mWifiStateMachine); - inOrder.verify(mWifiStateMachine).setOperationalMode(WifiStateMachine.CONNECT_MODE); + InOrder inOrder = inOrder(mWifiStateMachinePrime); + inOrder.verify(mWifiStateMachinePrime).enterClientMode(); assertEquals("DeviceActiveState", getCurrentState().getName()); } @@ -550,10 +555,9 @@ public class WifiControllerTest { verify(mWifiStateMachinePrime).enterSoftAPMode(any()); assertEquals("ApEnabledState", getCurrentState().getName()); - reset(mWifiStateMachine); + reset(mWifiStateMachinePrime); mWifiController.sendMessage(CMD_RECOVERY_RESTART_WIFI); mLooper.dispatchAll(); - verifyZeroInteractions(mWifiStateMachine); - verify(mWifiStateMachinePrime, never()).disableWifi(); + verify(mWifiStateMachinePrime).disableWifi(); } } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiStateMachinePrimeTest.java b/tests/wifitests/src/com/android/server/wifi/WifiStateMachinePrimeTest.java index ae8d8cd95..e3775cd68 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiStateMachinePrimeTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiStateMachinePrimeTest.java @@ -19,8 +19,10 @@ package com.android.server.wifi; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.*; +import android.content.Context; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; +import android.os.BatteryStats; import android.os.test.TestLooper; import android.support.test.filters.SmallTest; import android.util.Log; @@ -30,6 +32,7 @@ import com.android.internal.app.IBatteryStats; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; @@ -44,23 +47,33 @@ public class WifiStateMachinePrimeTest { private static final String CLIENT_MODE_STATE_STRING = "ClientModeActiveState"; private static final String SCAN_ONLY_MODE_STATE_STRING = "ScanOnlyModeActiveState"; - private static final String SOFT_AP_MODE_STATE_STRING = "SoftAPModeActiveState"; private static final String WIFI_DISABLED_STATE_STRING = "WifiDisabledState"; private static final String WIFI_IFACE_NAME = "mockWlan"; @Mock WifiInjector mWifiInjector; + @Mock Context mContext; @Mock WifiNative mWifiNative; @Mock WifiApConfigStore mWifiApConfigStore; TestLooper mLooper; + @Mock ClientModeManager mClientModeManager; @Mock ScanOnlyModeManager mScanOnlyModeManager; @Mock SoftApManager mSoftApManager; @Mock DefaultModeManager mDefaultModeManager; @Mock IBatteryStats mBatteryStats; + @Mock SelfRecovery mSelfRecovery; + @Mock BaseWifiDiagnostics mWifiDiagnostics; + ClientModeManager.Listener mClientListener; ScanOnlyModeManager.Listener mScanOnlyListener; + ScanOnlyModeCallback mScanOnlyCallback = new ScanOnlyModeCallback(); + ClientModeCallback mClientModeCallback = new ClientModeCallback(); WifiManager.SoftApCallback mSoftApManagerCallback; @Mock WifiManager.SoftApCallback mSoftApStateMachineCallback; + WifiNative.StatusListener mWifiNativeStatusListener; WifiStateMachinePrime mWifiStateMachinePrime; + final ArgumentCaptor<WifiNative.StatusListener> mStatusListenerCaptor = + ArgumentCaptor.forClass(WifiNative.StatusListener.class); + /** * Set up the test environment. */ @@ -71,14 +84,23 @@ public class WifiStateMachinePrimeTest { MockitoAnnotations.initMocks(this); mLooper = new TestLooper(); + when(mWifiInjector.getSelfRecovery()).thenReturn(mSelfRecovery); + when(mWifiInjector.makeWifiDiagnostics(eq(mWifiNative))).thenReturn(mWifiDiagnostics); + mWifiStateMachinePrime = createWifiStateMachinePrime(); mLooper.dispatchAll(); + verify(mWifiNative).registerStatusListener(mStatusListenerCaptor.capture()); + mWifiNativeStatusListener = mStatusListenerCaptor.getValue(); + mWifiStateMachinePrime.registerSoftApCallback(mSoftApStateMachineCallback); + mWifiStateMachinePrime.registerScanOnlyCallback(mScanOnlyCallback); + mWifiStateMachinePrime.registerClientModeCallback(mClientModeCallback); } private WifiStateMachinePrime createWifiStateMachinePrime() { return new WifiStateMachinePrime(mWifiInjector, + mContext, mLooper.getLooper(), mWifiNative, mDefaultModeManager, @@ -93,12 +115,54 @@ public class WifiStateMachinePrimeTest { mWifiStateMachinePrime = null; } + private class ClientModeCallback implements ClientModeManager.Listener { + public int currentState = WifiManager.WIFI_STATE_UNKNOWN; + + @Override + public void onStateChanged(int state) { + currentState = state; + } + } + + private class ScanOnlyModeCallback implements ScanOnlyModeManager.Listener { + public int currentState = WifiManager.WIFI_STATE_UNKNOWN; + + @Override + public void onStateChanged(int state) { + currentState = state; + } + } + private void enterSoftApActiveMode() throws Exception { enterSoftApActiveMode( new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null)); } /** + * Helper method to enter the ClientModeActiveState for WifiStateMachinePrime. + */ + private void enterClientModeActiveState() throws Exception { + String fromState = mWifiStateMachinePrime.getCurrentMode(); + doAnswer( + new Answer<Object>() { + public ClientModeManager answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + mClientListener = (ClientModeManager.Listener) args[0]; + return mClientModeManager; + } + }).when(mWifiInjector).makeClientModeManager( + any(ClientModeManager.Listener.class)); + mWifiStateMachinePrime.enterClientMode(); + mLooper.dispatchAll(); + mClientListener.onStateChanged(WifiManager.WIFI_STATE_ENABLED); + mLooper.dispatchAll(); + + assertEquals(CLIENT_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode()); + verify(mClientModeManager).start(); + verify(mBatteryStats).noteWifiOn(); + } + + /** * Helper method to enter the ScanOnlyModeActiveState for WifiStateMachinePrime. */ private void enterScanOnlyModeActiveState() throws Exception { @@ -114,9 +178,13 @@ public class WifiStateMachinePrimeTest { any(ScanOnlyModeManager.Listener.class)); mWifiStateMachinePrime.enterScanOnlyMode(); mLooper.dispatchAll(); + mScanOnlyListener.onStateChanged(WifiManager.WIFI_STATE_ENABLED); + mLooper.dispatchAll(); + assertEquals(SCAN_ONLY_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode()); verify(mScanOnlyModeManager).start(); verify(mBatteryStats).noteWifiOn(); + verify(mBatteryStats).noteWifiState(eq(BatteryStats.WIFI_STATE_OFF_SCANNING), eq(null)); } /** @@ -138,15 +206,10 @@ public class WifiStateMachinePrimeTest { any()); mWifiStateMachinePrime.enterSoftAPMode(softApConfig); mLooper.dispatchAll(); - assertEquals(SOFT_AP_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode()); verify(mSoftApManager).start(); - verify(mBatteryStats).noteWifiOn(); - } - - private void verifyCleanupCalled() { - // for now, this is a single call, but make a helper to avoid adding any additional cleanup - // checks - verify(mWifiNative).teardownAllInterfaces(); + if (fromState.equals(WIFI_DISABLED_STATE_STRING)) { + verify(mBatteryStats).noteWifiOn(); + } } /** @@ -154,7 +217,6 @@ public class WifiStateMachinePrimeTest { */ @Test public void testWifiDisabledAtStartup() throws Exception { - verify(mWifiNative).teardownAllInterfaces(); assertEquals(WIFI_DISABLED_STATE_STRING, mWifiStateMachinePrime.getCurrentMode()); } @@ -165,7 +227,6 @@ public class WifiStateMachinePrimeTest { @Test public void testEnterScanOnlyModeFromDisabled() throws Exception { enterScanOnlyModeActiveState(); - verify(mWifiNative, times(2)).teardownAllInterfaces(); } /** @@ -175,22 +236,18 @@ public class WifiStateMachinePrimeTest { @Test public void testEnterSoftApModeFromDisabled() throws Exception { enterSoftApActiveMode(); - verify(mWifiNative, times(2)).teardownAllInterfaces(); } /** * Test that WifiStateMachinePrime properly enters the SoftApModeActiveState from another state. - * Expectations: When going from one state to another, cleanup will be called */ @Test public void testEnterSoftApModeFromDifferentState() throws Exception { - mWifiStateMachinePrime.enterClientMode(); + enterClientModeActiveState(); mLooper.dispatchAll(); assertEquals(CLIENT_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode()); reset(mBatteryStats); enterSoftApActiveMode(); - // still only two times since we do not control the interface yet in client mode - verify(mWifiNative, times(2)).teardownAllInterfaces(); } /** @@ -205,41 +262,22 @@ public class WifiStateMachinePrimeTest { verify(mScanOnlyModeManager).stop(); verify(mBatteryStats).noteWifiOff(); assertEquals(WIFI_DISABLED_STATE_STRING, mWifiStateMachinePrime.getCurrentMode()); - verify(mWifiNative, times(3)).teardownAllInterfaces(); } /** - * Test that we can disable wifi fully from the SoftApModeActiveState. + * Test that we can disable wifi from the SoftApModeActiveState and not impact softap. */ @Test - public void testDisableWifiFromSoftApModeActiveState() throws Exception { + public void testDisableWifiFromSoftApModeActiveStateDoesNotStopSoftAp() throws Exception { enterSoftApActiveMode(); + reset(mDefaultModeManager); mWifiStateMachinePrime.disableWifi(); mLooper.dispatchAll(); - verify(mSoftApManager).stop(); - verify(mBatteryStats).noteWifiOff(); + verify(mSoftApManager, never()).stop(); + verify(mBatteryStats, never()).noteWifiOff(); + verify(mDefaultModeManager).sendScanAvailableBroadcast(eq(mContext), eq(false)); assertEquals(WIFI_DISABLED_STATE_STRING, mWifiStateMachinePrime.getCurrentMode()); - verify(mWifiNative, times(3)).teardownAllInterfaces(); - } - - /** - * Test that we can disable wifi fully from the SoftApModeState. - */ - @Test - public void testDisableWifiFromSoftApModeState() throws Exception { - enterSoftApActiveMode(); - // now inject failure through the SoftApManager.Listener - mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, 0); - mLooper.dispatchAll(); - assertEquals(WIFI_DISABLED_STATE_STRING, mWifiStateMachinePrime.getCurrentMode()); - - mWifiStateMachinePrime.disableWifi(); - mLooper.dispatchAll(); - verify(mBatteryStats).noteWifiOff(); - - assertEquals(WIFI_DISABLED_STATE_STRING, mWifiStateMachinePrime.getCurrentMode()); - verify(mWifiNative, times(4)).teardownAllInterfaces(); } /** @@ -250,27 +288,28 @@ public class WifiStateMachinePrimeTest { public void testSwitchModeWhenScanOnlyModeActiveState() throws Exception { enterScanOnlyModeActiveState(); - mWifiStateMachinePrime.enterClientMode(); + reset(mBatteryStats); + enterClientModeActiveState(); mLooper.dispatchAll(); verify(mScanOnlyModeManager).stop(); assertEquals(CLIENT_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode()); - verify(mWifiNative, times(2)).teardownAllInterfaces(); } /** * Test that we can switch from SoftApActiveMode to another mode. - * Expectation: When switching out of SoftApModeActiveState we stop the SoftApManager and tear - * down existing interfaces. + * Expectation: When switching out of SoftApModeActiveState we do not impact softap operation */ @Test public void testSwitchModeWhenSoftApActiveMode() throws Exception { enterSoftApActiveMode(); - mWifiStateMachinePrime.enterClientMode(); + reset(mWifiNative); + + enterClientModeActiveState(); mLooper.dispatchAll(); - verify(mSoftApManager).stop(); + verify(mSoftApManager, never()).stop(); assertEquals(CLIENT_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode()); - verify(mWifiNative, times(2)).teardownAllInterfaces(); + verify(mWifiNative, never()).teardownAllInterfaces(); } /** @@ -290,7 +329,6 @@ public class WifiStateMachinePrimeTest { reset(mSoftApManager, mBatteryStats); enterSoftApActiveMode(); - verify(mWifiNative, times(4)).teardownAllInterfaces(); } /** @@ -306,8 +344,8 @@ public class WifiStateMachinePrimeTest { mLooper.dispatchAll(); assertEquals(WIFI_DISABLED_STATE_STRING, mWifiStateMachinePrime.getCurrentMode()); verify(mScanOnlyModeManager).stop(); - verify(mWifiNative, times(3)).teardownAllInterfaces(); verify(mBatteryStats).noteWifiOff(); + assertEquals(WifiManager.WIFI_STATE_UNKNOWN, mScanOnlyCallback.currentState); } /** @@ -321,9 +359,6 @@ public class WifiStateMachinePrimeTest { // now inject failure through the SoftApManager.Listener mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, 0); mLooper.dispatchAll(); - assertEquals(WIFI_DISABLED_STATE_STRING, mWifiStateMachinePrime.getCurrentMode()); - verify(mSoftApManager).stop(); - verify(mWifiNative, times(3)).teardownAllInterfaces(); verify(mBatteryStats).noteWifiOff(); } @@ -340,7 +375,6 @@ public class WifiStateMachinePrimeTest { mLooper.dispatchAll(); assertEquals(WIFI_DISABLED_STATE_STRING, mWifiStateMachinePrime.getCurrentMode()); verify(mScanOnlyModeManager).stop(); - verify(mWifiNative, times(3)).teardownAllInterfaces(); verify(mBatteryStats).noteWifiOff(); } @@ -352,13 +386,12 @@ public class WifiStateMachinePrimeTest { @Test public void testSoftApDisabledWhenActive() throws Exception { enterSoftApActiveMode(); + reset(mWifiNative); // now inject failure through the SoftApManager.Listener mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, 0); mLooper.dispatchAll(); - assertEquals(WIFI_DISABLED_STATE_STRING, mWifiStateMachinePrime.getCurrentMode()); - verify(mSoftApManager).stop(); - verify(mWifiNative, times(3)).teardownAllInterfaces(); verify(mBatteryStats).noteWifiOff(); + verifyNoMoreInteractions(mWifiNative); } /** @@ -435,7 +468,6 @@ public class WifiStateMachinePrimeTest { mLooper.dispatchAll(); assertEquals(SCAN_ONLY_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode()); verify(mScanOnlyModeManager, never()).stop(); - verify(mWifiNative, times(2)).teardownAllInterfaces(); } /** @@ -450,7 +482,6 @@ public class WifiStateMachinePrimeTest { mLooper.dispatchAll(); assertEquals(SCAN_ONLY_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode()); verify(mScanOnlyModeManager, never()).stop(); - verify(mWifiNative, times(2)).teardownAllInterfaces(); } /** @@ -501,42 +532,53 @@ public class WifiStateMachinePrimeTest { when(mWifiInjector.makeSoftApManager(any(WifiManager.SoftApCallback.class), eq(softApConfig1))) .thenReturn(mSoftApManager); + // make a second softap manager + SoftApManager softapManager = mock(SoftApManager.class); when(mWifiInjector.makeSoftApManager(any(WifiManager.SoftApCallback.class), - eq(softApConfig2))) - .thenReturn(mSoftApManager); - + eq(softApConfig2))) + .thenReturn(softapManager); mWifiStateMachinePrime.enterSoftAPMode(softApConfig1); mWifiStateMachinePrime.enterSoftAPMode(softApConfig2); mLooper.dispatchAll(); - assertEquals(SOFT_AP_MODE_STATE_STRING, mWifiStateMachinePrime.getCurrentMode()); - verify(mBatteryStats).noteWifiOff(); + verify(mSoftApManager).start(); + verify(softapManager).start(); + verify(mBatteryStats).noteWifiOn(); } /** - * Test that when softap manager reports that softap has stopped, we return to the - * WifiDisabledState. + * Test that we safely disable wifi if it is already disabled. + * Expectations: We should not interact with WifiNative since we should have already cleaned up + * everything. */ @Test - public void testSoftApStopReturnsToWifiDisabled() throws Exception { - enterSoftApActiveMode(); + public void disableWifiWhenAlreadyOff() throws Exception { + mWifiStateMachinePrime.disableWifi(); + // since we start up in disabled, this should not re-enter the disabled state + verify(mDefaultModeManager).sendScanAvailableBroadcast(eq(mContext), eq(false)); + } - mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0); + /** + * Trigger recovery and a bug report if we see a native failure. + */ + @Test + public void handleWifiNativeFailure() throws Exception { + mWifiNativeStatusListener.onStatusChanged(false); mLooper.dispatchAll(); - assertEquals(WIFI_DISABLED_STATE_STRING, mWifiStateMachinePrime.getCurrentMode()); - verify(mWifiNative, times(3)).teardownAllInterfaces(); - verify(mBatteryStats).noteWifiOff(); + verify(mWifiDiagnostics).captureBugReportData( + WifiDiagnostics.REPORT_REASON_WIFINATIVE_FAILURE); + verify(mSelfRecovery).trigger(eq(SelfRecovery.REASON_WIFINATIVE_FAILURE)); } /** - * Test that we safely disable wifi if it is already disabled. - * Expectations: We should not interact with WifiNative since we should have already cleaned up - * everything. + * Verify an onStatusChanged callback with "true" does not trigger recovery. */ @Test - public void disableWifiWhenAlreadyOff() throws Exception { - mWifiStateMachinePrime.disableWifi(); - // since we start up in disabled, this should not re-enter the disabled state - verify(mWifiNative).teardownAllInterfaces(); + public void handleWifiNativeStatusReady() throws Exception { + mWifiNativeStatusListener.onStatusChanged(true); + mLooper.dispatchAll(); + verify(mWifiDiagnostics, never()).captureBugReportData( + WifiDiagnostics.REPORT_REASON_WIFINATIVE_FAILURE); + verify(mSelfRecovery, never()).trigger(eq(SelfRecovery.REASON_WIFINATIVE_FAILURE)); } } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java index c90bde3bb..c70a77102 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java @@ -336,9 +336,6 @@ public class WifiStateMachineTest { OsuProvider mOsuProvider; ContentObserver mContentObserver; - final ArgumentCaptor<WifiManager.SoftApCallback> mSoftApCallbackCaptor = - ArgumentCaptor.forClass(WifiManager.SoftApCallback.class); - @Mock WifiScanner mWifiScanner; @Mock SupplicantStateTracker mSupplicantStateTracker; @Mock WifiMetrics mWifiMetrics; @@ -353,7 +350,6 @@ public class WifiStateMachineTest { @Mock WifiConfigManager mWifiConfigManager; @Mock WifiNative mWifiNative; @Mock WifiConnectivityManager mWifiConnectivityManager; - @Mock SoftApManager mSoftApManager; @Mock WifiStateTracker mWifiStateTracker; @Mock PasspointManager mPasspointManager; @Mock SelfRecovery mSelfRecovery; @@ -371,8 +367,6 @@ public class WifiStateMachineTest { @Mock WakeupController mWakeupController; @Mock ScanRequestProxy mScanRequestProxy; - final ArgumentCaptor<WifiNative.StatusListener> mStatusListenerCaptor = - ArgumentCaptor.forClass(WifiNative.StatusListener.class); final ArgumentCaptor<WifiNative.InterfaceCallback> mInterfaceCallbackCaptor = ArgumentCaptor.forClass(WifiNative.InterfaceCallback.class); @@ -568,61 +562,16 @@ public class WifiStateMachineTest { @Test public void loadComponentsInStaMode() throws Exception { startSupplicantAndDispatchMessages(); - - verify(mContext).sendStickyBroadcastAsUser( - (Intent) argThat(new WifiEnablingStateIntentMatcher()), eq(UserHandle.ALL)); - assertEquals("DisconnectedState", getCurrentState().getName()); } - private void loadComponentsInApMode(int mode) throws Exception { - SoftApModeConfiguration config = new SoftApModeConfiguration(mode, new WifiConfiguration()); - mWsm.setHostApRunning(config, true); - mLooper.dispatchAll(); - - assertEquals("SoftApState", getCurrentState().getName()); - - verify(mWifiNative, never()).setupInterfaceForSoftApMode(any()); - verify(mSoftApManager, never()).start(); - } - - @Test - public void loadComponentsInApModeForTethering() throws Exception { - loadComponentsInApMode(WifiManager.IFACE_IP_MODE_TETHERED); - } - - @Test - public void loadComponentsInApModeForLOHS() throws Exception { - loadComponentsInApMode(WifiManager.IFACE_IP_MODE_LOCAL_ONLY); - } - - @Test - public void shouldRequireSupplicantStartupToLeaveInitialState() throws Exception { - when(mWifiNative.setupInterfaceForClientMode(anyBoolean(), any())).thenReturn(null); - mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); - mLooper.dispatchAll(); - assertEquals("DefaultState", getCurrentState().getName()); - // we should be sending a wifi enabling update - verify(mContext).sendStickyBroadcastAsUser( - (Intent) argThat(new WifiEnablingStateIntentMatcher()), any()); - } - - @Test - public void loadComponentsFailure() throws Exception { - when(mWifiNative.setupInterfaceForClientMode(anyBoolean(), any())).thenReturn(null); - - mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); - mLooper.dispatchAll(); - assertEquals("DefaultState", getCurrentState().getName()); - } - @Test public void checkInitialStateStickyWhenDisabledMode() throws Exception { mLooper.dispatchAll(); assertEquals("DefaultState", getCurrentState().getName()); assertEquals(WifiStateMachine.DISABLED_MODE, mWsm.getOperationalModeForTest()); - mWsm.setOperationalMode(WifiStateMachine.DISABLED_MODE); + mWsm.setOperationalMode(WifiStateMachine.DISABLED_MODE, null); mLooper.dispatchAll(); assertEquals(WifiStateMachine.DISABLED_MODE, mWsm.getOperationalModeForTest()); assertEquals("DefaultState", getCurrentState().getName()); @@ -636,7 +585,7 @@ public class WifiStateMachineTest { assertEquals(WifiStateMachine.DISABLED_MODE, mWsm.getOperationalModeForTest()); // But if someone tells us to enter connect mode, we start up supplicant - mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); + mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE, WIFI_IFACE_NAME); mLooper.dispatchAll(); assertEquals("DisconnectedState", getCurrentState().getName()); } @@ -651,43 +600,22 @@ public class WifiStateMachineTest { assertEquals("DefaultState", getCurrentState().getName()); assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState()); - mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE); - mLooper.dispatchAll(); - assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest()); - assertEquals("ScanModeState", getCurrentState().getName()); - assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState()); - verify(mContext, never()).sendStickyBroadcastAsUser( - (Intent) argThat(new WifiEnablingStateIntentMatcher()), any()); - // switch to connect mode and verify wifi is reported as enabled startSupplicantAndDispatchMessages(); assertEquals("DisconnectedState", getCurrentState().getName()); assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); assertEquals(WifiManager.WIFI_STATE_ENABLED, mWsm.syncGetWifiState()); - verify(mContext).sendStickyBroadcastAsUser( - (Intent) argThat(new WifiEnablingStateIntentMatcher()), eq(UserHandle.ALL)); // reset the expectations on mContext since we did get an expected broadcast, but we should // not on the next transition reset(mContext); - // now go back to scan mode with "wifi disabled" to verify the reported wifi state. - mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE); + // now disable wifi and verify the reported wifi state + mWsm.setOperationalMode(WifiStateMachine.DISABLED_MODE, null); mLooper.dispatchAll(); - assertEquals(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE, - mWsm.getOperationalModeForTest()); - assertEquals("ScanModeState", getCurrentState().getName()); - assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState()); - verify(mContext, never()).sendStickyBroadcastAsUser( - (Intent) argThat(new WifiEnablingStateIntentMatcher()), any()); - - // now go to AP mode - SoftApModeConfiguration config = new SoftApModeConfiguration( - WifiManager.IFACE_IP_MODE_TETHERED, new WifiConfiguration()); - mWsm.setHostApRunning(config, true); - mLooper.dispatchAll(); - assertEquals("SoftApState", getCurrentState().getName()); + assertEquals(WifiStateMachine.DISABLED_MODE, mWsm.getOperationalModeForTest()); + assertEquals("DefaultState", getCurrentState().getName()); assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState()); verify(mContext, never()).sendStickyBroadcastAsUser( (Intent) argThat(new WifiEnablingStateIntentMatcher()), any()); @@ -856,14 +784,9 @@ public class WifiStateMachineTest { * Helper method to move through startup states. */ private void startSupplicantAndDispatchMessages() throws Exception { - mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); + mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE, WIFI_IFACE_NAME); mLooper.dispatchAll(); - // this will be removed when interface management is dynamic - verify(mWifiNative, atLeastOnce()).teardownAllInterfaces(); - - verify(mWifiNative, atLeastOnce()) - .setupInterfaceForClientMode(eq(false), mInterfaceCallbackCaptor.capture()); verify(mWifiLastResortWatchdog, atLeastOnce()).clearAllFailureCounts(); assertEquals("DisconnectedState", getCurrentState().getName()); @@ -1045,7 +968,7 @@ public class WifiStateMachineTest { public void verifyWifiStateTrackerUpdatedWhenDisabled() throws Exception { connect(); - mWsm.setOperationalMode(WifiStateMachine.DISABLED_MODE); + mWsm.setOperationalMode(WifiStateMachine.DISABLED_MODE, null); mLooper.dispatchAll(); verify(mWifiStateTracker).updateState(eq(WifiStateTracker.DISCONNECTED)); } @@ -1712,8 +1635,7 @@ public class WifiStateMachineTest { * client mode. */ @Test - public void syncStartSubscriptionProvisioningInAPMode() throws Exception { - loadComponentsInApMode(WifiManager.IFACE_IP_MODE_LOCAL_ONLY); + public void syncStartSubscriptionProvisioningNoOpWifiDisabled() throws Exception { mLooper.startAutoDispatch(); assertEquals(false, mWsm.syncStartSubscriptionProvisioning( OTHER_USER_UID, mOsuProvider, mProvisioningCallback, mWsmAsyncChannel)); @@ -1783,119 +1705,6 @@ public class WifiStateMachineTest { } /** - * Trigger recovery and a bug report of we see a native failure when Client mode is active. - */ - @Test - public void handleWifiNativeFailureWhenClientModeActive() throws Exception { - // Trigger initialize to capture the death handler registration. - loadComponentsInStaMode(); - - verify(mWifiNative).registerStatusListener(mStatusListenerCaptor.capture()); - - // Now trigger the death notification. - mStatusListenerCaptor.getValue().onStatusChanged(false); - mLooper.dispatchAll(); - verify(mSelfRecovery).trigger(eq(SelfRecovery.REASON_WIFINATIVE_FAILURE)); - verify(mWifiDiagnostics).captureBugReportData( - WifiDiagnostics.REPORT_REASON_WIFINATIVE_FAILURE); - } - - /** - * WifiNative failures when in a state other than client mode should just be dropped. - */ - @Test - public void handleWifiNativeFailureInDefaultDoesNotRestartClientMode() throws Exception { - // Trigger initialize to capture the death handler registration. - loadComponentsInStaMode(); - verify(mWifiNative).registerStatusListener(mStatusListenerCaptor.capture()); - - mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE); - mLooper.dispatchAll(); - - // Now trigger the death notification. - mStatusListenerCaptor.getValue().onStatusChanged(false); - mLooper.dispatchAll(); - verify(mSelfRecovery, never()).trigger(anyInt()); - verify(mWifiDiagnostics, never()).captureBugReportData(anyInt()); - } - - /** - * Test verifying that interface onDown callback triggers SelfRecovery when Supplicant has - * already reported the driver is not active. - */ - @Test - public void testInterfaceOnDownInClientModeTriggersSelfRecovery() throws Exception { - // Trigger initialize to capture the death handler registration. - loadComponentsInStaMode(); - - // make sure we mark the iface up - mInterfaceCallbackCaptor.getValue().onUp(WIFI_IFACE_NAME); - - // make sure supplicant has been reported as inactive - when(mWifiNative.isInterfaceUp(eq(WIFI_IFACE_NAME))).thenReturn(true); - mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, WifiSsid.createFromAsciiEncoded(""), null, - SupplicantState.INTERFACE_DISABLED)); - mLooper.dispatchAll(); - - // trigger onDown for the client interface - mInterfaceCallbackCaptor.getValue().onDown(WIFI_IFACE_NAME); - mLooper.dispatchAll(); - - // WSM should trigger self recovery, but not disconnect until externally triggered - verify(mSelfRecovery).trigger(eq(SelfRecovery.REASON_STA_IFACE_DOWN)); - } - - /** - * Test verifying that interface onDown callback does not trigger SelfRecovery when - * Supplicant reports that the driver is active. - */ - @Test - public void testInterfaceOnDownInClientModeDoesNotTriggerSelfRecoveryIfDriverActive() - throws Exception { - // Trigger initialize to capture the death handler registration. - loadComponentsInStaMode(); - - // make sure we mark the iface up - mInterfaceCallbackCaptor.getValue().onUp(WIFI_IFACE_NAME); - mLooper.dispatchAll(); - - // make sure supplicant has been reported as active - mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, WifiSsid.createFromAsciiEncoded(""), null, - SupplicantState.DISCONNECTED)); - mLooper.dispatchAll(); - - // trigger onDown for the client interface - mInterfaceCallbackCaptor.getValue().onDown(WIFI_IFACE_NAME); - mLooper.dispatchAll(); - - // WSM should trigger self recovery, but not disconnect until externally triggered - verify(mSelfRecovery, never()).trigger(eq(SelfRecovery.REASON_STA_IFACE_DOWN)); - } - - /** - * Test verifying that Supplicant update for inactive driver does not trigger SelfRecovery - * when the interface is reported down. - */ - @Test - public void testSupplicantUpdateDriverInactiveInClientModeTriggersSelfRecovery() - throws Exception { - // Trigger initialize to capture the death handler registration. - loadComponentsInStaMode(); - - when(mWifiNative.isInterfaceUp(eq(WIFI_IFACE_NAME))).thenReturn(false); - - mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, - new StateChangeResult(0, WifiSsid.createFromAsciiEncoded(""), null, - SupplicantState.INTERFACE_DISABLED)); - mLooper.dispatchAll(); - - // WSM should trigger self recovery, but not disconnect until externally triggered - verify(mSelfRecovery, never()).trigger(eq(SelfRecovery.REASON_STA_IFACE_DOWN)); - } - - /** * Test verifying that interface Supplicant update for inactive driver does not trigger * SelfRecovery when WifiNative reports the interface is up. */ @@ -1918,47 +1727,6 @@ public class WifiStateMachineTest { } /** - * Test verifying that interface onDown callback does not trigger SelfRecovery when - * MacRandomization is enabled. - */ - @Test - public void testInterfaceOnDownInClientModeDoesNotTriggerSelfRecoveryWithMacRand() - throws Exception { - when(mFrameworkFacade.getIntegerSetting(mContext, - Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, 0)).thenReturn(1); - mContentObserver.onChange(false); - - // Trigger initialize to capture the death handler registration. - loadComponentsInStaMode(); - - // make sure we mark the iface up - mInterfaceCallbackCaptor.getValue().onUp(WIFI_IFACE_NAME); - mLooper.dispatchAll(); - - // trigger onDown for the client interface - mInterfaceCallbackCaptor.getValue().onDown(WIFI_IFACE_NAME); - mLooper.dispatchAll(); - - // WSM should trigger self recovery, but not disconnect until externally triggered - verify(mSelfRecovery, never()).trigger(eq(SelfRecovery.REASON_STA_IFACE_DOWN)); - } - - /** - * Test verifying that interface onDestroyed callbacks are not currently hooked up. - */ - @Test - public void testInterfaceOnDestroyedDoesNotTriggerClientModeShutdown() throws Exception { - connect(); - - // trigger onDestroyed for the client interface - mInterfaceCallbackCaptor.getValue().onDown(WIFI_IFACE_NAME); - mLooper.dispatchAll(); - - // since this is not handled yet, should not trigger a disconnect - assertEquals("ConnectedState", getCurrentState().getName()); - } - - /** * Verifies that WifiInfo is updated upon SUPPLICANT_STATE_CHANGE_EVENT. */ @Test @@ -2052,13 +1820,13 @@ public class WifiStateMachineTest { assertEquals(sBSSID, wifiInfo.getBSSID()); assertEquals(SupplicantState.COMPLETED, wifiInfo.getSupplicantState()); - // Set WSM to SCAN_ONLY_MODE, verify state and wifi disabled in ConnectivityManager, and + // Set WSM to DISABLED_MODE, verify state and wifi disabled in ConnectivityManager, and // WifiInfo is reset() and state set to DISCONNECTED - mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE); + mWsm.setOperationalMode(WifiStateMachine.DISABLED_MODE, null); mLooper.dispatchAll(); - assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest()); - assertEquals("ScanModeState", getCurrentState().getName()); + assertEquals(WifiStateMachine.DISABLED_MODE, mWsm.getOperationalModeForTest()); + assertEquals("DefaultState", getCurrentState().getName()); assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState()); inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(false)); assertNull(wifiInfo.getBSSID()); |