diff options
author | Nate Jiang <qiangjiang@google.com> | 2020-04-02 20:18:36 -0700 |
---|---|---|
committer | Nate Jiang <qiangjiang@google.com> | 2020-04-17 18:34:46 -0700 |
commit | fecef5b1be05409a5ac666611b8bfdefe7d34a27 (patch) | |
tree | a2770d72f8b1f76b950350f1410c71621175b4bf | |
parent | 63da7f604a87743c33f9d0bcf18a87eb5c8e05ec (diff) |
Add in memory timestamp for channel inside score card
Use the timestamp to age out channel for initial partial scan and PNO
scan. The timestamp is elapsed time since boot.
Bug: 153115968
Test: atest com.android.servre.wifi
Change-Id: Icd1c84ae1c3518f501466377a8f6e4e532f83332
4 files changed, 70 insertions, 50 deletions
diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java index bf774688e..7178a0a5c 100644 --- a/service/java/com/android/server/wifi/WifiConnectivityManager.java +++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java @@ -114,13 +114,15 @@ public class WifiConnectivityManager { // to prevent caveat from things like PNO scan. private static final int WATCHDOG_INTERVAL_MS = 20 * 60 * 1000; // 20 minutes // Restricted channel list age out value. - private static final int CHANNEL_LIST_AGE_MS = 60 * 60 * 1000; // 1 hour + private static final long CHANNEL_LIST_AGE_MS = 60 * 60 * 1000; // 1 hour // This is the time interval for the connection attempt rate calculation. Connection attempt // timestamps beyond this interval is evicted from the list. public static final int MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS = 4 * 60 * 1000; // 4 mins // Max number of connection attempts in the above time interval. public static final int MAX_CONNECTION_ATTEMPTS_RATE = 6; private static final int TEMP_BSSID_BLOCK_DURATION = 10 * 1000; // 10 seconds + // Maximum age of frequencies last seen to be included in pno scans. (30 days) + private static final long MAX_PNO_SCAN_FREQUENCY_AGE_MS = (long) 1000 * 3600 * 24 * 30; // ClientModeImpl has a bunch of states. From the // WifiConnectivityManager's perspective it only cares // if it is in Connected state, Disconnected state or in @@ -975,7 +977,7 @@ public class WifiConnectivityManager { R.integer.config_wifiInitialPartialScanChannelCacheAgeMins); int maxCount = mContext.getResources().getInteger( R.integer.config_wifiInitialPartialScanChannelMaxCount); - freqs = fetchChannelSetForPartialScan(maxCount); + freqs = fetchChannelSetForPartialScan(maxCount, ageInMillis); } else { freqs = fetchChannelSetForNetworkForPartialScan(config.networkId); } @@ -999,14 +1001,16 @@ public class WifiConnectivityManager { * @param channelSet Target set for adding channel to. * @param config Network for query channel from WifiScoreCard * @param maxCount Size limit of the set. If equals to 0, means no limit. + * @param ageInMillis Only consider channel info whose timestamps are younger than this value. * @return True if all available channels for this network are added, otherwise false. */ private boolean addChannelFromWifiScoreCard(@NonNull Set<Integer> channelSet, - @NonNull WifiConfiguration config, int maxCount) { + @NonNull WifiConfiguration config, int maxCount, long ageInMillis) { WifiScoreCard.PerNetwork network = mWifiScoreCard.lookupNetwork(config.SSID); - List<Integer> channelList = network.getFrequencies(); - for (Integer channel : channelList) { + for (Integer channel : network.getFrequencies(ageInMillis)) { if (maxCount > 0 && channelSet.size() >= maxCount) { + localLog("addChannelFromWifiScoreCard: size limit reached for network:" + + config.SSID); return false; } channelSet.add(channel); @@ -1031,7 +1035,8 @@ public class WifiConnectivityManager { channelSet.add(mWifiInfo.getFrequency()); } // Then get channels for the network. - addChannelFromWifiScoreCard(channelSet, config, maxNumActiveChannelsForPartialScans); + addChannelFromWifiScoreCard(channelSet, config, maxNumActiveChannelsForPartialScans, + CHANNEL_LIST_AGE_MS); return channelSet; } @@ -1039,7 +1044,7 @@ public class WifiConnectivityManager { * Fetch channel set for all saved and suggestion non-passpoint network for partial scan. */ @VisibleForTesting - public Set<Integer> fetchChannelSetForPartialScan(int maxCount) { + public Set<Integer> fetchChannelSetForPartialScan(int maxCount, long ageInMillis) { List<WifiConfiguration> networks = getAllScanOptimizationNetworks(); if (networks.isEmpty()) { return null; @@ -1051,7 +1056,7 @@ public class WifiConnectivityManager { Set<Integer> channelSet = new HashSet<>(); for (WifiConfiguration config : networks) { - if (!addChannelFromWifiScoreCard(channelSet, config, maxCount)) { + if (!addChannelFromWifiScoreCard(channelSet, config, maxCount, ageInMillis)) { return channelSet; } } @@ -1430,7 +1435,8 @@ public class WifiConnectivityManager { continue; } Set<Integer> channelList = new HashSet<>(); - addChannelFromWifiScoreCard(channelList, config, 0); + addChannelFromWifiScoreCard(channelList, config, 0, + MAX_PNO_SCAN_FREQUENCY_AGE_MS); pnoNetwork.frequencies = channelList.stream().mapToInt(Integer::intValue).toArray(); localLog("retrievePnoNetworkList " + pnoNetwork.ssid + ":" + Arrays.toString(pnoNetwork.frequencies)); diff --git a/service/java/com/android/server/wifi/WifiScoreCard.java b/service/java/com/android/server/wifi/WifiScoreCard.java index 4f12470e0..fdf7a678b 100644 --- a/service/java/com/android/server/wifi/WifiScoreCard.java +++ b/service/java/com/android/server/wifi/WifiScoreCard.java @@ -40,6 +40,7 @@ import android.util.ArrayMap; import android.util.Base64; import android.util.Log; import android.util.Pair; +import android.util.SparseLongArray; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; @@ -68,6 +69,7 @@ import java.lang.annotation.RetentionPolicy; import java.nio.ByteBuffer; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -803,6 +805,8 @@ public class WifiScoreCard { private NetworkConnectionStats mStatsCurrBuild; private NetworkConnectionStats mStatsPrevBuild; private LruList<Integer> mFrequencyList; + // In memory keep frequency with timestamp last time available, the elapsed time since boot. + private SparseLongArray mFreqTimestamp; PerNetwork(String ssid) { super(computeHashLong(ssid, MacAddress.fromString(DEFAULT_MAC_ADDRESS), mL2KeySeed)); @@ -812,7 +816,8 @@ public class WifiScoreCard { mRecentStats = new NetworkConnectionStats(); mStatsCurrBuild = new NetworkConnectionStats(); mStatsPrevBuild = new NetworkConnectionStats(); - mFrequencyList = new LruList<Integer>(MAX_FREQUENCIES_PER_SSID); + mFrequencyList = new LruList<>(MAX_FREQUENCIES_PER_SSID); + mFreqTimestamp = new SparseLongArray(); } void updateEventStats(Event event, int rssi, int txSpeed, int failureReason) { @@ -923,10 +928,19 @@ public class WifiScoreCard { /** * Retrieve the list of frequencies seen for this network, with the most recent first. - * @return + * @param ageInMills Max age to filter the channels. + * @return a list of frequencies */ - List<Integer> getFrequencies() { - return mFrequencyList.getEntries(); + List<Integer> getFrequencies(Long ageInMills) { + List<Integer> results = new ArrayList<>(); + Long nowInMills = mClock.getElapsedSinceBootMillis(); + for (Integer freq : mFrequencyList.getEntries()) { + if (nowInMills - mFreqTimestamp.get(freq, 0L) > ageInMills) { + continue; + } + results.add(freq); + } + return results; } /** @@ -935,6 +949,7 @@ public class WifiScoreCard { */ void addFrequency(int frequency) { mFrequencyList.add(frequency); + mFreqTimestamp.put(frequency, mClock.getElapsedSinceBootMillis()); } /** diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java index be6ee2622..093abfe50 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java @@ -158,6 +158,8 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { resources.setInteger( R.integer.config_wifiHighMovementNetworkSelectionOptimizationRssiDelta, HIGH_MVMT_RSSI_DELTA); + resources.setInteger(R.integer.config_wifiInitialPartialScanChannelCacheAgeMins, + CHANNEL_CACHE_AGE_MINS); } /** @@ -241,6 +243,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { private static final String TEST_SSID = "SSID"; private static final int TEMP_BSSID_BLOCK_DURATION_MS = 10 * 1000; // 10 seconds private static final int TEST_CONNECTED_NETWORK_ID = 55; + private static final int CHANNEL_CACHE_AGE_MINS = 14400; Context mockContext() { Context context = mock(Context.class); @@ -1783,7 +1786,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { when(mClientModeImpl.getCurrentWifiConfiguration()) .thenReturn(configuration); when(mWifiScoreCard.lookupNetwork(configuration.SSID)).thenReturn(mPerNetwork); - when(mPerNetwork.getFrequencies()).thenReturn(channelList); + when(mPerNetwork.getFrequencies(anyLong())).thenReturn(new ArrayList<>()); doAnswer(new AnswerWithArguments() { public void answer(ScanSettings settings, ScanListener listener, @@ -1848,17 +1851,11 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { R.integer.config_wifi_framework_associated_partial_scan_max_num_active_channels, 10); - final List<Integer> channelList = new ArrayList<>(); - channelList.add(TEST_FREQUENCY_1); - channelList.add(TEST_FREQUENCY_2); - channelList.add(TEST_FREQUENCY_3); WifiConfiguration configuration = WifiConfigurationTestUtil.createOpenNetwork(); configuration.networkId = TEST_CONNECTED_NETWORK_ID; when(mWifiConfigManager.getConfiguredNetwork(TEST_CONNECTED_NETWORK_ID)) .thenReturn(configuration); - when(mWifiScoreCard.lookupNetwork(configuration.SSID)).thenReturn(mPerNetwork); - when(mPerNetwork.getFrequencies()).thenReturn(channelList); - + List<Integer> channelList = linkScoreCardFreqsToNetwork(configuration).get(0); when(mClientModeImpl.getCurrentWifiConfiguration()) .thenReturn(configuration); @@ -1903,16 +1900,11 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { R.integer.config_wifi_framework_associated_partial_scan_max_num_active_channels, 10); - final List<Integer> channelList = new ArrayList<>(); - channelList.add(TEST_FREQUENCY_1); - channelList.add(TEST_FREQUENCY_2); - channelList.add(TEST_FREQUENCY_3); WifiConfiguration configuration = WifiConfigurationTestUtil.createOpenNetwork(); configuration.networkId = TEST_CONNECTED_NETWORK_ID; when(mWifiConfigManager.getConfiguredNetwork(TEST_CONNECTED_NETWORK_ID)) .thenReturn(configuration); - when(mWifiScoreCard.lookupNetwork(configuration.SSID)).thenReturn(mPerNetwork); - when(mPerNetwork.getFrequencies()).thenReturn(channelList); + List<Integer> channelList = linkScoreCardFreqsToNetwork(configuration).get(0); when(mClientModeImpl.getCurrentWifiConfiguration()) .thenReturn(configuration); @@ -1954,16 +1946,11 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { when(mWifiNS.hasSufficientLinkQuality(eq(mWifiInfo))).thenReturn(true); when(mWifiNS.hasInternetOrExpectNoInternet(eq(mWifiInfo))).thenReturn(true); - final List<Integer> channelList = new ArrayList<>(); - channelList.add(TEST_FREQUENCY_1); - channelList.add(TEST_FREQUENCY_2); - channelList.add(TEST_FREQUENCY_3); WifiConfiguration configuration = WifiConfigurationTestUtil.createOpenNetwork(); configuration.networkId = TEST_CONNECTED_NETWORK_ID; when(mWifiConfigManager.getConfiguredNetwork(TEST_CONNECTED_NETWORK_ID)) .thenReturn(configuration); - when(mWifiScoreCard.lookupNetwork(configuration.SSID)).thenReturn(mPerNetwork); - when(mPerNetwork.getFrequencies()).thenReturn(channelList); + List<Integer> channelList = linkScoreCardFreqsToNetwork(configuration).get(0); when(mClientModeImpl.getCurrentWifiConfiguration()) .thenReturn(new WifiConfiguration()); @@ -3024,14 +3011,12 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { assertEquals("frequencies should be empty", 0, pnoNetworks.get(1).frequencies.length); //Set up wifiScoreCard to get frequency. - List<Integer> channelList = new ArrayList<>(); - channelList.add(TEST_FREQUENCY_1); - channelList.add(TEST_FREQUENCY_2); - channelList.add(TEST_FREQUENCY_3); + List<Integer> channelList = Arrays + .asList(TEST_FREQUENCY_1, TEST_FREQUENCY_2, TEST_FREQUENCY_3); when(mWifiScoreCard.lookupNetwork(network1.SSID)).thenReturn(mPerNetwork); when(mWifiScoreCard.lookupNetwork(network2.SSID)).thenReturn(mPerNetwork1); - when(mPerNetwork.getFrequencies()).thenReturn(channelList); - when(mPerNetwork1.getFrequencies()).thenReturn(new ArrayList<>()); + when(mPerNetwork.getFrequencies(anyLong())).thenReturn(channelList); + when(mPerNetwork1.getFrequencies(anyLong())).thenReturn(new ArrayList<>()); //Set config_wifiPnoFrequencyCullingEnabled false, should ignore get frequency. mResources.setBoolean(R.bool.config_wifiPnoFrequencyCullingEnabled, false); @@ -3042,7 +3027,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { assertEquals("frequencies should be empty", 0, pnoNetworks.get(0).frequencies.length); assertEquals("frequencies should be empty", 0, pnoNetworks.get(1).frequencies.length); - ////Set config_wifiPnoFrequencyCullingEnabled false, should get the right frequency. + // Set config_wifiPnoFrequencyCullingEnabled false, should get the right frequency. mResources.setBoolean(R.bool.config_wifiPnoFrequencyCullingEnabled, true); pnoNetworks = mWifiConnectivityManager.retrievePnoNetworkList(); assertEquals(2, pnoNetworks.size()); @@ -3087,13 +3072,11 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { List<List<Integer>> results = new ArrayList<>(); int i = 0; for (WifiConfiguration config : configs) { - List<Integer> channelList = new ArrayList<>(); - channelList.add(TEST_FREQUENCY_1 + i); - channelList.add(TEST_FREQUENCY_2 + i); - channelList.add(TEST_FREQUENCY_3 + i); + List<Integer> channelList = Arrays.asList(TEST_FREQUENCY_1 + i, TEST_FREQUENCY_2 + i, + TEST_FREQUENCY_3 + i); WifiScoreCard.PerNetwork perNetwork = mock(WifiScoreCard.PerNetwork.class); when(mWifiScoreCard.lookupNetwork(config.SSID)).thenReturn(perNetwork); - when(perNetwork.getFrequencies()).thenReturn(channelList); + when(perNetwork.getFrequencies(anyLong())).thenReturn(channelList); results.add(channelList); i++; } @@ -3115,8 +3098,8 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mLruConnectionTracker.addNetwork(configuration2); mLruConnectionTracker.addNetwork(configuration1); - assertEquals(new HashSet<>(freqs.get(0)), - mWifiConnectivityManager.fetchChannelSetForPartialScan(3)); + assertEquals(new HashSet<>(freqs.get(0)), mWifiConnectivityManager + .fetchChannelSetForPartialScan(3, CHANNEL_CACHE_AGE_MINS)); } /** diff --git a/tests/wifitests/src/com/android/server/wifi/WifiScoreCardTest.java b/tests/wifitests/src/com/android/server/wifi/WifiScoreCardTest.java index 498b18d53..3fc62609a 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiScoreCardTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiScoreCardTest.java @@ -66,6 +66,7 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Arrays; import java.util.List; + /** * Unit tests for {@link com.android.server.wifi.WifiScoreCard}. */ @@ -472,10 +473,9 @@ public class WifiScoreCardTest extends WifiBaseTest { assertEquals(diag, 0, dailyStats.getCount(CNT_ASSOCIATION_REJECTION)); assertEquals(diag, 0, dailyStats.getCount(CNT_ASSOCIATION_TIMEOUT)); assertEquals(diag, 0, dailyStats.getCount(CNT_AUTHENTICATION_FAILURE)); - List<Integer> frequencies = perNetwork.getFrequencies(); + List<Integer> frequencies = perNetwork.getFrequencies(Long.MAX_VALUE); assertEquals(diag, 2, frequencies.size()); - List<Integer> expectedFrequencies = - new ArrayList<>(Arrays.asList(new Integer[] {2432, 5805})); + List<Integer> expectedFrequencies = new ArrayList<>(Arrays.asList(2432, 5805)); assertEquals(diag, expectedFrequencies, frequencies); } @@ -1253,4 +1253,20 @@ public class WifiScoreCardTest extends WifiBaseTest { assertEquals(WifiHealthMonitor.REASON_AUTH_FAILURE, mWifiScoreCard.detectAbnormalConnectionFailure(mWifiInfo.getSSID())); } + + @Test + public void testAddGetFrequencies() { + mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); + PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); + millisecondsPass(100); + perNetwork.addFrequency(5805); + millisecondsPass(1000); + perNetwork.addFrequency(2432); + assertEquals(2, perNetwork.getFrequencies(Long.MAX_VALUE).size()); + assertEquals(2432, (int) perNetwork.getFrequencies(Long.MAX_VALUE).get(0)); + assertEquals(5805, (int) perNetwork.getFrequencies(Long.MAX_VALUE).get(1)); + // Check over aged channel will not return. + assertEquals(1, perNetwork.getFrequencies(900L).size()); + assertEquals(2432, (int) perNetwork.getFrequencies(Long.MAX_VALUE).get(0)); + } } |