diff options
author | Irfan Sheriff <isheriff@google.com> | 2010-12-14 11:29:23 -0800 |
---|---|---|
committer | Irfan Sheriff <isheriff@google.com> | 2010-12-15 08:37:05 -0800 |
commit | 96071a7031bac06e3f249610b010ad5651efe8ae (patch) | |
tree | 95774671c3f950bed16e922682866d30f4aba986 /wifi | |
parent | 2bc248b698b17fd333beae828039a8bff7604a9f (diff) | |
download | frameworks_base-96071a7031bac06e3f249610b010ad5651efe8ae.zip frameworks_base-96071a7031bac06e3f249610b010ad5651efe8ae.tar.gz frameworks_base-96071a7031bac06e3f249610b010ad5651efe8ae.tar.bz2 |
Handle supplicant stop correctly
- Use a clean terminate for a regular stop and on failure kill supplicant. This prevents
WifiMonitor from getting hung permanently on a socket in case of a kill
- When WifiMonitor exits, kill supplicant and cleanup sockets
Change-Id: I87c32e03d945433f33eed8c326d7f0368925bf55
Diffstat (limited to 'wifi')
-rw-r--r-- | wifi/java/android/net/wifi/WifiNative.java | 4 | ||||
-rw-r--r-- | wifi/java/android/net/wifi/WifiStateMachine.java | 117 |
2 files changed, 97 insertions, 24 deletions
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java index 0310420..a64b814 100644 --- a/wifi/java/android/net/wifi/WifiNative.java +++ b/wifi/java/android/net/wifi/WifiNative.java @@ -48,7 +48,7 @@ public class WifiNative { public native static boolean startSupplicant(); - public native static boolean stopSupplicant(); + public native static boolean killSupplicant(); public native static boolean connectToSupplicant(); @@ -80,6 +80,8 @@ public class WifiNative { public native static boolean disconnectCommand(); + public native static boolean terminateCommand(); + public native static String statusCommand(); public native static int getRssiCommand(); diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 5474b3f..dc5e0d8 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -127,6 +127,18 @@ public class WifiStateMachine extends HierarchicalStateMachine { private static final int POLL_RSSI_INTERVAL_MSECS = 3000; /** + * Delay between supplicant restarts upon failure to establish connection + */ + private static final int SUPPLICANT_RESTART_INTERVAL_MSECS = 5000; + + /** + * Number of times we attempt to restart supplicant + */ + private static final int SUPPLICANT_RESTART_TRIES = 5; + + private int mSupplicantRestartCount = 0; + + /** * Instance of the bluetooth headset helper. This needs to be created * early because there is a delay before it actually 'connects', as * noted by its javadoc. If we check before it is connected, it will be @@ -365,10 +377,11 @@ public class WifiStateMachine extends HierarchicalStateMachine { /* Driver loaded */ private HierarchicalState mDriverLoadedState = new DriverLoadedState(); /* Driver loaded, waiting for supplicant to start */ - private HierarchicalState mWaitForSupState = new WaitForSupState(); - + private HierarchicalState mSupplicantStartingState = new SupplicantStartingState(); /* Driver loaded and supplicant ready */ - private HierarchicalState mDriverSupReadyState = new DriverSupReadyState(); + private HierarchicalState mSupplicantStartedState = new SupplicantStartedState(); + /* Waiting for supplicant to stop and monitor to exit */ + private HierarchicalState mSupplicantStoppingState = new SupplicantStoppingState(); /* Driver start issued, waiting for completed event */ private HierarchicalState mDriverStartingState = new DriverStartingState(); /* Driver started */ @@ -513,10 +526,10 @@ public class WifiStateMachine extends HierarchicalStateMachine { addState(mDriverFailedState, mDriverUnloadedState); addState(mDriverLoadingState, mDefaultState); addState(mDriverLoadedState, mDefaultState); - addState(mWaitForSupState, mDriverLoadedState); - addState(mDriverSupReadyState, mDefaultState); - addState(mDriverStartingState, mDriverSupReadyState); - addState(mDriverStartedState, mDriverSupReadyState); + addState(mSupplicantStartingState, mDefaultState); + addState(mSupplicantStartedState, mDefaultState); + addState(mDriverStartingState, mSupplicantStartedState); + addState(mDriverStartedState, mSupplicantStartedState); addState(mScanModeState, mDriverStartedState); addState(mConnectModeState, mDriverStartedState); addState(mConnectingState, mConnectModeState); @@ -524,8 +537,9 @@ public class WifiStateMachine extends HierarchicalStateMachine { addState(mDisconnectingState, mConnectModeState); addState(mDisconnectedState, mConnectModeState); addState(mWaitForWpsCompletionState, mConnectModeState); - addState(mDriverStoppingState, mDriverSupReadyState); - addState(mDriverStoppedState, mDriverSupReadyState); + addState(mDriverStoppingState, mSupplicantStartedState); + addState(mDriverStoppedState, mSupplicantStartedState); + addState(mSupplicantStoppingState, mDefaultState); addState(mSoftApStartedState, mDefaultState); setInitialState(mInitialState); @@ -1742,7 +1756,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { Log.d(TAG, "Supplicant start successful"); mWifiMonitor.startMonitoring(); setWifiState(WIFI_STATE_ENABLED); - transitionTo(mWaitForSupState); + transitionTo(mSupplicantStartingState); } else { Log.e(TAG, "Failed to start supplicant!"); sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0)); @@ -1888,7 +1902,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { } - class WaitForSupState extends HierarchicalState { + class SupplicantStartingState extends HierarchicalState { @Override public void enter() { if (DBG) Log.d(TAG, getName() + "\n"); @@ -1900,6 +1914,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { switch(message.what) { case SUP_CONNECTION_EVENT: Log.d(TAG, "Supplicant connection established"); + mSupplicantRestartCount = 0; mSupplicantStateTracker.resetSupplicantState(); /* Initialize data structures */ mLastBssid = null; @@ -1919,10 +1934,18 @@ public class WifiStateMachine extends HierarchicalStateMachine { transitionTo(mDriverStartedState); break; case SUP_DISCONNECTION_EVENT: - Log.e(TAG, "Failed to setup control channel, restart supplicant"); - WifiNative.stopSupplicant(); - transitionTo(mDriverLoadedState); - sendMessageAtFrontOfQueue(CMD_START_SUPPLICANT); + if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) { + Log.e(TAG, "Failed to setup control channel, restart supplicant"); + WifiNative.killSupplicant(); + transitionTo(mDriverLoadedState); + sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); + } else { + mSupplicantRestartCount = 0; + Log.e(TAG, "Failed " + mSupplicantRestartCount + + " times to start supplicant, unload driver"); + transitionTo(mDriverLoadedState); + sendMessage(CMD_UNLOAD_DRIVER); + } break; case CMD_LOAD_DRIVER: case CMD_UNLOAD_DRIVER: @@ -1951,7 +1974,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { } } - class DriverSupReadyState extends HierarchicalState { + class SupplicantStartedState extends HierarchicalState { @Override public void enter() { if (DBG) Log.d(TAG, getName() + "\n"); @@ -1966,23 +1989,26 @@ public class WifiStateMachine extends HierarchicalStateMachine { switch(message.what) { case CMD_STOP_SUPPLICANT: /* Supplicant stopped by user */ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); - Log.d(TAG, "Stop supplicant received"); - WifiNative.closeSupplicantConnection(); - WifiNative.stopSupplicant(); + Log.d(TAG, "send terminate command to supplicant"); + if (!WifiNative.terminateCommand()) { + Log.e(TAG, "Failed to terminate cleanly, issue kill"); + WifiNative.killSupplicant(); + } handleNetworkDisconnect(); sendSupplicantConnectionChangedBroadcast(false); mSupplicantStateTracker.resetSupplicantState(); - transitionTo(mDriverLoadedState); + transitionTo(mSupplicantStoppingState); break; - case SUP_DISCONNECTION_EVENT: /* Supplicant died */ + case SUP_DISCONNECTION_EVENT: /* Supplicant connection lost */ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); - Log.e(TAG, "Supplicant died, restarting"); + Log.e(TAG, "Connection lost, restart supplicant"); + WifiNative.killSupplicant(); WifiNative.closeSupplicantConnection(); handleNetworkDisconnect(); sendSupplicantConnectionChangedBroadcast(false); mSupplicantStateTracker.resetSupplicantState(); transitionTo(mDriverLoadedState); - sendMessageAtFrontOfQueue(CMD_START_SUPPLICANT); /* restart */ + sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); break; case SCAN_RESULTS_EVENT: setScanResults(WifiNative.scanResultsCommand()); @@ -2058,6 +2084,51 @@ public class WifiStateMachine extends HierarchicalStateMachine { } } + class SupplicantStoppingState extends HierarchicalState { + @Override + public void enter() { + if (DBG) Log.d(TAG, getName() + "\n"); + EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); + } + @Override + public boolean processMessage(Message message) { + if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); + switch(message.what) { + case SUP_CONNECTION_EVENT: + Log.e(TAG, "Supplicant connection received while stopping"); + break; + case SUP_DISCONNECTION_EVENT: + Log.d(TAG, "Supplicant connection lost"); + WifiNative.closeSupplicantConnection(); + transitionTo(mDriverLoadedState); + break; + case CMD_LOAD_DRIVER: + case CMD_UNLOAD_DRIVER: + case CMD_START_SUPPLICANT: + case CMD_STOP_SUPPLICANT: + case CMD_START_AP: + case CMD_STOP_AP: + case CMD_START_DRIVER: + case CMD_STOP_DRIVER: + case CMD_SET_SCAN_MODE: + case CMD_SET_SCAN_TYPE: + case CMD_SET_HIGH_PERF_MODE: + case CMD_SET_BLUETOOTH_COEXISTENCE: + case CMD_SET_BLUETOOTH_SCAN_MODE: + case CMD_SET_COUNTRY_CODE: + case CMD_SET_FREQUENCY_BAND: + case CMD_START_PACKET_FILTERING: + case CMD_STOP_PACKET_FILTERING: + deferMessage(message); + break; + default: + return NOT_HANDLED; + } + EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); + return HANDLED; + } + } + class DriverStartingState extends HierarchicalState { @Override public void enter() { |