diff options
| author | 2013-09-24 17:38:09 -0700 | |
|---|---|---|
| committer | 2013-09-24 17:38:09 -0700 | |
| commit | 6029611e3ab3e1adf3f463ed90abbdcc8b0bd7f1 (patch) | |
| tree | 972ae3929adddd5bd66f009625c4c2b8a4ce0f40 | |
| parent | e14d0c211fb669f88c284af85c942135e834e498 (diff) | |
Fix an incorrectly created race accessing Wifi Supplicant
ScanModeState is trying to undo whatever it did in its enter(), in its
exit() function. But doing that is incorrect because it is possible to
transition to multiple states that require different conditions.
In this bug, the state machine transitioned from ScanModeState to
WaitForP2pDisabled state; in response to Stop Supplicant command. Well,
when we are trying to stop supplicant, there is clearly no need to
enable P2P or load all networks. But since this code exists in exit(),
it is executed nonetheless, causing race conditions accessing the
wpa_supplicant (WifiStateMachine is trying to shut it down, but
P2pStateMachine is trying to bring up the p2p interfaces).
We solve that problem by moving this code to the place where we transition
to DisconnectedState - since that's the state that needs this as a
precondition.
Bug: 10761752
Change-Id: Iaf0ffd8056de8533b5d2bfdf8c440fbb7e406dac
| -rw-r--r-- | wifi/java/android/net/wifi/WifiStateMachine.java | 54 |
1 files changed, 35 insertions, 19 deletions
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 94d9288a165e..76bd636e127f 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -427,8 +427,12 @@ public class WifiStateMachine extends StateMachine { /* An IP address was removed from our interface */ static final int CMD_IP_ADDRESS_REMOVED = BASE + 141; + /* Wifi state machine modes of operation */ + /* CONNECT_MODE - connect to any 'known' AP when it becomes available */ public static final int CONNECT_MODE = 1; + /* SCAN_ONLY_MODE - don't connect to any APs; scan, but only while apps hold lock */ public static final int SCAN_ONLY_MODE = 2; + /* SCAN_ONLY_WITH_WIFI_OFF - scan, but don't connect to any APs */ public static final int SCAN_ONLY_WITH_WIFI_OFF_MODE = 3; private static final int SUCCESS = 1; @@ -2942,6 +2946,8 @@ public class WifiStateMachine extends StateMachine { if (mOperationalMode != CONNECT_MODE) { mWifiNative.disconnect(); + mWifiConfigStore.disableAllNetworks(); + setWifiState(WIFI_STATE_DISABLED); transitionTo(mScanModeState); } else { /* Driver stop may have disabled networks, enable right after start */ @@ -2969,7 +2975,15 @@ public class WifiStateMachine extends StateMachine { } mWifiNative.setPowerSave(true); - if (mP2pSupported) mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P); + if (mP2pSupported) { + if (mOperationalMode == CONNECT_MODE) { + mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P); + } else { + // P2P statemachine starts in disabled state, and is not enabled until + // CMD_ENABLE_P2P is sent from here; so, nothing needs to be done to + // keep it disabled. + } + } final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); @@ -3240,31 +3254,26 @@ public class WifiStateMachine extends StateMachine { private int mLastOperationMode; @Override public void enter() { - mWifiConfigStore.disableAllNetworks(); mLastOperationMode = mOperationalMode; - if (mLastOperationMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { - mWifiP2pChannel.sendMessage(CMD_DISABLE_P2P_REQ); - setWifiState(WIFI_STATE_DISABLED); - } - } - @Override - public void exit() { - if (mLastOperationMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { - setWifiState(WIFI_STATE_ENABLED); - // Load and re-enable networks when going back to enabled state - // This is essential for networks to show up after restore - mWifiConfigStore.loadAndEnableAllNetworks(); - mWifiP2pChannel.sendMessage(CMD_ENABLE_P2P); - } else { - mWifiConfigStore.enableAllNetworks(); - } - mWifiNative.reconnect(); } @Override public boolean processMessage(Message message) { switch(message.what) { case CMD_SET_OPERATIONAL_MODE: if (message.arg1 == CONNECT_MODE) { + + if (mLastOperationMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { + setWifiState(WIFI_STATE_ENABLED); + // Load and re-enable networks when going back to enabled state + // This is essential for networks to show up after restore + mWifiConfigStore.loadAndEnableAllNetworks(); + mWifiP2pChannel.sendMessage(CMD_ENABLE_P2P); + } else { + mWifiConfigStore.enableAllNetworks(); + } + + mWifiNative.reconnect(); + mOperationalMode = CONNECT_MODE; transitionTo(mDisconnectedState); } else { @@ -3890,6 +3899,13 @@ public class WifiStateMachine extends StateMachine { case CMD_SET_OPERATIONAL_MODE: if (message.arg1 != CONNECT_MODE) { mOperationalMode = message.arg1; + + mWifiConfigStore.disableAllNetworks(); + if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { + mWifiP2pChannel.sendMessage(CMD_DISABLE_P2P_REQ); + setWifiState(WIFI_STATE_DISABLED); + } + transitionTo(mScanModeState); } break; |