From f7814ce9117a6622dd1662cbe9396b1684447004 Mon Sep 17 00:00:00 2001 From: Rebecca Silberstein Date: Wed, 16 May 2018 08:58:42 -0700 Subject: ModeManagers: do not report disabled when stopped When Client and Scan modes are explicitly stopped, there is no need to report state changes to WSMP. Bug: 79532177 Test: toggle wifi quickly Test: WifiCrashTest Test: atest android.net.wifi.cts Change-Id: I133f486159f3c475084619cddfd6da482a17c00a --- .../com/android/server/wifi/ClientModeManager.java | 20 +++++++++++++++++++- .../com/android/server/wifi/ScanOnlyModeManager.java | 18 ++++++++++++++++++ .../java/com/android/server/wifi/SoftApManager.java | 1 + 3 files changed, 38 insertions(+), 1 deletion(-) (limited to 'service') diff --git a/service/java/com/android/server/wifi/ClientModeManager.java b/service/java/com/android/server/wifi/ClientModeManager.java index 922d21958..b5300d24c 100644 --- a/service/java/com/android/server/wifi/ClientModeManager.java +++ b/service/java/com/android/server/wifi/ClientModeManager.java @@ -53,6 +53,8 @@ public class ClientModeManager implements ActiveModeManager { private String mClientInterfaceName; private boolean mIfaceIsUp = false; + private boolean mExpectedStop = false; + ClientModeManager(Context context, @NonNull Looper looper, WifiNative wifiNative, Listener listener, WifiMetrics wifiMetrics, ScanRequestProxy scanRequestProxy, WifiStateMachine wifiStateMachine) { @@ -77,6 +79,7 @@ public class ClientModeManager implements ActiveModeManager { */ public void stop() { Log.d(TAG, " currentstate: " + getCurrentStateName()); + mExpectedStop = true; if (mClientInterfaceName != null) { if (mIfaceIsUp) { updateWifiState(WifiManager.WIFI_STATE_DISABLING, @@ -127,7 +130,19 @@ public class ClientModeManager implements ActiveModeManager { * @param currentState current wifi state */ private void updateWifiState(int newState, int currentState) { - mListener.onStateChanged(newState); + if (!mExpectedStop) { + mListener.onStateChanged(newState); + } else { + Log.d(TAG, "expected stop, not triggering callbacks: newState = " + newState); + } + + // Once we report the mode has stopped/failed any other stop signals are redundant + // note: this can happen in failure modes where we get multiple callbacks as underlying + // components/interface stops or the underlying interface is destroyed in cleanup + if (newState == WifiManager.WIFI_STATE_UNKNOWN + || newState == WifiManager.WIFI_STATE_DISABLED) { + mExpectedStop = true; + } if (newState == WifiManager.WIFI_STATE_UNKNOWN) { // do not need to broadcast failure to system @@ -314,6 +329,9 @@ public class ClientModeManager implements ActiveModeManager { updateWifiState(WifiManager.WIFI_STATE_DISABLED, WifiManager.WIFI_STATE_DISABLING); + + // once we leave started, nothing else to do... stop the state machine + mStateMachine.quitNow(); } } diff --git a/service/java/com/android/server/wifi/ScanOnlyModeManager.java b/service/java/com/android/server/wifi/ScanOnlyModeManager.java index a98c6ba66..346d2ca67 100644 --- a/service/java/com/android/server/wifi/ScanOnlyModeManager.java +++ b/service/java/com/android/server/wifi/ScanOnlyModeManager.java @@ -52,6 +52,8 @@ public class ScanOnlyModeManager implements ActiveModeManager { private String mClientInterfaceName; private boolean mIfaceIsUp = false; + private boolean mExpectedStop = false; + ScanOnlyModeManager(@NonNull Context context, @NonNull Looper looper, @NonNull WifiNative wifiNative, @NonNull Listener listener, @NonNull WifiMetrics wifiMetrics, @@ -78,6 +80,7 @@ public class ScanOnlyModeManager implements ActiveModeManager { */ public void stop() { Log.d(TAG, " currentstate: " + getCurrentStateName()); + mExpectedStop = true; mStateMachine.quitNow(); } @@ -118,6 +121,18 @@ public class ScanOnlyModeManager implements ActiveModeManager { * @param state new Wifi state */ private void updateWifiState(int state) { + if (mExpectedStop) { + Log.d(TAG, "expected stop, not triggering callbacks: state = " + state); + return; + } + + // Once we report the mode has stopped/failed any other stop signals are redundant + // note: this can happen in failure modes where we get multiple callbacks as underlying + // components/interface stops or the underlying interface is destroyed in cleanup + if (state == WifiManager.WIFI_STATE_UNKNOWN || state == WifiManager.WIFI_STATE_DISABLED) { + mExpectedStop = true; + } + mListener.onStateChanged(state); } @@ -266,6 +281,9 @@ public class ScanOnlyModeManager implements ActiveModeManager { mClientInterfaceName = null; } updateWifiState(WifiManager.WIFI_STATE_DISABLED); + + // once we leave started, nothing else to do... stop the state machine + mStateMachine.quitNow(); } } } diff --git a/service/java/com/android/server/wifi/SoftApManager.java b/service/java/com/android/server/wifi/SoftApManager.java index 2faf11577..6c52918a5 100644 --- a/service/java/com/android/server/wifi/SoftApManager.java +++ b/service/java/com/android/server/wifi/SoftApManager.java @@ -514,6 +514,7 @@ public class SoftApManager implements ActiveModeManager { WifiManager.WIFI_AP_STATE_DISABLING, 0); mApInterfaceName = null; mIfaceIsUp = false; + mStateMachine.quitNow(); } @Override -- cgit v1.2.3 From 6ecc9ff41652d29b6f5a8e8b1771dc673b0bf29a Mon Sep 17 00:00:00 2001 From: Rebecca Silberstein Date: Fri, 18 May 2018 11:06:47 -0700 Subject: WifiStateMachinePrime: discard messages from old managers Discard updates from previous mode managers in Client and ScanOnly modes. Bug: 79532177 Test: toggle wifi quickly Test: WifiCrashTest Test: frameworks/opt/net/wifi/tests/wifitests/runtests.sh Change-Id: I790baf5eb522b8aab37834920233d9e751ca0045 --- .../android/server/wifi/WifiStateMachinePrime.java | 61 +++++++++++++++++++--- 1 file changed, 54 insertions(+), 7 deletions(-) (limited to 'service') diff --git a/service/java/com/android/server/wifi/WifiStateMachinePrime.java b/service/java/com/android/server/wifi/WifiStateMachinePrime.java index fcb199eee..85ea001fb 100644 --- a/service/java/com/android/server/wifi/WifiStateMachinePrime.java +++ b/service/java/com/android/server/wifi/WifiStateMachinePrime.java @@ -351,16 +351,24 @@ public class WifiStateMachinePrime { } class ClientModeActiveState extends ModeActiveState { + ClientListener mListener; private class ClientListener implements ClientModeManager.Listener { @Override public void onStateChanged(int state) { - Log.d(TAG, "State changed from client mode."); + // make sure this listener is still active + if (this != mListener) { + Log.d(TAG, "Client mode state change from previous manager"); + return; + } + + Log.d(TAG, "State changed from client mode. state = " + state); + if (state == WifiManager.WIFI_STATE_UNKNOWN) { // error while setting up client mode or an unexpected failure. - mModeStateMachine.sendMessage(CMD_CLIENT_MODE_FAILED); + mModeStateMachine.sendMessage(CMD_CLIENT_MODE_FAILED, this); } else if (state == WifiManager.WIFI_STATE_DISABLED) { // client mode stopped - mModeStateMachine.sendMessage(CMD_CLIENT_MODE_STOPPED); + mModeStateMachine.sendMessage(CMD_CLIENT_MODE_STOPPED, this); } else if (state == WifiManager.WIFI_STATE_ENABLED) { // client mode is ready to go Log.d(TAG, "client mode active"); @@ -374,13 +382,20 @@ public class WifiStateMachinePrime { public void enter() { Log.d(TAG, "Entering ClientModeActiveState"); - mManager = mWifiInjector.makeClientModeManager(new ClientListener()); + mListener = new ClientListener(); + mManager = mWifiInjector.makeClientModeManager(mListener); mManager.start(); mActiveModeManagers.add(mManager); updateBatteryStatsWifiState(true); } + @Override + public void exit() { + super.exit(); + mListener = null; + } + @Override public boolean processMessage(Message message) { if (checkForAndHandleModeChange(message)) { @@ -392,12 +407,21 @@ public class WifiStateMachinePrime { Log.d(TAG, "Received CMD_START_CLIENT_MODE when active - drop"); break; case CMD_CLIENT_MODE_FAILED: + if (mListener != message.obj) { + Log.d(TAG, "Client mode state change from previous manager"); + return HANDLED; + } Log.d(TAG, "ClientMode failed, return to WifiDisabledState."); // notify WifiController that ClientMode failed mClientModeCallback.onStateChanged(WifiManager.WIFI_STATE_UNKNOWN); mModeStateMachine.transitionTo(mWifiDisabledState); break; case CMD_CLIENT_MODE_STOPPED: + if (mListener != message.obj) { + Log.d(TAG, "Client mode state change from previous manager"); + return HANDLED; + } + Log.d(TAG, "ClientMode stopped, return to WifiDisabledState."); // notify WifiController that ClientMode stopped mClientModeCallback.onStateChanged(WifiManager.WIFI_STATE_DISABLED); @@ -411,17 +435,23 @@ public class WifiStateMachinePrime { } class ScanOnlyModeActiveState extends ModeActiveState { + ScanOnlyListener mListener; private class ScanOnlyListener implements ScanOnlyModeManager.Listener { @Override public void onStateChanged(int state) { + if (this != mListener) { + Log.d(TAG, "ScanOnly mode state change from previous manager"); + return; + } + 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); + mModeStateMachine.sendMessage(CMD_SCAN_ONLY_MODE_FAILED, this); } else if (state == WifiManager.WIFI_STATE_DISABLED) { Log.d(TAG, "ScanOnlyMode stopped"); //scan only mode stopped - mModeStateMachine.sendMessage(CMD_SCAN_ONLY_MODE_STOPPED); + mModeStateMachine.sendMessage(CMD_SCAN_ONLY_MODE_STOPPED, this); } else if (state == WifiManager.WIFI_STATE_ENABLED) { // scan mode is ready to go Log.d(TAG, "scan mode active"); @@ -435,7 +465,8 @@ public class WifiStateMachinePrime { public void enter() { Log.d(TAG, "Entering ScanOnlyModeActiveState"); - mManager = mWifiInjector.makeScanOnlyModeManager(new ScanOnlyListener()); + mListener = new ScanOnlyListener(); + mManager = mWifiInjector.makeScanOnlyModeManager(mListener); mManager.start(); mActiveModeManagers.add(mManager); @@ -443,6 +474,12 @@ public class WifiStateMachinePrime { updateBatteryStatsScanModeActive(); } + @Override + public void exit() { + super.exit(); + mListener = null; + } + @Override public boolean processMessage(Message message) { if (checkForAndHandleModeChange(message)) { @@ -454,12 +491,22 @@ public class WifiStateMachinePrime { Log.d(TAG, "Received CMD_START_SCAN_ONLY_MODE when active - drop"); break; case CMD_SCAN_ONLY_MODE_FAILED: + if (mListener != message.obj) { + Log.d(TAG, "ScanOnly mode state change from previous manager"); + return HANDLED; + } + 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: + if (mListener != message.obj) { + Log.d(TAG, "ScanOnly mode state change from previous manager"); + return HANDLED; + } + Log.d(TAG, "ScanOnlyMode stopped, return to WifiDisabledState."); // notify WifiController that ScanOnlyMode stopped mScanOnlyCallback.onStateChanged(WifiManager.WIFI_STATE_DISABLED); -- cgit v1.2.3