diff options
-rw-r--r-- | service/java/com/android/server/wifi/WifiConfigManager.java | 60 | ||||
-rw-r--r-- | tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java | 65 |
2 files changed, 123 insertions, 2 deletions
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index 4b622bf31..1fdabfa07 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -61,6 +61,7 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.BitSet; import java.util.Calendar; import java.util.Collection; @@ -212,6 +213,12 @@ public class WifiConfigManager { * Maximum age of scan results that can be used for averaging out RSSI value. */ private static final int SCAN_RESULT_MAXIMUM_AGE_MS = 40000; + + /** + * Maximum age of frequencies last seen to be included in pno scans. (30 days) + */ + @VisibleForTesting + public static final long MAX_PNO_SCAN_FREQUENCY_AGE_MS = (long) 1000 * 3600 * 24 * 30; /** * General sorting algorithm of all networks for scanning purposes: * Place the configurations in descending order of their |numAssociation| values. If networks @@ -278,6 +285,7 @@ public class WifiConfigManager { * Number of channels to scan for during partial scans initiated while connected. */ private final int mMaxNumActiveChannelsForPartialScans; + /** * Verbose logging flag. Toggled by developer options. */ @@ -374,7 +382,6 @@ public class WifiConfigManager { R.bool.config_wifi_only_link_same_credential_configurations); mMaxNumActiveChannelsForPartialScans = mContext.getResources().getInteger( R.integer.config_wifi_framework_associated_partial_scan_max_num_active_channels); - try { mSystemUiUid = mContext.getPackageManager().getPackageUidAsUser(SYSUI_PACKAGE_NAME, PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM); @@ -2358,6 +2365,42 @@ public class WifiConfigManager { } /** + * Retrieve a set of channels on which AP's for the provided network was seen using the + * internal ScanResult's cache {@link #mScanDetailCaches}. This is used to reduced the list + * of frequencies for pno scans. + * + * @param networkId network ID corresponding to the network. + * @param ageInMillis only consider scan details whose timestamps are earlier than this. + * @return Set containing the frequencies on which this network was found, null if the network + * was not found or there are no associated scan details in the cache. + */ + private Set<Integer> fetchChannelSetForNetworkForPnoScan(int networkId, long ageInMillis) { + WifiConfiguration config = getInternalConfiguredNetwork(networkId); + if (config == null) { + return null; + } + ScanDetailCache scanDetailCache = getScanDetailCacheForNetwork(networkId); + if (scanDetailCache == null) { + return null; + } + if (mVerboseLoggingEnabled) { + Log.v(TAG, new StringBuilder("fetchChannelSetForNetworkForPnoScan ageInMillis ") + .append(ageInMillis) + .append(" for ") + .append(config.configKey()) + .append(" bssids " + scanDetailCache.size()) + .toString()); + } + Set<Integer> channelSet = new HashSet<>(); + long nowInMillis = mClock.getWallClockMillis(); + + // Add channels for the network to the output. + addToChannelSetForNetworkFromScanDetailCache(channelSet, scanDetailCache, nowInMillis, + ageInMillis, Integer.MAX_VALUE); + return channelSet; + } + + /** * Retrieves a list of all the saved networks before enabling disconnected/connected PNO. * * PNO network list sent to the firmware has limited size. If there are a lot of saved @@ -2384,7 +2427,20 @@ public class WifiConfigManager { Collections.sort(networks, sScanListComparator); // The most frequently connected network has the highest priority now. for (WifiConfiguration config : networks) { - pnoList.add(WifiConfigurationUtil.createPnoNetwork(config)); + WifiScanner.PnoSettings.PnoNetwork pnoNetwork = + WifiConfigurationUtil.createPnoNetwork(config); + Set<Integer> channelSet = fetchChannelSetForNetworkForPnoScan(config.networkId, + MAX_PNO_SCAN_FREQUENCY_AGE_MS); + if (channelSet != null) { + pnoNetwork.frequencies = channelSet.stream() + .mapToInt(Integer::intValue) + .toArray(); + } + pnoList.add(pnoNetwork); + if (mVerboseLoggingEnabled) { + Log.v(TAG, "retrievePnoNetworkList " + pnoNetwork.ssid + ":" + + Arrays.toString(pnoNetwork.frequencies)); + } } return pnoList; } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java index 40f9f459d..05d79ed65 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java @@ -97,6 +97,10 @@ public class WifiConfigManagerTest { private static final int TEST_STATIC_PROXY_PORT_2 = 3000; private static final String TEST_STATIC_PROXY_EXCLUSION_LIST_2 = ""; private static final String TEST_PAC_PROXY_LOCATION_2 = "http://blah"; + private static final int TEST_RSSI = -50; + private static final int TEST_FREQUENCY_1 = 2412; + private static final int TEST_FREQUENCY_2 = 5180; + private static final int TEST_FREQUENCY_3 = 5240; @Mock private Context mContext; @Mock private Clock mClock; @@ -1597,6 +1601,67 @@ public class WifiConfigManagerTest { } /** + * Verifies frequencies are populated correctly for pno networks. + * {@link WifiConfigManager#retrievePnoNetworkList()}. + */ + @Test + public void testRetrievePnoListFrequencies() { + // Create and add 3 networks. + WifiConfiguration network1 = WifiConfigurationTestUtil.createEapNetwork(); + WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); + verifyAddNetworkToWifiConfigManager(network1); + verifyAddNetworkToWifiConfigManager(network2); + + // Enable all of them. + assertTrue(mWifiConfigManager.enableNetwork(network1.networkId, false, TEST_CREATOR_UID)); + assertTrue(mWifiConfigManager.enableNetwork(network2.networkId, false, TEST_CREATOR_UID)); + assertTrue(mWifiConfigManager.updateNetworkAfterConnect(network1.networkId)); + + // Retrieve the Pno network list & verify the order of the networks returned. + // Frequencies should be empty since no scan results have been received yet. + List<WifiScanner.PnoSettings.PnoNetwork> pnoNetworks = + mWifiConfigManager.retrievePnoNetworkList(); + assertEquals(2, pnoNetworks.size()); + assertEquals(network1.SSID, pnoNetworks.get(0).ssid); + assertEquals(network2.SSID, pnoNetworks.get(1).ssid); + assertTrue("frequencies should be empty", pnoNetworks.get(0).frequencies.length == 0); + assertTrue("frequencies should be empty", pnoNetworks.get(1).frequencies.length == 0); + + // Add frequencies to |network1| + ScanDetail scanDetail1 = createScanDetailForNetwork(network1, TEST_BSSID + "1", + TEST_RSSI, TEST_FREQUENCY_1); + ScanDetail scanDetail2 = createScanDetailForNetwork(network1, TEST_BSSID + "2", + TEST_RSSI, TEST_FREQUENCY_1); + ScanDetail scanDetail3 = createScanDetailForNetwork(network1, TEST_BSSID + "3", + TEST_RSSI, TEST_FREQUENCY_2); + ScanDetail scanDetail4 = createScanDetailForNetwork(network1, TEST_BSSID + "4", + TEST_RSSI, TEST_FREQUENCY_3); + + // Set last seen timestamps so that when retrieving the frequencies for |network1| + // |TEST_FREQUENCY_2| gets included but |TEST_FREQUENCY_3| gets excluded. + scanDetail3.getScanResult().seen = + mClock.getWallClockMillis() - WifiConfigManager.MAX_PNO_SCAN_FREQUENCY_AGE_MS + 1; + scanDetail4.getScanResult().seen = + mClock.getWallClockMillis() - WifiConfigManager.MAX_PNO_SCAN_FREQUENCY_AGE_MS; + mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(scanDetail1); + mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(scanDetail2); + mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(scanDetail3); + mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(scanDetail4); + + // Verify the frequencies are correct for |network1| and |TEST_FREQUENCY_3| is not in the + // list because it's older than the max age. + pnoNetworks = mWifiConfigManager.retrievePnoNetworkList(); + assertEquals(2, pnoNetworks.size()); + assertEquals(network1.SSID, pnoNetworks.get(0).ssid); + assertEquals(network2.SSID, pnoNetworks.get(1).ssid); + assertEquals(2, pnoNetworks.get(0).frequencies.length); + Arrays.sort(pnoNetworks.get(0).frequencies); + assertEquals(TEST_FREQUENCY_1, pnoNetworks.get(0).frequencies[0]); + assertEquals(TEST_FREQUENCY_2, pnoNetworks.get(0).frequencies[1]); + assertTrue("frequencies should be empty", pnoNetworks.get(1).frequencies.length == 0); + } + + /** * Verifies that the list of PNO networks does not contain ephemeral or passpoint networks * {@link WifiConfigManager#retrievePnoNetworkList()}. */ |