summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Su <dysu@google.com>2020-06-30 17:52:18 -0700
committerDavid Su <dysu@google.com>2020-07-01 15:31:44 -0700
commit9e80c7bb6a53d2a4ba1df348ea36b43707167840 (patch)
treed17f0cb6a4575c25c815967de18dde6d4ae83bf3
parentdb04b29f0f6a96b19850fc17e23818855f800d61 (diff)
Fix quickly toggling airplane mode on then off could leave Wifi disabled
If Wifi is enabled, and we toggle airplane mode on then off quickly, afterwards wifi could be stuck in the disabled state, even though the expected behavior is that Wifi return to enabled state. This is due to a race between CMD_AIRPLANE_TOGGLED and ClientListener.onStopped(). To fix this, defer CMD_AIRPLANE_TOGGLED if we are still processing a previous CMD_AIRPLANE_TOGGLED. Bug: 160105640 Test: atest ActiveModeWardenTest Test: manually toggle airplane mode on then off quickly while wifi is enabled Change-Id: I8f40dbba0be170a5eca38f0221b4b722cb4b96a4
-rw-r--r--service/java/com/android/server/wifi/ActiveModeWarden.java12
-rw-r--r--tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java37
2 files changed, 47 insertions, 2 deletions
diff --git a/service/java/com/android/server/wifi/ActiveModeWarden.java b/service/java/com/android/server/wifi/ActiveModeWarden.java
index e0a0a3d29..cf54e328b 100644
--- a/service/java/com/android/server/wifi/ActiveModeWarden.java
+++ b/service/java/com/android/server/wifi/ActiveModeWarden.java
@@ -850,6 +850,9 @@ public class ActiveModeWarden {
}
class EnabledState extends BaseState {
+
+ private boolean mIsDisablingDueToAirplaneMode;
+
@Override
public void enter() {
log("EnabledState.enter()");
@@ -857,6 +860,7 @@ public class ActiveModeWarden {
if (!hasAnyModeManager()) {
Log.e(TAG, "Entered EnabledState, but no active mode managers");
}
+ mIsDisablingDueToAirplaneMode = false;
}
@Override
@@ -894,11 +898,15 @@ public class ActiveModeWarden {
case CMD_AIRPLANE_TOGGLED:
// airplane mode toggled on is handled in the default state
if (mSettingsStore.isAirplaneModeOn()) {
+ mIsDisablingDueToAirplaneMode = true;
return NOT_HANDLED;
} else {
- if (hasAnyModeManagerStopping()) {
- // previous airplane mode toggle on is being processed, defer the
+ if (mIsDisablingDueToAirplaneMode) {
+ // Previous airplane mode toggle on is being processed, defer the
// message toggle off until previous processing is completed.
+ // Once previous airplane mode toggle is complete, we should
+ // transition to DisabledState. There, we will process the deferred
+ // airplane mode toggle message to disable airplane mode.
deferMessage(msg);
} else {
// when airplane mode is toggled off, but wifi is on, we can keep it
diff --git a/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java b/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java
index ceaf76dc8..8294bdb04 100644
--- a/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java
@@ -2240,6 +2240,43 @@ public class ActiveModeWardenTest extends WifiBaseTest {
}
@Test
+ public void airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithOneModeManager2()
+ throws Exception {
+ enterClientModeActiveState();
+ assertInEnabledState();
+
+ // APM toggle on
+ assertWifiShutDown(() -> {
+ when(mSettingsStore.isAirplaneModeOn()).thenReturn(true);
+ mActiveModeWarden.airplaneModeToggled();
+ mLooper.dispatchAll();
+ });
+
+
+ // APM toggle off before the stop is complete.
+ assertInEnabledState();
+ when(mClientModeManager.isStopping()).thenReturn(true);
+ when(mSettingsStore.isAirplaneModeOn()).thenReturn(false);
+ mActiveModeWarden.airplaneModeToggled();
+ // This test is identical to
+ // airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithOneModeManager, except the
+ // dispatchAll() here is removed. There could be a race between airplaneModeToggled and
+ // mClientListener.onStopped(). See b/160105640#comment5.
+
+ mClientListener.onStopped();
+ mLooper.dispatchAll();
+
+ verify(mClientModeManager, times(2)).start();
+ verify(mClientModeManager, times(2)).setRole(ROLE_CLIENT_PRIMARY);
+
+ mClientListener.onStarted();
+ mLooper.dispatchAll();
+
+ // We should be back to enabled state.
+ assertInEnabledState();
+ }
+
+ @Test
public void airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithTwoModeManager()
throws Exception {
enterClientModeActiveState();