diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2020-04-09 22:32:30 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-04-09 22:32:30 +0000 |
commit | 66ed6f4c29a78457585afe5d5734ba6035d70e08 (patch) | |
tree | 622c23209e2bedf897bf7f30e406c6036596a83e | |
parent | b9e042d647ff9f0249151d774db05d1c44c026f9 (diff) | |
parent | 4a6c9ac574b2b801b8babe12291170019a866136 (diff) |
Merge changes I9e62138a,Iafcd193e into rvc-dev
* changes:
WifiBackupRestoreTest: Fix a unit test for new auto-join flag
SelfRecovery: Add overlay for the recovery limit
7 files changed, 109 insertions, 42 deletions
diff --git a/service/java/com/android/server/wifi/SelfRecovery.java b/service/java/com/android/server/wifi/SelfRecovery.java index e789dd3a4..b7eb72364 100644 --- a/service/java/com/android/server/wifi/SelfRecovery.java +++ b/service/java/com/android/server/wifi/SelfRecovery.java @@ -17,12 +17,16 @@ package com.android.server.wifi; import android.annotation.IntDef; +import android.content.Context; import android.util.Log; +import com.android.wifi.resources.R; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Iterator; import java.util.LinkedList; +import java.util.concurrent.TimeUnit; /** * This class is used to recover the wifi stack from a fatal failure. The recovery mechanism @@ -50,19 +54,19 @@ public class SelfRecovery { REASON_STA_IFACE_DOWN}) public @interface RecoveryReason {} - 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 "Sta Interface Down" // REASON_STA_IFACE_DOWN }; + private final Context mContext; private final ActiveModeWarden mActiveModeWarden; private final Clock mClock; // Time since boot (in millis) that restart occurred private final LinkedList<Long> mPastRestartTimes; - public SelfRecovery(ActiveModeWarden activeModeWarden, Clock clock) { + public SelfRecovery(Context context, ActiveModeWarden activeModeWarden, Clock clock) { + mContext = context; mActiveModeWarden = activeModeWarden; mClock = clock; mPastRestartTimes = new LinkedList<>(); @@ -94,11 +98,17 @@ public class SelfRecovery { Log.e(TAG, "Triggering recovery for reason: " + REASON_STRINGS[reason]); if (reason == REASON_WIFINATIVE_FAILURE) { + int maxRecoveriesPerHour = mContext.getResources().getInteger( + R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour); + if (maxRecoveriesPerHour == 0) { + Log.e(TAG, "Recovery disabled. Disabling wifi"); + mActiveModeWarden.recoveryDisableWifi(); + return; + } 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 ). Disabling wifi"); + if (mPastRestartTimes.size() >= maxRecoveriesPerHour) { + Log.e(TAG, "Already restarted wifi " + maxRecoveriesPerHour + " times in" + + " last 1 hour. Disabling wifi"); mActiveModeWarden.recoveryDisableWifi(); return; } @@ -115,7 +125,7 @@ public class SelfRecovery { long now = mClock.getElapsedSinceBootMillis(); while (iter.hasNext()) { Long restartTimeMillis = iter.next(); - if (now - restartTimeMillis > MAX_RESTARTS_TIME_WINDOW_MILLIS) { + if (now - restartTimeMillis > TimeUnit.HOURS.toMillis(1)) { iter.remove(); } else { break; diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java index 68311303b..78bacc56d 100644 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ b/service/java/com/android/server/wifi/WifiInjector.java @@ -369,7 +369,7 @@ public class WifiInjector { this, mFrameworkFacade, mClock); mLockManager = new WifiLockManager(mContext, mBatteryStats, mClientModeImpl, mFrameworkFacade, wifiHandler, mWifiNative, mClock, mWifiMetrics); - mSelfRecovery = new SelfRecovery(mActiveModeWarden, mClock); + mSelfRecovery = new SelfRecovery(mContext, mActiveModeWarden, mClock); mWifiMulticastLockManager = new WifiMulticastLockManager( mClientModeImpl.getMcastLockManagerFilterController(), mBatteryStats); mDppManager = new DppManager(wifiHandler, mWifiNative, diff --git a/service/java/com/android/server/wifi/WifiShellCommand.java b/service/java/com/android/server/wifi/WifiShellCommand.java index f3bd4ba01..6af4e8dd3 100644 --- a/service/java/com/android/server/wifi/WifiShellCommand.java +++ b/service/java/com/android/server/wifi/WifiShellCommand.java @@ -407,11 +407,12 @@ public class WifiShellCommand extends BasicShellCommandHandler { countDownLatch.countDown(); } }; + WifiConfiguration config = buildWifiConfiguration(pw); mWifiService.connect( - buildWifiConfiguration(pw), -1, new Binder(), actionListener, - actionListener.hashCode()); + config, -1, new Binder(), actionListener, actionListener.hashCode()); // wait for status. countDownLatch.await(500, TimeUnit.MILLISECONDS); + setAutoJoin(pw, config.SSID, config.allowAutojoin); break; } case "add-network": { @@ -429,11 +430,12 @@ public class WifiShellCommand extends BasicShellCommandHandler { countDownLatch.countDown(); } }; + WifiConfiguration config = buildWifiConfiguration(pw); mWifiService.save( - buildWifiConfiguration(pw), new Binder(), actionListener, - actionListener.hashCode()); + config, new Binder(), actionListener, actionListener.hashCode()); // wait for status. countDownLatch.await(500, TimeUnit.MILLISECONDS); + setAutoJoin(pw, config.SSID, config.allowAutojoin); break; } case "forget-network": { @@ -489,10 +491,12 @@ public class WifiShellCommand extends BasicShellCommandHandler { mWifiService.enableVerboseLogging(enabled ? 1 : 0); break; } - case "add-suggestion": + case "add-suggestion": { + WifiNetworkSuggestion suggestion = buildSuggestion(pw); mWifiService.addNetworkSuggestions( - Arrays.asList(buildSuggestion(pw)), SHELL_PACKAGE_NAME, null); + Arrays.asList(suggestion), SHELL_PACKAGE_NAME, null); break; + } case "remove-suggestion": { String ssid = getNextArgRequired(); List<WifiNetworkSuggestion> suggestions = @@ -652,6 +656,8 @@ public class WifiShellCommand extends BasicShellCommandHandler { while (option != null) { if (option.equals("-m")) { configuration.meteredOverride = METERED_OVERRIDE_METERED; + } else if (option.equals("-d")) { + configuration.allowAutojoin = false; } else { pw.println("Ignoring unknown option " + option); } @@ -685,6 +691,8 @@ public class WifiShellCommand extends BasicShellCommandHandler { suggestionBuilder.setIsMetered(true); } else if (option.equals("-s")) { suggestionBuilder.setCredentialSharedWithUser(true); + } else if (option.equals("-d")) { + suggestionBuilder.setIsInitialAutojoinEnabled(false); } else { pw.println("Ignoring unknown option " + option); } @@ -730,6 +738,23 @@ public class WifiShellCommand extends BasicShellCommandHandler { .build(); } + private void setAutoJoin(PrintWriter pw, String ssid, boolean allowAutojoin) { + // For suggestions, this will work only if the config has already been added + // to WifiConfigManager. + WifiConfiguration retrievedConfig = + mWifiService.getPrivilegedConfiguredNetworks(SHELL_PACKAGE_NAME, null) + .getList() + .stream() + .filter(n -> n.SSID.equals(ssid)) + .findAny() + .orElse(null); + if (retrievedConfig == null) { + pw.println("Cannot retrieve config, autojoin setting skipped."); + return; + } + mWifiService.allowAutojoin(retrievedConfig.networkId, allowAutojoin); + } + private int sendLinkProbe(PrintWriter pw) throws InterruptedException { // Note: should match WifiNl80211Manager#SEND_MGMT_FRAME_TIMEOUT_MS final int sendMgmtFrameTimeoutMs = 1000; @@ -795,7 +820,7 @@ public class WifiShellCommand extends BasicShellCommandHandler { pw.println(" Start a new scan"); pw.println(" list-networks"); pw.println(" Lists the saved networks"); - pw.println(" connect-network <ssid> open|owe|wpa2|wpa3 [<passphrase>] [-m]"); + pw.println(" connect-network <ssid> open|owe|wpa2|wpa3 [<passphrase>] [-m] [-d]"); pw.println(" Connect to a network with provided params and add to saved networks list"); pw.println(" <ssid> - SSID of the network"); pw.println(" open|owe|wpa2|wpa3 - Security type of the network."); @@ -806,7 +831,8 @@ public class WifiShellCommand extends BasicShellCommandHandler { pw.println(" - 'wpa2' - WPA-2 PSK networks (Most prevalent)"); pw.println(" - 'wpa3' - WPA-3 PSK networks"); pw.println(" -m - Mark the network metered."); - pw.println(" add-network <ssid> open|owe|wpa2|wpa3 [<passphrase>] [-m]"); + pw.println(" -d - Mark the network autojoin disabled."); + pw.println(" add-network <ssid> open|owe|wpa2|wpa3 [<passphrase>] [-m] [-d]"); pw.println(" Add/update saved network with provided params"); pw.println(" <ssid> - SSID of the network"); pw.println(" open|owe|wpa2|wpa3 - Security type of the network."); @@ -817,6 +843,7 @@ public class WifiShellCommand extends BasicShellCommandHandler { pw.println(" - 'wpa2' - WPA-2 PSK networks (Most prevalent)"); pw.println(" - 'wpa3' - WPA-3 PSK networks"); pw.println(" -m - Mark the network metered."); + pw.println(" -d - Mark the network autojoin disabled."); pw.println(" forget-network <networkId>"); pw.println(" Remove the network mentioned by <networkId>"); pw.println(" - Use list-networks to retrieve <networkId> for the network"); @@ -824,7 +851,7 @@ public class WifiShellCommand extends BasicShellCommandHandler { pw.println(" Current wifi status"); pw.println(" set-verbose-logging enabled|disabled "); pw.println(" Set the verbose logging enabled or disabled"); - pw.println(" add-suggestion <ssid> open|owe|wpa2|wpa3 [<passphrase>] [-u] [-m] [-s]"); + pw.println(" add-suggestion <ssid> open|owe|wpa2|wpa3 [<passphrase>] [-u] [-m] [-s] [-d]"); pw.println(" Add a network suggestion with provided params"); pw.println(" Use 'network-suggestions-set-user-approved " + SHELL_PACKAGE_NAME + " yes'" + " to approve suggestions added via shell (Needs root access)"); @@ -839,6 +866,7 @@ public class WifiShellCommand extends BasicShellCommandHandler { pw.println(" -u - Mark the suggestion untrusted."); pw.println(" -m - Mark the suggestion metered."); pw.println(" -s - Share the suggestion with user."); + pw.println(" -d - Mark the suggestion autojoin disabled."); pw.println(" remove-suggestion <ssid>"); pw.println(" Remove a network suggestion with provided SSID of the network"); pw.println(" remove-all-suggestions"); diff --git a/service/res/values/config.xml b/service/res/values/config.xml index 4d351b105..43d4a03c5 100644 --- a/service/res/values/config.xml +++ b/service/res/values/config.xml @@ -399,4 +399,9 @@ <!-- Enable WPA2 to WPA3 auto-upgrade offload to capable Driver/Firmware --> <bool translatable="false" name="config_wifiSaeUpgradeOffloadEnabled">false</bool> + + <!-- Number of self recoveries to be attempted per hour. Any fatal errors beyond this will + cause the wifi stack to turn wifi off and wait for user input. + Set to 0 to turn off recovery attempts and always turn off wifi on failures --> + <integer translatable="false" name="config_wifiMaxNativeFailureSelfRecoveryPerHour">2</integer> </resources> diff --git a/service/res/values/overlayable.xml b/service/res/values/overlayable.xml index 7244911af..028d7240f 100644 --- a/service/res/values/overlayable.xml +++ b/service/res/values/overlayable.xml @@ -126,6 +126,7 @@ <item type="integer" name="config_wifiPollRssiIntervalMilliseconds" /> <item type="bool" name="config_wifiSaeUpgradeEnabled" /> <item type="bool" name="config_wifiSaeUpgradeOffloadEnabled" /> + <item type="integer" name="config_wifiMaxNativeFailureSelfRecoveryPerHour" /> <!-- Params from config.xml that can be overlayed --> <!-- Params from strings.xml that can be overlayed --> diff --git a/tests/wifitests/src/com/android/server/wifi/SelfRecoveryTest.java b/tests/wifitests/src/com/android/server/wifi/SelfRecoveryTest.java index fe8bfd575..3538598c3 100644 --- a/tests/wifitests/src/com/android/server/wifi/SelfRecoveryTest.java +++ b/tests/wifitests/src/com/android/server/wifi/SelfRecoveryTest.java @@ -19,25 +19,39 @@ package com.android.server.wifi; import static org.mockito.Mockito.*; import static org.mockito.MockitoAnnotations.*; +import android.content.Context; + import androidx.test.filters.SmallTest; +import com.android.wifi.resources.R; + import org.junit.Before; import org.junit.Test; import org.mockito.Mock; +import java.util.concurrent.TimeUnit; + /** * Unit tests for {@link com.android.server.wifi.SelfRecovery}. */ @SmallTest public class SelfRecoveryTest extends WifiBaseTest { + private static final int DEFAULT_MAX_RECOVERY_PER_HOUR = 2; SelfRecovery mSelfRecovery; + MockResources mResources; + @Mock Context mContext; @Mock ActiveModeWarden mActiveModeWarden; @Mock Clock mClock; @Before public void setUp() throws Exception { initMocks(this); - mSelfRecovery = new SelfRecovery(mActiveModeWarden, mClock); + mResources = new MockResources(); + // Default value of 2 recovery per hour. + mResources.setInteger(R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour, + DEFAULT_MAX_RECOVERY_PER_HOUR); + when(mContext.getResources()).thenReturn(mResources); + mSelfRecovery = new SelfRecovery(mContext, mActiveModeWarden, mClock); } /** @@ -51,7 +65,7 @@ public class SelfRecoveryTest extends WifiBaseTest { reset(mActiveModeWarden); when(mClock.getElapsedSinceBootMillis()) - .thenReturn(SelfRecovery.MAX_RESTARTS_TIME_WINDOW_MILLIS + 1); + .thenReturn(TimeUnit.HOURS.toMillis(1) + 1); mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE); verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE); reset(mActiveModeWarden); @@ -80,25 +94,16 @@ public class SelfRecoveryTest extends WifiBaseTest { } /** - * Verifies that invocations of {@link SelfRecovery#trigger(int)} for REASON_HAL_CRASH & - * REASON_WIFICOND_CRASH are limited to {@link SelfRecovery#MAX_RESTARTS_IN_TIME_WINDOW} in a - * {@link SelfRecovery#MAX_RESTARTS_TIME_WINDOW_MILLIS} millisecond time window. + * Verifies that invocations of {@link SelfRecovery#trigger(int)} for REASON_WIFI_NATIVE + * are limited to {@link R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour} in a + * 1 hour time window. */ @Test public void testTimeWindowLimiting_typicalUse() { when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); // Fill up the SelfRecovery's restart time window buffer, ensure all the restart triggers // aren't ignored - for (int i = 0; i < SelfRecovery.MAX_RESTARTS_IN_TIME_WINDOW / 2; i++) { - mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE); - verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE); - reset(mActiveModeWarden); - - mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE); - verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE); - reset(mActiveModeWarden); - } - if ((SelfRecovery.MAX_RESTARTS_IN_TIME_WINDOW % 2) == 1) { + for (int i = 0; i < DEFAULT_MAX_RECOVERY_PER_HOUR; i++) { mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE); verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE); reset(mActiveModeWarden); @@ -128,27 +133,46 @@ public class SelfRecoveryTest extends WifiBaseTest { // now TRAVEL FORWARDS IN TIME and ensure that more restarts can occur when(mClock.getElapsedSinceBootMillis()) - .thenReturn(SelfRecovery.MAX_RESTARTS_TIME_WINDOW_MILLIS + 1); + .thenReturn(TimeUnit.HOURS.toMillis(1) + 1); mSelfRecovery.trigger(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); reset(mActiveModeWarden); when(mClock.getElapsedSinceBootMillis()) - .thenReturn(SelfRecovery.MAX_RESTARTS_TIME_WINDOW_MILLIS + 1); + .thenReturn(TimeUnit.HOURS.toMillis(1) + 1); mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE); verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE); reset(mActiveModeWarden); } /** + * Verifies that invocations of {@link SelfRecovery#trigger(int)} for REASON_WIFI_NATIVE + * does not trigger recovery if {@link R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour} + * is set to 0 + */ + @Test + public void testTimeWindowLimiting_NativeFailureOff() { + when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); + mResources.setInteger(R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour, 0); + mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE); + verify(mActiveModeWarden, never()) + .recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE); + verify(mActiveModeWarden).recoveryDisableWifi(); + reset(mActiveModeWarden); + + // Verify L.R.Watchdog can still restart things (It has its own complex limiter) + mSelfRecovery.trigger(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); + verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); + } + + /** * Verifies that invocations of {@link SelfRecovery#trigger(int)} for * REASON_LAST_RESORT_WATCHDOG are NOT limited to - * {@link SelfRecovery#MAX_RESTARTS_IN_TIME_WINDOW} in a - * {@link SelfRecovery#MAX_RESTARTS_TIME_WINDOW_MILLIS} millisecond time window. + * {{@link R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour} in a 1 hour time window. */ @Test public void testTimeWindowLimiting_lastResortWatchdog_noEffect() { - for (int i = 0; i < SelfRecovery.MAX_RESTARTS_IN_TIME_WINDOW * 2; i++) { + for (int i = 0; i < DEFAULT_MAX_RECOVERY_PER_HOUR * 2; i++) { // Verify L.R.Watchdog can still restart things (It has it's own complex limiter) mSelfRecovery.trigger(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); @@ -159,12 +183,11 @@ public class SelfRecoveryTest extends WifiBaseTest { /** * Verifies that invocations of {@link SelfRecovery#trigger(int)} for * REASON_STA_IFACE_DOWN are NOT limited to - * {@link SelfRecovery#MAX_RESTARTS_IN_TIME_WINDOW} in a - * {@link SelfRecovery#MAX_RESTARTS_TIME_WINDOW_MILLIS} millisecond time window. + * {{@link R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour} in a 1 hour time window. */ @Test public void testTimeWindowLimiting_staIfaceDown_noEffect() { - for (int i = 0; i < SelfRecovery.MAX_RESTARTS_IN_TIME_WINDOW * 2; i++) { + for (int i = 0; i < DEFAULT_MAX_RECOVERY_PER_HOUR * 2; i++) { mSelfRecovery.trigger(SelfRecovery.REASON_STA_IFACE_DOWN); verify(mActiveModeWarden).recoveryDisableWifi(); verify(mActiveModeWarden, never()).recoveryRestartWifi(anyInt()); diff --git a/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java index 30c171f20..a2a1a4595 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java @@ -1020,7 +1020,7 @@ public class WifiBackupRestoreTest extends WifiBaseTest { @Test public void testRestoreFromV1_2BackupData() { List<WifiConfiguration> configurations = new ArrayList<>(); - configurations.add(createNetworkForConfigurationWithV1_1Data()); + configurations.add(createNetworkForConfigurationWithV1_2Data()); byte[] backupData = WIFI_BACKUP_DATA_V1_2.getBytes(); List<WifiConfiguration> retrievedConfigurations = |