summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/java/com/android/server/wifi/ClientModeManager.java20
-rw-r--r--service/java/com/android/server/wifi/ScanOnlyModeManager.java18
-rw-r--r--service/java/com/android/server/wifi/SoftApManager.java1
-rw-r--r--service/java/com/android/server/wifi/WifiStateMachinePrime.java61
-rw-r--r--tests/wifitests/src/com/android/server/wifi/ClientModeManagerTest.java12
-rw-r--r--tests/wifitests/src/com/android/server/wifi/ScanOnlyModeManagerTest.java8
6 files changed, 98 insertions, 22 deletions
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
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,7 +382,8 @@ 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);
@@ -382,6 +391,12 @@ public class WifiStateMachinePrime {
}
@Override
+ public void exit() {
+ super.exit();
+ mListener = null;
+ }
+
+ @Override
public boolean processMessage(Message message) {
if (checkForAndHandleModeChange(message)) {
return HANDLED;
@@ -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);
@@ -444,6 +475,12 @@ public class WifiStateMachinePrime {
}
@Override
+ public void exit() {
+ super.exit();
+ mListener = null;
+ }
+
+ @Override
public boolean processMessage(Message message) {
if (checkForAndHandleModeChange(message)) {
return HANDLED;
@@ -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);
diff --git a/tests/wifitests/src/com/android/server/wifi/ClientModeManagerTest.java b/tests/wifitests/src/com/android/server/wifi/ClientModeManagerTest.java
index b04caf54d..ca6ddfd61 100644
--- a/tests/wifitests/src/com/android/server/wifi/ClientModeManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/ClientModeManagerTest.java
@@ -158,7 +158,7 @@ public class ClientModeManagerTest {
assertEquals(2, intents.size());
checkWifiStateChangedBroadcast(intents.get(0), WIFI_STATE_DISABLING, WIFI_STATE_UNKNOWN);
checkWifiStateChangedBroadcast(intents.get(1), WIFI_STATE_DISABLED, WIFI_STATE_DISABLING);
- checkWifiStateChangeListenerUpdate(WIFI_STATE_DISABLED);
+ checkWifiStateChangeListenerUpdate(WIFI_STATE_UNKNOWN);
}
/**
@@ -227,11 +227,14 @@ public class ClientModeManagerTest {
@Test
public void clientModeStopCleansUpState() throws Exception {
startClientModeAndVerifyEnabled();
- reset(mContext);
+ reset(mContext, mListener);
mClientModeManager.stop();
mLooper.dispatchAll();
verifyNotificationsForCleanShutdown(WIFI_STATE_ENABLED);
+
+ // on an explicit stop, we should not trigger the callback
+ verifyNoMoreInteractions(mListener);
}
/**
@@ -309,11 +312,6 @@ public class ClientModeManagerTest {
mClientModeManager.stop();
mLooper.dispatchAll();
- verify(mListener).onStateChanged(WIFI_STATE_DISABLING);
- verify(mListener).onStateChanged(WIFI_STATE_DISABLED);
-
- reset(mListener);
-
// now trigger interface destroyed and make sure callback doesn't get called
mInterfaceCallbackCaptor.getValue().onDestroyed(TEST_INTERFACE_NAME);
mLooper.dispatchAll();
diff --git a/tests/wifitests/src/com/android/server/wifi/ScanOnlyModeManagerTest.java b/tests/wifitests/src/com/android/server/wifi/ScanOnlyModeManagerTest.java
index 3ad57f535..41362eec6 100644
--- a/tests/wifitests/src/com/android/server/wifi/ScanOnlyModeManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/ScanOnlyModeManagerTest.java
@@ -170,7 +170,7 @@ public class ScanOnlyModeManagerTest {
mLooper.dispatchAll();
verify(mWifiNative).teardownInterface(TEST_INTERFACE_NAME);
verify(mContext, never()).sendStickyBroadcastAsUser(any(), eq(UserHandle.ALL));
- checkWifiStateChangeListenerUpdate(WIFI_STATE_DISABLED);
+ verifyNoMoreInteractions(mListener);
}
/**
@@ -214,7 +214,6 @@ public class ScanOnlyModeManagerTest {
mLooper.dispatchAll();
verify(mContext, never()).sendStickyBroadcastAsUser(any(), eq(UserHandle.ALL));
checkWifiStateChangeListenerUpdate(WIFI_STATE_UNKNOWN);
- checkWifiStateChangeListenerUpdate(WIFI_STATE_DISABLED);
verify(mScanRequestProxy).clearScanResults();
}
@@ -246,10 +245,6 @@ public class ScanOnlyModeManagerTest {
mScanOnlyModeManager.stop();
mLooper.dispatchAll();
- verify(mListener).onStateChanged(WIFI_STATE_DISABLED);
-
- reset(mListener);
-
// now trigger interface destroyed and make sure callback doesn't get called
mInterfaceCallbackCaptor.getValue().onDestroyed(TEST_INTERFACE_NAME);
mLooper.dispatchAll();
@@ -282,6 +277,5 @@ public class ScanOnlyModeManagerTest {
inOrder.verify(mWakeupController).start();
inOrder.verify(mWakeupController).stop();
inOrder.verify(mWifiNative).teardownInterface(eq(TEST_INTERFACE_NAME));
- inOrder.verify(mListener).onStateChanged(eq(WIFI_STATE_DISABLED));
}
}