Change single scan schedule for single saved network
This commit allows the OEM to use a differnet single scan schedule
when screen is on and device is connected to the only saved network.
Bug: 140596420
Test: atest com.android.server.wifi
Change-Id: I4de216783653b2933b69dcf6e708a05f5ab3a9f4
diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java
index 575a410..d203edf 100644
--- a/service/java/com/android/server/wifi/WifiConnectivityManager.java
+++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java
@@ -164,6 +164,7 @@
private static final int[] DEFAULT_SCANNING_SCHEDULE = {20, 40, 80, 160};
private int[] mConnectedSingleScanSchedule;
private int[] mDisconnectedSingleScanSchedule;
+ private int[] mConnectedSingleSavedNetworkSingleScanSchedule;
private final Object mLock = new Object();
@@ -518,32 +519,38 @@
WifiConfigManager.OnNetworkUpdateListener {
@Override
public void onNetworkAdded(WifiConfiguration config) {
- updatePnoScan();
+ updateScan();
}
@Override
public void onNetworkEnabled(WifiConfiguration config) {
- updatePnoScan();
+ updateScan();
}
@Override
public void onNetworkRemoved(WifiConfiguration config) {
- updatePnoScan();
+ updateScan();
}
@Override
public void onNetworkUpdated(WifiConfiguration config) {
- updatePnoScan();
+ updateScan();
}
@Override
public void onNetworkTemporarilyDisabled(WifiConfiguration config, int disableReason) { }
@Override
public void onNetworkPermanentlyDisabled(WifiConfiguration config, int disableReason) {
- updatePnoScan();
+ updateScan();
}
- private void updatePnoScan() {
- // Update the PNO scan network list when screen is off. Here we
- // rely on startConnectivityScan() to perform all the checks and clean up.
- if (!mScreenOn) {
- localLog("Saved networks updated");
+ private void updateScan() {
+ if (mScreenOn) {
+ // Update scanning schedule if needed
+ if (updateSingleScanningSchedule()) {
+ localLog("Saved networks updated impacting single scan schedule");
+ startConnectivityScan(false);
+ }
+ } else {
+ // Update the PNO scan network list when screen is off. Here we
+ // rely on startConnectivityScan() to perform all the checks and clean up.
+ localLog("Saved networks updated impacting pno scan");
startConnectivityScan(false);
}
}
@@ -585,14 +592,14 @@
}
/** Initialize single scanning schedules, and validate them */
- private int[] initializeScanningSchedule(Context context, int state) {
+ private int[] initializeScanningSchedule(int state) {
int[] schedule;
if (state == WIFI_STATE_CONNECTED) {
- schedule = context.getResources().getIntArray(
+ schedule = mContext.getResources().getIntArray(
R.array.config_wifiConnectedScanIntervalScheduleSec);
} else if (state == WIFI_STATE_DISCONNECTED) {
- schedule = context.getResources().getIntArray(
+ schedule = mContext.getResources().getIntArray(
R.array.config_wifiDisconnectedScanIntervalScheduleSec);
} else {
schedule = null;
@@ -880,6 +887,28 @@
}
}
+ // Update the single scanning schedule if needed, and return true if update occurs
+ private boolean updateSingleScanningSchedule() {
+ if (mWifiState != WIFI_STATE_CONNECTED) {
+ // No need to update the scanning schedule
+ return false;
+ }
+
+ boolean shouldUseSingleSavedNetworkSchedule = useSingleSavedNetworkSchedule();
+
+ if (mCurrentSingleScanSchedule == mConnectedSingleScanSchedule
+ && shouldUseSingleSavedNetworkSchedule) {
+ mCurrentSingleScanSchedule = mConnectedSingleSavedNetworkSingleScanSchedule;
+ return true;
+ }
+ if (mCurrentSingleScanSchedule == mConnectedSingleSavedNetworkSingleScanSchedule
+ && !shouldUseSingleSavedNetworkSchedule) {
+ mCurrentSingleScanSchedule = mConnectedSingleScanSchedule;
+ return true;
+ }
+ return false;
+ }
+
// Reset the last periodic single scan time stamp so that the next periodic single
// scan can start immediately.
private void resetLastPeriodicSingleScanTimeStamp() {
@@ -1166,18 +1195,54 @@
}
/**
+ * Check if Single saved network schedule should be used
+ * This is true if the following is satisfied:
+ * 1. Device is in connected state (this method is only called in this state)
+ * 2. Device has a single saved network
+ * 3. The connected network is the saved network
+ */
+ private boolean useSingleSavedNetworkSchedule() {
+ List<WifiConfiguration> savedNetworks =
+ mConfigManager.getSavedNetworks(Process.WIFI_UID);
+
+ // return true if there is a single saved network which is the currently connected network
+ return (savedNetworks.size() == 1
+ && savedNetworks.get(0).status == WifiConfiguration.Status.CURRENT);
+ }
+
+ private int[] initSingleSavedNetworkSchedule() {
+ int[] schedule = mContext.getResources().getIntArray(
+ R.array.config_wifiSingleSavedNetworkConnectedScanIntervalScheduleSec);
+ if (schedule == null || schedule.length == 0) {
+ return null;
+ }
+
+ for (int val : schedule) {
+ if (val <= 0) {
+ return null;
+ }
+ }
+ return schedule;
+ }
+
+ /**
* Handler for WiFi state (connected/disconnected) changes
*/
public void handleConnectionStateChanged(int state) {
localLog("handleConnectionStateChanged: state=" + stateToString(state));
if (mConnectedSingleScanSchedule == null) {
- mConnectedSingleScanSchedule = initializeScanningSchedule(
- mContext, WIFI_STATE_CONNECTED);
+ mConnectedSingleScanSchedule = initializeScanningSchedule(WIFI_STATE_CONNECTED);
}
if (mDisconnectedSingleScanSchedule == null) {
- mDisconnectedSingleScanSchedule = initializeScanningSchedule(
- mContext, WIFI_STATE_DISCONNECTED);
+ mDisconnectedSingleScanSchedule = initializeScanningSchedule(WIFI_STATE_DISCONNECTED);
+ }
+ if (mConnectedSingleSavedNetworkSingleScanSchedule == null) {
+ mConnectedSingleSavedNetworkSingleScanSchedule =
+ initSingleSavedNetworkSchedule();
+ if (mConnectedSingleSavedNetworkSingleScanSchedule == null) {
+ mConnectedSingleSavedNetworkSingleScanSchedule = mConnectedSingleScanSchedule;
+ }
}
mWifiState = state;
@@ -1191,8 +1256,13 @@
setSingleScanningSchedule(mDisconnectedSingleScanSchedule);
startConnectivityScan(SCAN_IMMEDIATELY);
} else if (mWifiState == WIFI_STATE_CONNECTED) {
- // Switch to connected single scanning schedule
- setSingleScanningSchedule(mConnectedSingleScanSchedule);
+ if (useSingleSavedNetworkSchedule()) {
+ // Switch to Single-Saved-Network connected schedule
+ setSingleScanningSchedule(mConnectedSingleSavedNetworkSingleScanSchedule);
+ } else {
+ // Switch to connected single scanning schedule
+ setSingleScanningSchedule(mConnectedSingleScanSchedule);
+ }
startConnectivityScan(SCAN_ON_SCHEDULE);
} else {
// Intermediate state, no applicable single scanning schedule
diff --git a/service/res/values/config.xml b/service/res/values/config.xml
index 6b92fb0..460dce4 100644
--- a/service/res/values/config.xml
+++ b/service/res/values/config.xml
@@ -299,6 +299,13 @@
<item>160</item>
</integer-array>
+ <!-- Array describing scanning schedule in seconds when device is connected and screen is on
+ and the connected network is the only saved network.
+ When this array is set to an empty array, the noraml connected scan schedule defined
+ in config_wifiConnectedScanIntervalScheduleSec will be used -->
+ <integer-array translatable="false" name="config_wifiSingleSavedNetworkConnectedScanIntervalScheduleSec">
+ </integer-array>
+
<!-- Indicates that hidden networks are to be scanned during scan only mode -->
<bool translatable="false" name="config_wifiScanHiddenNetworksScanOnlyMode">false</bool>
diff --git a/service/res/values/overlayable.xml b/service/res/values/overlayable.xml
index 09ed48b..0bfa508 100644
--- a/service/res/values/overlayable.xml
+++ b/service/res/values/overlayable.xml
@@ -94,6 +94,7 @@
<item type="array" name="config_wifiRssiLevelThresholds" />
<item type="array" name="config_wifiDisconnectedScanIntervalScheduleSec" />
<item type="array" name="config_wifiConnectedScanIntervalScheduleSec" />
+ <item type="array" name="config_wifiSingleSavedNetworkConnectedScanIntervalScheduleSec" />
<item type="bool" name="config_wifiScanHiddenNetworksScanOnlyMode" />
<item type="integer" name="config_wifiHardwareSoftapMaxClientCount" />
<item type="bool" name="config_wifiIsUnusableEventMetricsEnabled" />
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
index 4e6e0a7..a00ec8c 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
@@ -160,8 +160,9 @@
private static final long CURRENT_SYSTEM_TIME_MS = 1000;
private static final int MAX_BSSID_BLACKLIST_SIZE = 16;
private static final int[] VALID_CONNECTED_SINGLE_SCAN_SCHEDULE = {10, 30, 50};
+ private static final int[] VALID_CONNECTED_SINGLE_SAVED_NETWORK_SCHEDULE = {15, 35, 55};
private static final int[] VALID_DISCONNECTED_SINGLE_SCAN_SCHEDULE = {25, 40, 60};
- private static final int[] INVALID_SCHEDULE_EMPTY = {};
+ private static final int[] SCHEDULE_EMPTY = {};
private static final int[] INVALID_SCHEDULE_NEGATIVE_VALUES = {10, -10, 20};
private static final int[] INVALID_SCHEDULE_ZERO_VALUES = {10, 0, 20};
private static final int MAX_SCAN_INTERVAL_IN_SCHEDULE = 60;
@@ -186,6 +187,9 @@
when(resource.getIntArray(
R.array.config_wifiDisconnectedScanIntervalScheduleSec))
.thenReturn(VALID_DISCONNECTED_SINGLE_SCAN_SCHEDULE);
+ when(resource.getIntArray(R.array
+ .config_wifiSingleSavedNetworkConnectedScanIntervalScheduleSec))
+ .thenReturn(SCHEDULE_EMPTY);
return resource;
}
@@ -769,7 +773,7 @@
@Test
public void checkPeriodicScanIntervalWhenDisconnectedWithEmptySchedule() throws Exception {
when(mResource.getIntArray(R.array.config_wifiDisconnectedScanIntervalScheduleSec))
- .thenReturn(INVALID_SCHEDULE_EMPTY);
+ .thenReturn(SCHEDULE_EMPTY);
checkWorkingWithDefaultSchedule();
}
@@ -987,6 +991,133 @@
}
/**
+ * When screen on and single saved network schedule is set
+ * If we have multiple saved networks, the regular connected state scan schedule is used
+ */
+ @Test
+ public void checkScanScheduleForMultipleSavedNetwork() {
+ long currentTimeStamp = CURRENT_SYSTEM_TIME_MS;
+ when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
+
+ // Set screen to ON
+ mWifiConnectivityManager.handleScreenStateChanged(true);
+
+ // Wait for max scanning interval so that any impact triggered
+ // by screen state change can settle
+ currentTimeStamp += MAX_SCAN_INTERVAL_IN_SCHEDULE * 1000;
+ when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
+
+ when(mResource.getIntArray(R.array
+ .config_wifiSingleSavedNetworkConnectedScanIntervalScheduleSec))
+ .thenReturn(VALID_CONNECTED_SINGLE_SAVED_NETWORK_SCHEDULE);
+
+ WifiConfiguration wifiConfiguration1 = new WifiConfiguration();
+ WifiConfiguration wifiConfiguration2 = new WifiConfiguration();
+ wifiConfiguration1.status = WifiConfiguration.Status.CURRENT;
+ List<WifiConfiguration> wifiConfigurationList = new ArrayList<WifiConfiguration>();
+ wifiConfigurationList.add(wifiConfiguration1);
+ wifiConfigurationList.add(wifiConfiguration2);
+ when(mWifiConfigManager.getSavedNetworks(anyInt())).thenReturn(wifiConfigurationList);
+
+ // Set firmware roaming to enabled
+ when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true);
+
+ // Set WiFi to connected state to trigger periodic scan
+ mWifiConnectivityManager.handleConnectionStateChanged(
+ WifiConnectivityManager.WIFI_STATE_CONNECTED);
+
+ // Get the first periodic scan interval
+ long firstIntervalMs = mAlarmManager
+ .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG)
+ - currentTimeStamp;
+ assertEquals(VALID_CONNECTED_SINGLE_SCAN_SCHEDULE[0] * 1000, firstIntervalMs);
+ }
+
+ /**
+ * When screen on and single saved network schedule is set
+ * If we have a single saved network (connected network),
+ * the single-saved-network connected state scan schedule is used
+ */
+ @Test
+ public void checkScanScheduleForSingleSavedNetworkConnected() {
+ long currentTimeStamp = CURRENT_SYSTEM_TIME_MS;
+ when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
+
+ // Set screen to ON
+ mWifiConnectivityManager.handleScreenStateChanged(true);
+
+ // Wait for max scanning interval so that any impact triggered
+ // by screen state change can settle
+ currentTimeStamp += MAX_SCAN_INTERVAL_IN_SCHEDULE * 1000;
+ when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
+
+ when(mResource.getIntArray(R.array
+ .config_wifiSingleSavedNetworkConnectedScanIntervalScheduleSec))
+ .thenReturn(VALID_CONNECTED_SINGLE_SAVED_NETWORK_SCHEDULE);
+
+ WifiConfiguration wifiConfiguration = new WifiConfiguration();
+ wifiConfiguration.status = WifiConfiguration.Status.CURRENT;
+ List<WifiConfiguration> wifiConfigurationList = new ArrayList<WifiConfiguration>();
+ wifiConfigurationList.add(wifiConfiguration);
+ when(mWifiConfigManager.getSavedNetworks(anyInt())).thenReturn(wifiConfigurationList);
+
+ // Set firmware roaming to enabled
+ when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true);
+
+ // Set WiFi to connected state to trigger periodic scan
+ mWifiConnectivityManager.handleConnectionStateChanged(
+ WifiConnectivityManager.WIFI_STATE_CONNECTED);
+
+ // Get the first periodic scan interval
+ long firstIntervalMs = mAlarmManager
+ .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG)
+ - currentTimeStamp;
+ assertEquals(VALID_CONNECTED_SINGLE_SAVED_NETWORK_SCHEDULE[0] * 1000, firstIntervalMs);
+ }
+
+ /**
+ * When screen on and single saved network schedule is set
+ * If we have a single saved network (not connected network),
+ * the regular connected state scan schedule is used
+ */
+ @Test
+ public void checkScanScheduleForSingleSavedNetwork() {
+ long currentTimeStamp = CURRENT_SYSTEM_TIME_MS;
+ when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
+
+ // Set screen to ON
+ mWifiConnectivityManager.handleScreenStateChanged(true);
+
+ // Wait for max scanning interval so that any impact triggered
+ // by screen state change can settle
+ currentTimeStamp += MAX_SCAN_INTERVAL_IN_SCHEDULE * 1000;
+ when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
+
+ when(mResource.getIntArray(R.array
+ .config_wifiSingleSavedNetworkConnectedScanIntervalScheduleSec))
+ .thenReturn(VALID_CONNECTED_SINGLE_SAVED_NETWORK_SCHEDULE);
+
+ // Set firmware roaming to enabled
+ when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true);
+
+ WifiConfiguration wifiConfiguration = new WifiConfiguration();
+ wifiConfiguration.status = WifiConfiguration.Status.ENABLED;
+ List<WifiConfiguration> wifiConfigurationList = new ArrayList<WifiConfiguration>();
+ wifiConfigurationList.add(wifiConfiguration);
+ when(mWifiConfigManager.getSavedNetworks(anyInt())).thenReturn(wifiConfigurationList);
+
+ // Set WiFi to connected state to trigger periodic scan
+ mWifiConnectivityManager.handleConnectionStateChanged(
+ WifiConnectivityManager.WIFI_STATE_CONNECTED);
+
+ // Get the first periodic scan interval
+ long firstIntervalMs = mAlarmManager
+ .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG)
+ - currentTimeStamp;
+ assertEquals(VALID_CONNECTED_SINGLE_SCAN_SCHEDULE[0] * 1000, firstIntervalMs);
+ }
+
+ /**
* When screen on trigger a disconnected state change event then a connected state
* change event back to back to verify that the minium scan interval is enforced.
*