diff options
author | Rebecca Silberstein <silberst@google.com> | 2018-04-03 15:59:39 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2018-04-03 15:59:39 +0000 |
commit | bd0ca3759ab4cbee1ffaf772702a1b2e783a5952 (patch) | |
tree | b29a9e9930821c3fbb01e9ae9603fb1ddb3c6578 /service | |
parent | 85fa6ab417f39148fceee1b7262063249600c0a2 (diff) | |
parent | 48aeddaf3b150d810f2a93da658e40824a99ae2a (diff) |
Merge changes Ie8265bde,Ic42964e0,I13282eb1,Ifb7fc528 into pi-dev
* changes:
WifiStateMachine: remove SupplicantStartingState
WifiController: disable wifi when recovery throttled
WifiStateMachine: remove supplicant disconnect handling
WifiStateMachine: onDown triggers wifi off
Diffstat (limited to 'service')
3 files changed, 139 insertions, 112 deletions
diff --git a/service/java/com/android/server/wifi/SelfRecovery.java b/service/java/com/android/server/wifi/SelfRecovery.java index d3985f5fd..c9e95a77f 100644 --- a/service/java/com/android/server/wifi/SelfRecovery.java +++ b/service/java/com/android/server/wifi/SelfRecovery.java @@ -38,11 +38,13 @@ public class SelfRecovery { */ public static final int REASON_LAST_RESORT_WATCHDOG = 0; public static final int REASON_WIFINATIVE_FAILURE = 1; + public static final int REASON_STA_IFACE_DOWN = 2; public static final long MAX_RESTARTS_IN_TIME_WINDOW = 2; // 2 restarts per hour public static final long MAX_RESTARTS_TIME_WINDOW_MILLIS = 60 * 60 * 1000; // 1 hour protected static final String[] REASON_STRINGS = { - "Last Resort Watchdog", // REASON_LAST_RESORT_WATCHDOG - "WifiNative Failure" // REASON_WIFINATIVE_FAILURE + "Last Resort Watchdog", // REASON_LAST_RESORT_WATCHDOG + "WifiNative Failure", // REASON_WIFINATIVE_FAILURE + "Sta Interface Down" // REASON_STA_IFACE_DOWN }; private final WifiController mWifiController; @@ -59,28 +61,39 @@ public class SelfRecovery { * Trigger recovery. * * This method does the following: - * 1. Raises a wtf. - * 2. Sends {@link WifiController#CMD_RESTART_WIFI} to {@link WifiController} to initiate the - * stack restart. + * 1. Checks reason code used to trigger recovery + * 2. Checks for sta iface down triggers and disables wifi by sending {@link + * WifiController#CMD_RECOVERY_DISABLE_WIFI} to {@link WifiController} to disable wifi. + * 3. Throttles restart calls for underlying native failures + * 4. Sends {@link WifiController#CMD_RECOVERY_RESTART_WIFI} to {@link WifiController} to + * initiate the stack restart. * @param reason One of the above |REASON_*| codes. */ public void trigger(int reason) { - if (!(reason == REASON_LAST_RESORT_WATCHDOG || reason == REASON_WIFINATIVE_FAILURE)) { + if (!(reason == REASON_LAST_RESORT_WATCHDOG || reason == REASON_WIFINATIVE_FAILURE + || reason == REASON_STA_IFACE_DOWN)) { Log.e(TAG, "Invalid trigger reason. Ignoring..."); return; } + if (reason == REASON_STA_IFACE_DOWN) { + Log.e(TAG, "STA interface down, disable wifi"); + mWifiController.sendMessage(WifiController.CMD_RECOVERY_DISABLE_WIFI); + return; + } + Log.e(TAG, "Triggering recovery for reason: " + REASON_STRINGS[reason]); if (reason == REASON_WIFINATIVE_FAILURE) { trimPastRestartTimes(); // Ensure there haven't been too many restarts within MAX_RESTARTS_TIME_WINDOW if (mPastRestartTimes.size() >= MAX_RESTARTS_IN_TIME_WINDOW) { Log.e(TAG, "Already restarted wifi (" + MAX_RESTARTS_IN_TIME_WINDOW + ") times in" - + " last (" + MAX_RESTARTS_TIME_WINDOW_MILLIS + "ms ). Ignoring..."); + + " last (" + MAX_RESTARTS_TIME_WINDOW_MILLIS + "ms ). Disabling wifi"); + mWifiController.sendMessage(WifiController.CMD_RECOVERY_DISABLE_WIFI); return; } mPastRestartTimes.add(mClock.getElapsedSinceBootMillis()); } - mWifiController.sendMessage(WifiController.CMD_RESTART_WIFI, reason); + mWifiController.sendMessage(WifiController.CMD_RECOVERY_RESTART_WIFI, reason); } /** diff --git a/service/java/com/android/server/wifi/WifiController.java b/service/java/com/android/server/wifi/WifiController.java index 5cc0306e1..3db804b9b 100644 --- a/service/java/com/android/server/wifi/WifiController.java +++ b/service/java/com/android/server/wifi/WifiController.java @@ -76,21 +76,23 @@ public class WifiController extends StateMachine { private static final int BASE = Protocol.BASE_WIFI_CONTROLLER; - static final int CMD_EMERGENCY_MODE_CHANGED = BASE + 1; - static final int CMD_SCAN_ALWAYS_MODE_CHANGED = BASE + 7; - static final int CMD_WIFI_TOGGLED = BASE + 8; - static final int CMD_AIRPLANE_TOGGLED = BASE + 9; - static final int CMD_SET_AP = BASE + 10; - static final int CMD_DEFERRED_TOGGLE = BASE + 11; - static final int CMD_USER_PRESENT = BASE + 12; - static final int CMD_AP_START_FAILURE = BASE + 13; - static final int CMD_EMERGENCY_CALL_STATE_CHANGED = BASE + 14; - static final int CMD_AP_STOPPED = BASE + 15; - static final int CMD_STA_START_FAILURE = BASE + 16; + static final int CMD_EMERGENCY_MODE_CHANGED = BASE + 1; + static final int CMD_SCAN_ALWAYS_MODE_CHANGED = BASE + 7; + static final int CMD_WIFI_TOGGLED = BASE + 8; + static final int CMD_AIRPLANE_TOGGLED = BASE + 9; + static final int CMD_SET_AP = BASE + 10; + static final int CMD_DEFERRED_TOGGLE = BASE + 11; + static final int CMD_USER_PRESENT = BASE + 12; + static final int CMD_AP_START_FAILURE = BASE + 13; + static final int CMD_EMERGENCY_CALL_STATE_CHANGED = BASE + 14; + static final int CMD_AP_STOPPED = BASE + 15; + static final int CMD_STA_START_FAILURE = BASE + 16; // Command used to trigger a wifi stack restart when in active mode - static final int CMD_RESTART_WIFI = BASE + 17; + static final int CMD_RECOVERY_RESTART_WIFI = BASE + 17; // Internal command used to complete wifi stack restart - private static final int CMD_RESTART_WIFI_CONTINUE = BASE + 18; + private static final int CMD_RECOVERY_RESTART_WIFI_CONTINUE = BASE + 18; + // Command to disable wifi when SelfRecovery is throttled or otherwise not doing full recovery + static final int CMD_RECOVERY_DISABLE_WIFI = BASE + 19; private DefaultState mDefaultState = new DefaultState(); private StaEnabledState mStaEnabledState = new StaEnabledState(); @@ -215,8 +217,9 @@ public class WifiController extends StateMachine { case CMD_AP_START_FAILURE: case CMD_AP_STOPPED: case CMD_STA_START_FAILURE: - case CMD_RESTART_WIFI: - case CMD_RESTART_WIFI_CONTINUE: + case CMD_RECOVERY_RESTART_WIFI: + case CMD_RECOVERY_RESTART_WIFI_CONTINUE: + case CMD_RECOVERY_DISABLE_WIFI: break; case CMD_USER_PRESENT: mFirstUserSignOnSeen = true; @@ -297,7 +300,7 @@ public class WifiController extends StateMachine { log("DEFERRED_TOGGLE handled"); sendMessage((Message)(msg.obj)); break; - case CMD_RESTART_WIFI_CONTINUE: + case CMD_RECOVERY_RESTART_WIFI_CONTINUE: transitionTo(mDeviceActiveState); break; default: @@ -649,7 +652,7 @@ public class WifiController extends StateMachine { } mFirstUserSignOnSeen = true; return HANDLED; - } else if (msg.what == CMD_RESTART_WIFI) { + } else if (msg.what == CMD_RECOVERY_RESTART_WIFI) { final String bugTitle = "Wi-Fi BugReport"; final String bugDetail; if (msg.obj != null && msg.arg1 < SelfRecovery.REASON_STRINGS.length @@ -663,9 +666,12 @@ public class WifiController extends StateMachine { mWifiStateMachine.takeBugReport(bugTitle, bugDetail); }); } - deferMessage(obtainMessage(CMD_RESTART_WIFI_CONTINUE)); + deferMessage(obtainMessage(CMD_RECOVERY_RESTART_WIFI_CONTINUE)); transitionTo(mApStaDisabledState); return HANDLED; + } else if (msg.what == CMD_RECOVERY_DISABLE_WIFI) { + loge("Recovery has been throttled, disable wifi"); + transitionTo(mApStaDisabledState); } return NOT_HANDLED; } diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index eb3848dc6..e2345e9b1 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -229,15 +229,23 @@ public class WifiStateMachine extends StateMachine { private final InterfaceCallback mWifiNativeInterfaceCallback = new InterfaceCallback() { @Override public void onDestroyed(String ifaceName) { - sendMessage(CMD_INTERFACE_DESTROYED); + if (mInterfaceName != null && mInterfaceName.equals(ifaceName)) { + sendMessage(CMD_INTERFACE_DESTROYED); + } } @Override public void onUp(String ifaceName) { + if (mInterfaceName != null && mInterfaceName.equals(ifaceName)) { + sendMessage(CMD_INTERFACE_STATUS_CHANGED, 1); + } } @Override public void onDown(String ifaceName) { + if (mInterfaceName != null && mInterfaceName.equals(ifaceName)) { + sendMessage(CMD_INTERFACE_STATUS_CHANGED, 0); + } } }; private boolean mIpReachabilityDisconnectEnabled = true; @@ -326,8 +334,6 @@ public class WifiStateMachine extends StateMachine { */ public static final String SUPPLICANT_BSSID_ANY = "any"; - private int mSupplicantRestartCount = 0; - /** * The link properties of the wifi interface. * Do not modify this directly; use updateLinkProperties instead. @@ -459,12 +465,14 @@ public class WifiStateMachine extends StateMachine { static final int CMD_STOP_SUPPLICANT = BASE + 12; /* STA interface destroyed */ static final int CMD_INTERFACE_DESTROYED = BASE + 13; + /* STA interface down */ + static final int CMD_INTERFACE_DOWN = BASE + 14; /* Indicates Static IP succeeded */ static final int CMD_STATIC_IP_SUCCESS = BASE + 15; /* Indicates Static IP failed */ static final int CMD_STATIC_IP_FAILURE = BASE + 16; - /* A delayed message sent to start driver when it fail to come up */ - static final int CMD_DRIVER_START_TIMED_OUT = BASE + 19; + /* Interface status change */ + static final int CMD_INTERFACE_STATUS_CHANGED = BASE + 20; /* Start the soft access point */ static final int CMD_START_AP = BASE + 21; @@ -769,8 +777,6 @@ public class WifiStateMachine extends StateMachine { private State mDefaultState = new DefaultState(); /* Temporary initial state */ private State mInitialState = new InitialState(); - /* Driver loaded, waiting for supplicant to start */ - private State mSupplicantStartingState = new SupplicantStartingState(); /* Driver loaded and supplicant ready */ private State mSupplicantStartedState = new SupplicantStartedState(); /* Scan for networks, no connection will be established */ @@ -992,7 +998,6 @@ public class WifiStateMachine extends StateMachine { // CHECKSTYLE:OFF IndentationCheck addState(mDefaultState); addState(mInitialState, mDefaultState); - addState(mSupplicantStartingState, mInitialState); addState(mSupplicantStartedState, mInitialState); addState(mConnectModeState, mSupplicantStartedState); addState(mL2ConnectedState, mConnectModeState); @@ -1045,9 +1050,6 @@ public class WifiStateMachine extends StateMachine { getHandler()); mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.RX_HS20_ANQP_ICON_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_CONNECTION_EVENT, getHandler()); - mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_DISCONNECTION_EVENT, - getHandler()); mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, getHandler()); mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_REQUEST_IDENTITY, @@ -3380,6 +3382,25 @@ public class WifiStateMachine extends StateMachine { + macRandomizationEnabled); } + /** + * Handle the error case where our underlying interface went down (if we do not have mac + * randomization enabled (b/72459123). + * + * This method triggers SelfRecovery with the error of REASON_STA_IFACE_DOWN. SelfRecovery then + * decides if wifi should be restarted or disabled. + */ + private void handleInterfaceDown() { + if (mEnableConnectedMacRandomization.get()) { + // interface will go down when mac randomization is active, skip + Log.d(TAG, "MacRandomization enabled, ignoring iface down"); + return; + } + + Log.e(TAG, "Detected an interface down, report failure to SelfRecovery"); + // report a failure + mWifiInjector.getSelfRecovery().trigger(SelfRecovery.REASON_STA_IFACE_DOWN); + } + /******************************************************** * HSM states *******************************************************/ @@ -3488,7 +3509,6 @@ public class WifiStateMachine extends StateMachine { break; case CMD_START_SUPPLICANT: case CMD_STOP_SUPPLICANT: - case CMD_DRIVER_START_TIMED_OUT: case CMD_START_AP_FAILURE: case CMD_STOP_AP: case CMD_AP_STOPPED: @@ -3496,8 +3516,6 @@ public class WifiStateMachine extends StateMachine { case CMD_RECONNECT: case CMD_REASSOCIATE: case CMD_RELOAD_TLS_AND_RECONNECT: - case WifiMonitor.SUP_CONNECTION_EVENT: - case WifiMonitor.SUP_DISCONNECTION_EVENT: case WifiMonitor.NETWORK_CONNECTION_EVENT: case WifiMonitor.NETWORK_DISCONNECTION_EVENT: case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: @@ -3524,6 +3542,8 @@ public class WifiStateMachine extends StateMachine { case CMD_SELECT_TX_POWER_SCENARIO: case CMD_WIFINATIVE_FAILURE: case CMD_INTERFACE_DESTROYED: + case CMD_INTERFACE_DOWN: + case CMD_INTERFACE_STATUS_CHANGED: messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; break; case CMD_START_AP: @@ -3712,6 +3732,23 @@ public class WifiStateMachine extends StateMachine { } class InitialState extends State { + private boolean mIfaceIsUp; + + private void onUpChanged(boolean isUp) { + if (isUp == mIfaceIsUp) { + return; // no change + } + mIfaceIsUp = isUp; + if (isUp) { + Log.d(TAG, "Client mode interface is up"); + // for now, do nothing - client mode has never waited for iface up + } else { + // A driver/firmware hang can now put the interface in a down state. + // We detect the interface going down and recover from it + handleInterfaceDown(); + } + } + private void cleanup() { // tell scanning service that scans are not available - about to kill the interface and // supplicant @@ -3727,10 +3764,12 @@ public class WifiStateMachine extends StateMachine { // TODO: Remove this big hammer. We cannot support concurrent interfaces with this! mWifiNative.teardownAllInterfaces(); mInterfaceName = null; + mIfaceIsUp = false; } @Override public void enter() { + mIfaceIsUp = false; mWifiMonitor.stopAllMonitoring(); mWifiStateTracker.updateState(WifiStateTracker.INVALID); cleanup(); @@ -3751,6 +3790,9 @@ public class WifiStateMachine extends StateMachine { transitionTo(mDefaultState); break; } + // now that we have the interface, initialize our up/down status + onUpChanged(mWifiNative.isInterfaceUp(mInterfaceName)); + mIpClient = mFacade.makeIpClient( mContext, mInterfaceName, new IpClientCallback()); mIpClient.setMulticastFilter(true); @@ -3759,7 +3801,7 @@ public class WifiStateMachine extends StateMachine { mWifiMonitor.startMonitoring(mInterfaceName); mWifiInjector.getWifiLastResortWatchdog().clearAllFailureCounts(); setSupplicantLogLevel(); - transitionTo(mSupplicantStartingState); + transitionTo(mSupplicantStartedState); break; case CMD_SET_OPERATIONAL_MODE: if (message.arg1 == CONNECT_MODE) { @@ -3773,46 +3815,20 @@ public class WifiStateMachine extends StateMachine { WifiDiagnostics.REPORT_REASON_WIFINATIVE_FAILURE); mWifiInjector.getSelfRecovery().trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE); break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class SupplicantStartingState extends State { - - @Override - public boolean processMessage(Message message) { - logStateAndMessage(message, this); - - switch(message.what) { - case WifiMonitor.SUP_CONNECTION_EVENT: - if (mVerboseLoggingEnabled) log("Supplicant connection established"); - - mSupplicantRestartCount = 0; - /* Reset the supplicant state to indicate the supplicant - * state is not known at this time */ - mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); - /* Initialize data structures */ - mLastBssid = null; - mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; - mLastSignalLevel = -1; - mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName)); - // Attempt to migrate data out of legacy store. - if (!mWifiConfigManager.migrateFromLegacyStore()) { - Log.e(TAG, "Failed to migrate from legacy config store"); + case CMD_INTERFACE_STATUS_CHANGED: + boolean isUp = message.arg1 == 1; + // For now, this message can be triggered due to link state and/or interface + // status changes (b/77218676). First check if we really see an iface down by + // consulting our view of supplicant state. + if (!isUp && SupplicantState.isDriverActive(mWifiInfo.getSupplicantState())) { + // the driver is active, so this could just be part of normal operation, do + // not disable wifi in these cases (ex, a network was removed) or worry + // about the link status + break; } - sendSupplicantConnectionChangedBroadcast(true); - transitionTo(mSupplicantStartedState); - break; - case WifiMonitor.SUP_DISCONNECTION_EVENT: - // since control is split between WSM and WSMP - do not worry about supplicant - // dying if we haven't seen it up yet + + onUpChanged(isUp); break; - case CMD_START_SUPPLICANT: - case CMD_STOP_SUPPLICANT: - case CMD_STOP_AP: default: return NOT_HANDLED; } @@ -3827,6 +3843,19 @@ public class WifiStateMachine extends StateMachine { logd("SupplicantStartedState enter"); } + // reset state related to supplicant starting + mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); + // Initialize data structures + mLastBssid = null; + mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; + mLastSignalLevel = -1; + mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName)); + // Attempt to migrate data out of legacy store. + if (!mWifiConfigManager.migrateFromLegacyStore()) { + Log.e(TAG, "Failed to migrate from legacy config store"); + } + sendSupplicantConnectionChangedBroadcast(true); + mWifiNative.setExternalSim(mInterfaceName, true); setRandomMacOui(); @@ -3897,19 +3926,6 @@ public class WifiStateMachine extends StateMachine { logStateAndMessage(message, this); switch(message.what) { - case WifiMonitor.SUP_DISCONNECTION_EVENT: /* Supplicant connection lost */ - // first check if we are expecting a mode switch - if (mModeChange) { - logd("expecting a mode change, do not restart supplicant"); - return HANDLED; - } - loge("Connection lost, restart supplicant"); - handleSupplicantConnectionLoss(true); - handleNetworkDisconnect(); - mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); - sendMessage(CMD_START_SUPPLICANT); - transitionTo(mInitialState); - break; case CMD_TARGET_BSSID: // Trying to associate to this BSSID if (message.obj != null) { @@ -4082,12 +4098,6 @@ public class WifiStateMachine extends StateMachine { case WifiManager.FORGET_NETWORK: s = "FORGET_NETWORK"; break; - case WifiMonitor.SUP_CONNECTION_EVENT: - s = "SUP_CONNECTION_EVENT"; - break; - case WifiMonitor.SUP_DISCONNECTION_EVENT: - s = "SUP_DISCONNECTION_EVENT"; - break; case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: s = "SUPPLICANT_STATE_CHANGE_EVENT"; break; @@ -4336,20 +4346,6 @@ public class WifiStateMachine extends StateMachine { break; case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: SupplicantState state = handleSupplicantStateChange(message); - // A driver/firmware hang can now put the interface in a down state. - // We detect the interface going down and recover from it - if (!SupplicantState.isDriverActive(state) && !mModeChange - && !mEnableConnectedMacRandomization.get()) { - if (mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) { - handleNetworkDisconnect(); - } - log("Detected an interface down, restart driver"); - // Rely on the fact that this will force us into killing supplicant and then - // restart supplicant from a clean state. - sendMessage(CMD_START_SUPPLICANT); - transitionTo(mInitialState); - break; - } // Supplicant can fail to report a NETWORK_DISCONNECTION_EVENT // when authentication times out after a successful connection, @@ -4371,6 +4367,18 @@ public class WifiStateMachine extends StateMachine { if (state == SupplicantState.COMPLETED) { mIpClient.confirmConfiguration(); } + + if (!SupplicantState.isDriverActive(state)) { + // still use supplicant to detect interface down while work to + // mitigate b/77218676 is in progress + // note: explicitly using this command to dedup iface down notification + // paths (onUpChanged filters out duplicate updates) + sendMessage(CMD_INTERFACE_STATUS_CHANGED, 0); + if (mVerboseLoggingEnabled) { + Log.d(TAG, "detected interface down via supplicant"); + } + } + break; case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: if (message.arg1 == 1) { |