summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vinit Deshapnde <vinitd@google.com> 2013-09-24 17:38:09 -0700
committer Vinit Deshapnde <vinitd@google.com> 2013-09-24 17:38:09 -0700
commit6029611e3ab3e1adf3f463ed90abbdcc8b0bd7f1 (patch)
tree972ae3929adddd5bd66f009625c4c2b8a4ce0f40
parente14d0c211fb669f88c284af85c942135e834e498 (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.java54
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;