summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2020-04-09 22:32:30 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2020-04-09 22:32:30 +0000
commit66ed6f4c29a78457585afe5d5734ba6035d70e08 (patch)
tree622c23209e2bedf897bf7f30e406c6036596a83e
parentb9e042d647ff9f0249151d774db05d1c44c026f9 (diff)
parent4a6c9ac574b2b801b8babe12291170019a866136 (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
-rw-r--r--service/java/com/android/server/wifi/SelfRecovery.java26
-rw-r--r--service/java/com/android/server/wifi/WifiInjector.java2
-rw-r--r--service/java/com/android/server/wifi/WifiShellCommand.java46
-rw-r--r--service/res/values/config.xml5
-rw-r--r--service/res/values/overlayable.xml1
-rw-r--r--tests/wifitests/src/com/android/server/wifi/SelfRecoveryTest.java69
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java2
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 =