diff options
author | Oscar Shu <xshu@google.com> | 2020-02-27 01:44:08 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-02-27 01:44:08 +0000 |
commit | 2d7d6154fd751d28114cc63af2af6963b125dc75 (patch) | |
tree | 7b67844e25c5163878e50a309db6cf3424e232a1 | |
parent | dd457ab2f2f359415e4ea0893a4b09136ece8223 (diff) | |
parent | 560f74b8c633834ad952a44a2a650ad63b618f83 (diff) |
Merge changes from topic "duplicateScansHighMovement-rvc-dev" into rvc-dev
* changes:
High movement - trigger delayed partial scan
Re-trigger scan to confirm network in HIGH_MVMT
8 files changed, 472 insertions, 97 deletions
diff --git a/service/java/com/android/server/wifi/WifiCandidates.java b/service/java/com/android/server/wifi/WifiCandidates.java index 8879dce5f..d62ef00ca 100644 --- a/service/java/com/android/server/wifi/WifiCandidates.java +++ b/service/java/com/android/server/wifi/WifiCandidates.java @@ -30,9 +30,12 @@ import com.android.wifi.resources.R; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.StringJoiner; +import java.util.stream.Collectors; /** * Candidates for network selection @@ -40,10 +43,19 @@ import java.util.StringJoiner; public class WifiCandidates { private static final String TAG = "WifiCandidates"; - WifiCandidates(@NonNull WifiScoreCard wifiScoreCard, @NonNull Context context) { + public WifiCandidates(@NonNull WifiScoreCard wifiScoreCard, @NonNull Context context) { + this(wifiScoreCard, context, Collections.EMPTY_LIST); + } + + public WifiCandidates(@NonNull WifiScoreCard wifiScoreCard, @NonNull Context context, + @NonNull List<Candidate> candidates) { mWifiScoreCard = Preconditions.checkNotNull(wifiScoreCard); mContext = context; + for (Candidate c : candidates) { + mCandidates.put(c.getKey(), c); + } } + private final WifiScoreCard mWifiScoreCard; private final Context mContext; @@ -356,7 +368,7 @@ public class WifiCandidates { } } - private final Map<Key, CandidateImpl> mCandidates = new ArrayMap<>(); + private final Map<Key, Candidate> mCandidates = new ArrayMap<>(); private int mCurrentNetworkId = -1; @Nullable private MacAddress mCurrentBssid = null; @@ -420,10 +432,10 @@ public class WifiCandidates { double lastSelectionWeightBetweenZeroAndOne, boolean isMetered, int predictedThroughputMbps) { - CandidateImpl old = mCandidates.get(key); + Candidate old = mCandidates.get(key); if (old != null) { // check if we want to replace this old candidate - if (nominatorId > old.mNominatorId) return false; + if (nominatorId > old.getNominatorId()) return false; remove(old); } WifiScoreCard.PerBssid perBssid = mWifiScoreCard.lookupBssid( @@ -495,7 +507,7 @@ public class WifiCandidates { */ public Collection<Collection<Candidate>> getGroupedCandidates() { Map<Integer, Collection<Candidate>> candidatesForNetworkId = new ArrayMap<>(); - for (CandidateImpl candidate : mCandidates.values()) { + for (Candidate candidate : mCandidates.values()) { Collection<Candidate> cc = candidatesForNetworkId.get(candidate.getNetworkConfigId()); if (cc == null) { cc = new ArrayList<>(2); // Guess 2 bssids per network @@ -507,6 +519,14 @@ public class WifiCandidates { } /** + * Return a copy of the Candidates. + */ + public List<Candidate> getCandidates() { + return mCandidates.entrySet().stream().map(entry -> entry.getValue()) + .collect(Collectors.toList()); + } + + /** * Make a choice from among the candidates, using the provided scorer. * * @return the chosen scored candidate, or ScoredCandidate.NONE. diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java index 14abdfe99..86cf26698 100644 --- a/service/java/com/android/server/wifi/WifiConnectivityManager.java +++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java @@ -34,6 +34,7 @@ import android.os.Handler; import android.os.HandlerExecutor; import android.os.Process; import android.os.WorkSource; +import android.util.ArrayMap; import android.util.LocalLog; import android.util.Log; @@ -52,7 +53,9 @@ import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; /** * This class manages all the connectivity related scanning activities. @@ -71,6 +74,8 @@ public class WifiConnectivityManager { "WifiConnectivityManager Restart Single Scan"; public static final String RESTART_CONNECTIVITY_SCAN_TIMER_TAG = "WifiConnectivityManager Restart Scan"; + public static final String DELAYED_PARTIAL_SCAN_TIMER_TAG = + "WifiConnectivityManager Schedule Delayed Partial Scan Timer"; private static final long RESET_TIME_STAMP = Long.MIN_VALUE; // Constants to indicate whether a scan should start immediately or @@ -130,6 +135,8 @@ public class WifiConnectivityManager { // Log tag for this class private static final String TAG = "WifiConnectivityManager"; + private static final String ALL_SINGLE_SCAN_LISTENER = "AllSingleScanListener"; + private static final String PNO_SCAN_LISTENER = "PnoScanListener"; private final Context mContext; private final ClientModeImpl mStateMachine; @@ -168,6 +175,7 @@ public class WifiConnectivityManager { private long mLastPeriodicSingleScanTimeStamp = RESET_TIME_STAMP; private boolean mPnoScanStarted = false; private boolean mPeriodicScanTimerSet = false; + private boolean mDelayedPartialScanTimerSet = false; // Device configs private boolean mWaitForFullBandScanResults = false; @@ -186,6 +194,11 @@ public class WifiConnectivityManager { private int mCurrentSingleScanScheduleIndex; private int mPnoScanIntervalMs; private WifiChannelUtilization mWifiChannelUtilization; + // Cached WifiCandidates used in high mobility state to avoid connecting to APs that are + // moving relative to the user. + private CachedWifiCandidates mCachedWifiCandidates = null; + private @DeviceMobilityState int mDeviceMobilityState = + WifiManager.DEVICE_MOBILITY_STATE_UNKNOWN; // A helper to log debugging information in the local log buffer, which can // be retrieved in bugreport. @@ -235,6 +248,33 @@ public class WifiConnectivityManager { } }; + private final AlarmManager.OnAlarmListener mDelayedPartialScanTimerListener = + new AlarmManager.OnAlarmListener() { + public void onAlarm() { + if (mCachedWifiCandidates == null + || mCachedWifiCandidates.frequencies == null + || mCachedWifiCandidates.frequencies.size() == 0) { + return; + } + ScanSettings settings = new ScanSettings(); + settings.type = WifiScanner.SCAN_TYPE_HIGH_ACCURACY; + settings.band = getScanBand(false); + settings.reportEvents = WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT + | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN; + settings.numBssidsPerScan = 0; + int index = 0; + settings.channels = + new WifiScanner.ChannelSpec[mCachedWifiCandidates.frequencies.size()]; + for (Integer freq : mCachedWifiCandidates.frequencies) { + settings.channels[index++] = new WifiScanner.ChannelSpec(freq); + } + SingleScanListener singleScanListener = new SingleScanListener(false); + mScanner.startScan(settings, new HandlerExecutor(mEventHandler), + singleScanListener, WIFI_WORK_SOURCE); + mWifiMetrics.incrementConnectivityOneshotScanCount(); + } + }; + /** * Handles 'onResult' callbacks for the Periodic, Single & Pno ScanListener. * Executes selection of potential network candidates, initiation of connection attempt to that @@ -243,7 +283,8 @@ public class WifiConnectivityManager { * @return true - if a candidate is selected by WifiNetworkSelector * false - if no candidate is selected by WifiNetworkSelector */ - private boolean handleScanResults(List<ScanDetail> scanDetails, String listenerName) { + private boolean handleScanResults(List<ScanDetail> scanDetails, String listenerName, + boolean isFullScan) { mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization( mStateMachine.getWifiLinkLayerStats(), WifiChannelUtilization.UNKNOWN_FREQ); @@ -259,10 +300,17 @@ public class WifiConnectivityManager { localLog(listenerName + " onResults: start network selection"); - WifiConfiguration candidate = - mNetworkSelector.selectNetwork(scanDetails, bssidBlocklist, mWifiInfo, - mStateMachine.isConnected(), mStateMachine.isDisconnected(), - mUntrustedConnectionAllowed); + List<WifiCandidates.Candidate> candidates = mNetworkSelector.getCandidatesFromScan( + scanDetails, bssidBlocklist, mWifiInfo, mStateMachine.isConnected(), + mStateMachine.isDisconnected(), mUntrustedConnectionAllowed); + + if (mDeviceMobilityState == WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT + && mContext.getResources().getBoolean( + R.bool.config_wifiHighMovementNetworkSelectionOptimizationEnabled)) { + candidates = filterCandidatesHighMovement(candidates, listenerName, isFullScan); + } + + WifiConfiguration candidate = mNetworkSelector.selectNetwork(candidates); mWifiLastResortWatchdog.updateAvailableNetworks( mNetworkSelector.getConnectableScanDetails()); mWifiMetrics.countScanResults(scanDetails); @@ -279,6 +327,57 @@ public class WifiConnectivityManager { } } + private List<WifiCandidates.Candidate> filterCandidatesHighMovement( + List<WifiCandidates.Candidate> candidates, String listenerName, boolean isFullScan) { + boolean isNotPartialScan = isFullScan || listenerName.equals(PNO_SCAN_LISTENER); + if (candidates == null || candidates.isEmpty()) { + // No connectable networks nearby or network selection is unnecessary + if (isNotPartialScan) { + mCachedWifiCandidates = new CachedWifiCandidates(mClock.getElapsedSinceBootMillis(), + null); + } + return null; + } + + long minimumTimeBetweenScansMs = mContext.getResources().getInteger( + R.integer.config_wifiHighMovementNetworkSelectionOptimizationScanDelayMs); + if (mCachedWifiCandidates != null && mCachedWifiCandidates.candidateRssiMap != null) { + // cached candidates are too recent, wait for next scan + if (mClock.getElapsedSinceBootMillis() - mCachedWifiCandidates.timeSinceBootMs + < minimumTimeBetweenScansMs) { + return null; + } + + int rssiDelta = mContext.getResources().getInteger(R.integer + .config_wifiHighMovementNetworkSelectionOptimizationRssiDelta); + List<WifiCandidates.Candidate> filteredCandidates = candidates.stream().filter( + item -> mCachedWifiCandidates.candidateRssiMap.containsKey(item.getKey()) + && Math.abs(mCachedWifiCandidates.candidateRssiMap.get(item.getKey()) + - item.getScanRssi()) < rssiDelta) + .collect(Collectors.toList()); + + if (!filteredCandidates.isEmpty()) { + if (isNotPartialScan) { + mCachedWifiCandidates = + new CachedWifiCandidates(mClock.getElapsedSinceBootMillis(), + candidates); + } + return filteredCandidates; + } + } + + // Either no cached candidates, or all candidates got filtered out. + // Update the cached candidates here and schedule a delayed partial scan. + if (isNotPartialScan) { + mCachedWifiCandidates = new CachedWifiCandidates(mClock.getElapsedSinceBootMillis(), + candidates); + localLog("Found " + candidates.size() + " candidates at high mobility state. " + + "Re-doing scan to confirm network quality."); + scheduleDelayedPartialScan(minimumTimeBetweenScansMs); + } + return null; + } + /** * Set whether bluetooth is in the connected state */ @@ -286,6 +385,27 @@ public class WifiConnectivityManager { mNetworkSelector.setBluetoothConnected(isBluetoothConnected); } + private class CachedWifiCandidates { + public final long timeSinceBootMs; + public final Map<WifiCandidates.Key, Integer> candidateRssiMap; + public final Set<Integer> frequencies; + + CachedWifiCandidates(long timeSinceBootMs, List<WifiCandidates.Candidate> candidates) { + this.timeSinceBootMs = timeSinceBootMs; + if (candidates == null) { + this.candidateRssiMap = null; + this.frequencies = null; + } else { + this.candidateRssiMap = new ArrayMap<WifiCandidates.Key, Integer>(); + this.frequencies = new HashSet<Integer>(); + for (WifiCandidates.Candidate c : candidates) { + candidateRssiMap.put(c.getKey(), c.getScanRssi()); + frequencies.add(c.getFrequency()); + } + } + } + } + // All single scan results listener. // // Note: This is the listener for all the available single scan results, @@ -344,7 +464,8 @@ public class WifiConnectivityManager { Log.i(TAG, "Number of scan results ignored due to single radio chain scan: " + mNumScanResultsIgnoredDueToSingleRadioChain); } - boolean wasConnectAttempted = handleScanResults(mScanDetails, "AllSingleScanListener"); + boolean wasConnectAttempted = handleScanResults(mScanDetails, + ALL_SINGLE_SCAN_LISTENER, isFullBandScanResults); clearScanDetails(); // Update metrics to see if a single scan detected a valid network @@ -521,7 +642,7 @@ public class WifiConnectivityManager { } boolean wasConnectAttempted; - wasConnectAttempted = handleScanResults(mScanDetails, "PnoScanListener"); + wasConnectAttempted = handleScanResults(mScanDetails, PNO_SCAN_LISTENER, false); clearScanDetails(); mScanRestartCount = 0; @@ -1057,6 +1178,8 @@ public class WifiConnectivityManager { * @param newState the new device mobility state */ public void setDeviceMobilityState(@DeviceMobilityState int newState) { + mDeviceMobilityState = newState; + localLog("Device mobility state changed. state=" + newState); mWifiChannelUtilization.setDeviceMobilityState(newState); int newPnoScanIntervalMs = deviceMobilityStateToPnoScanIntervalMs(newState); if (newPnoScanIntervalMs < 0) { @@ -1202,6 +1325,22 @@ public class WifiConnectivityManager { mWatchdogListener, mEventHandler); } + // Schedules a delayed partial scan, which will scan the frequencies in mCachedWifiCandidates. + private void scheduleDelayedPartialScan(long delayMillis) { + mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, + mClock.getElapsedSinceBootMillis() + delayMillis, DELAYED_PARTIAL_SCAN_TIMER_TAG, + mDelayedPartialScanTimerListener, mEventHandler); + mDelayedPartialScanTimerSet = true; + } + + // Cancel the delayed partial scan timer. + private void cancelDelayedPartialScan() { + if (mDelayedPartialScanTimerSet) { + mAlarmManager.cancel(mDelayedPartialScanTimerListener); + mDelayedPartialScanTimerSet = false; + } + } + // Set up periodic scan timer private void schedulePeriodicScanTimer(int intervalMs) { mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, @@ -1281,6 +1420,7 @@ public class WifiConnectivityManager { // Due to b/28020168, timer based single scan will be scheduled // to provide periodic scan in an exponential backoff fashion. cancelPeriodicScanTimer(); + cancelDelayedPartialScan(); stopPnoScan(); mScanRestartCount = 0; } diff --git a/service/java/com/android/server/wifi/WifiNetworkSelector.java b/service/java/com/android/server/wifi/WifiNetworkSelector.java index dc8ac7843..60f79896b 100644 --- a/service/java/com/android/server/wifi/WifiNetworkSelector.java +++ b/service/java/com/android/server/wifi/WifiNetworkSelector.java @@ -662,6 +662,7 @@ public class WifiNetworkSelector { return candidate; } + /** * Cleans up state that should go away when wifi is disabled. */ @@ -670,7 +671,7 @@ public class WifiNetworkSelector { } /** - * Select the best network from the ones in range. Scan detail cache is also updated here. + * Returns the list of Candidates from networks in range. * * @param scanDetails List of ScanDetail for all the APs in range * @param bssidBlacklist Blacklisted BSSIDs @@ -678,11 +679,10 @@ public class WifiNetworkSelector { * @param connected True if the device is connected * @param disconnected True if the device is disconnected * @param untrustedNetworkAllowed True if untrusted networks are allowed for connection - * @return Configuration of the selected network, or Null if nothing + * @return list of valid Candidate(s) */ - @Nullable - public WifiConfiguration selectNetwork(List<ScanDetail> scanDetails, - Set<String> bssidBlacklist, WifiInfo wifiInfo, + public List<WifiCandidates.Candidate> getCandidatesFromScan( + List<ScanDetail> scanDetails, Set<String> bssidBlacklist, WifiInfo wifiInfo, boolean connected, boolean disconnected, boolean untrustedNetworkAllowed) { mFilteredNetworks.clear(); mConnectableNetworks.clear(); @@ -770,18 +770,31 @@ public class WifiNetworkSelector { } }); } - if (mConnectableNetworks.size() != wifiCandidates.size()) { localLog("Connectable: " + mConnectableNetworks.size() + " Candidates: " + wifiCandidates.size()); } + return wifiCandidates.getCandidates(); + } + + /** + * Using the registered Scorers, choose the best network from the list of Candidate(s). + * The ScanDetailCache is also updated here. + * @param candidates - Candidates to perferm network selection on. + * @return WifiConfiguration - the selected network, or null. + */ + @NonNull + public WifiConfiguration selectNetwork(List<WifiCandidates.Candidate> candidates) { + if (candidates == null || candidates.size() == 0) { + return null; + } + WifiCandidates wifiCandidates = new WifiCandidates(mWifiScoreCard, mContext, candidates); final WifiCandidates.CandidateScorer activeScorer = getActiveCandidateScorer(); // Update the NetworkSelectionStatus in the configs for the current candidates // This is needed for the legacy user connect choice, at least Collection<Collection<WifiCandidates.Candidate>> groupedCandidates = wifiCandidates.getGroupedCandidates(); for (Collection<WifiCandidates.Candidate> group : groupedCandidates) { - WifiCandidates.ScoredCandidate choice = activeScorer.scoreCandidates(group); if (choice == null) continue; ScanDetail scanDetail = getScanDetailForCandidateKey(choice.candidateKey); diff --git a/service/res/values/config.xml b/service/res/values/config.xml index fbab4df31..31156f359 100644 --- a/service/res/values/config.xml +++ b/service/res/values/config.xml @@ -369,6 +369,18 @@ <!-- Suspend optimization. --> <bool translatable="false" name="config_wifiSuspendOptimizationsEnabled">true</bool> + <!-- Network selection optimization at DEVICE_MOBILITY_STATE_HIGH_MVMT --> + <bool translatable="false" name="config_wifiHighMovementNetworkSelectionOptimizationEnabled">true</bool> + + <!-- Duration for the delayed scan used to verify access points are staying relatively stationary + to the device at high mobility state. (default = 10 seconds) --> + <integer translatable="false" name="config_wifiHighMovementNetworkSelectionOptimizationScanDelayMs">10000</integer> + + <!-- When config_wifiHighMovementNetworkSelectionOptimizationEnabled is true, BSSIDs with RSSI + from 2 consecutive scans that differ in either direction by more than this threshold will be + filtered out from network selection. (default = 10 dBs) --> + <integer translatable="false" name="config_wifiHighMovementNetworkSelectionOptimizationRssiDelta">10</integer> + <!-- The interval in milliseconds at which wifi rtt ranging requests will be throttled when they are coming from the background apps (default = 30 mins). --> <integer translatable="false" name="config_wifiRttBackgroundExecGapMs">1800000</integer> diff --git a/service/res/values/overlayable.xml b/service/res/values/overlayable.xml index 1aa8f12bc..b1c06a1e9 100644 --- a/service/res/values/overlayable.xml +++ b/service/res/values/overlayable.xml @@ -117,6 +117,9 @@ <item type="bool" name="config_wifiPnoFrequencyCullingEnabled" /> <item type="bool" name="config_wifiPnoRecencySortingEnabled" /> <item type="bool" name="config_wifiSuspendOptimizationsEnabled" /> + <item type="bool" name="config_wifiHighMovementNetworkSelectionOptimizationEnabled" /> + <item type="integer" name="config_wifiHighMovementNetworkSelectionOptimizationScanDelayMs" /> + <item type="integer" name="config_wifiHighMovementNetworkSelectionOptimizationRssiDelta" /> <item type="integer" name="config_wifiRttBackgroundExecGapMs" /> <item type="integer" name="config_wifiPollRssiIntervalMilliseconds" /> <item type="bool" name="config_wifiSaeUpgradeEnabled" /> diff --git a/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java b/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java index 9cf47cb74..4b64f71a6 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java @@ -113,6 +113,16 @@ public class WifiCandidatesTest extends WifiBaseTest { } /** + * Test retrieving the list of candidates. + */ + @Test + public void testGetCandidates() { + assertTrue(mWifiCandidates.add(mScanDetail1, mConfig1, 2, 0.0, false, 100)); + assertNotNull(mWifiCandidates.getCandidates()); + assertEquals(1, mWifiCandidates.getCandidates().size()); + } + + /** * Make sure we catch SSID mismatch due to quoting error */ @Test diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java index 2f231519b..3c37cdfee 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java @@ -21,6 +21,7 @@ import static com.android.server.wifi.WifiConfigurationTestUtil.generateWifiConf import static org.junit.Assert.*; import static org.mockito.Mockito.*; +import static org.mockito.Mockito.argThat; import android.app.test.MockAnswerUtil.AnswerWithArguments; import android.app.test.TestAlarmManager; @@ -55,6 +56,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatcher; import org.mockito.Captor; import org.mockito.InOrder; import org.mockito.Mock; @@ -131,6 +133,12 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { resources.setIntArray( R.array.config_wifiSingleSavedNetworkConnectedScanIntervalScheduleSec, SCHEDULE_EMPTY); + resources.setInteger( + R.integer.config_wifiHighMovementNetworkSelectionOptimizationScanDelayMs, + HIGH_MVMT_SCAN_DELAY_MS); + resources.setInteger( + R.integer.config_wifiHighMovementNetworkSelectionOptimizationRssiDelta, + HIGH_MVMT_RSSI_DELTA); } /** @@ -169,7 +177,9 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { @Mock private WifiScoreCard mWifiScoreCard; @Mock private WifiScoreCard.PerNetwork mPerNetwork; @Mock private WifiScoreCard.PerNetwork mPerNetwork1; - + @Mock WifiCandidates.Candidate mCandidate1; + @Mock WifiCandidates.Candidate mCandidate2; + private List<WifiCandidates.Candidate> mCandidateList; @Captor ArgumentCaptor<ScanResult> mCandidateScanResultCaptor; @Captor ArgumentCaptor<ArrayList<String>> mBssidBlacklistCaptor; @Captor ArgumentCaptor<ArrayList<String>> mSsidWhitelistCaptor; @@ -182,6 +192,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { private static final String CANDIDATE_SSID = "\"AnSsid\""; private static final String CANDIDATE_BSSID = "6c:f3:7f:ae:8c:f3"; private static final String INVALID_SCAN_RESULT_BSSID = "6c:f3:7f:ae:8c:f4"; + private static final int TEST_FREQUENCY = 2420; 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}; @@ -196,6 +207,8 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { private static final int TEST_FREQUENCY_1 = 2412; private static final int TEST_FREQUENCY_2 = 5180; private static final int TEST_FREQUENCY_3 = 5240; + private static final int HIGH_MVMT_SCAN_DELAY_MS = 10000; + private static final int HIGH_MVMT_RSSI_DELTA = 10; Context mockContext() { Context context = mock(Context.class); @@ -302,8 +315,25 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { candidate.getNetworkSelectionStatus().setCandidate(candidateScanResult); when(mWifiConfigManager.getConfiguredNetwork(CANDIDATE_NETWORK_ID)).thenReturn(candidate); - when(ns.selectNetwork(anyObject(), anyObject(), anyObject(), anyBoolean(), - anyBoolean(), anyBoolean())).thenReturn(candidate); + WifiCandidates.Key key = mock(WifiCandidates.Key.class); + when(mCandidate1.getKey()).thenReturn(key); + when(mCandidate1.getScanRssi()).thenReturn(-40); + when(mCandidate1.getFrequency()).thenReturn(TEST_FREQUENCY); + when(mCandidate2.getKey()).thenReturn(key); + when(mCandidate2.getScanRssi()).thenReturn(-60); + mCandidateList = new ArrayList<WifiCandidates.Candidate>(); + mCandidateList.add(mCandidate1); + when(ns.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), + anyBoolean())).thenReturn(mCandidateList); + when(ns.selectNetwork(any())) + .then(new AnswerWithArguments() { + public WifiConfiguration answer(List<WifiCandidates.Candidate> candidateList) { + if (candidateList == null) { + return null; + } + return candidate; + } + }); return ns; } @@ -579,8 +609,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { */ @Test public void pnoRetryForLowRssiNetwork() { - when(mWifiNS.selectNetwork(anyObject(), anyObject(), anyObject(), anyBoolean(), - anyBoolean(), anyBoolean())).thenReturn(null); + when(mWifiNS.selectNetwork(any())).thenReturn(null); // Set screen to off mWifiConnectivityManager.handleScreenStateChanged(false); @@ -634,8 +663,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { @Test public void watchdogBitePnoGoodIncrementsMetrics() { // Qns returns no candidate after watchdog single scan. - when(mWifiNS.selectNetwork(anyObject(), anyObject(), anyObject(), anyBoolean(), - anyBoolean(), anyBoolean())).thenReturn(null); + when(mWifiNS.selectNetwork(any())).thenReturn(null); // Set screen to off mWifiConnectivityManager.handleScreenStateChanged(false); @@ -653,6 +681,130 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { } /** + * Verify that 2 scans that are sufficiently far apart are required to initiate a connection + * when the high mobility scanning optimization is enabled. + */ + @Test + public void testHighMovementNetworkSelection() { + when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); + // Enable high movement optimization + mResources.setBoolean(R.bool.config_wifiHighMovementNetworkSelectionOptimizationEnabled, + true); + mWifiConnectivityManager.setDeviceMobilityState( + WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT); + + // Set WiFi to disconnected state to trigger scan + mWifiConnectivityManager.handleConnectionStateChanged( + WifiConnectivityManager.WIFI_STATE_DISCONNECTED); + mLooper.dispatchAll(); + + // Verify there is no connection due to currently having no cached candidates. + verify(mClientModeImpl, never()).startConnectToNetwork( + CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); + + // Move time forward but do not cross HIGH_MVMT_SCAN_DELAY_MS yet. + when(mClock.getElapsedSinceBootMillis()).thenReturn(HIGH_MVMT_SCAN_DELAY_MS - 1L); + // Set WiFi to disconnected state to trigger scan + mWifiConnectivityManager.handleConnectionStateChanged( + WifiConnectivityManager.WIFI_STATE_DISCONNECTED); + mLooper.dispatchAll(); + + // Verify we still don't connect because not enough time have passed since the candidates + // were cached. + verify(mClientModeImpl, never()).startConnectToNetwork( + CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); + + // Move time past HIGH_MVMT_SCAN_DELAY_MS. + when(mClock.getElapsedSinceBootMillis()).thenReturn((long) HIGH_MVMT_SCAN_DELAY_MS); + // Set WiFi to disconnected state to trigger scan + mWifiConnectivityManager.handleConnectionStateChanged( + WifiConnectivityManager.WIFI_STATE_DISCONNECTED); + mLooper.dispatchAll(); + + // Verify a candidate if found this time. + verify(mClientModeImpl).startConnectToNetwork( + CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); + } + + /** + * Verify that the device is initiating partial scans to verify AP stability in the high + * movement mobility state. + */ + @Test + public void testHighMovementTriggerPartialScan() { + when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); + // Enable high movement optimization + mResources.setBoolean(R.bool.config_wifiHighMovementNetworkSelectionOptimizationEnabled, + true); + mWifiConnectivityManager.setDeviceMobilityState( + WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT); + + // Set WiFi to disconnected state to trigger scan + mWifiConnectivityManager.handleConnectionStateChanged( + WifiConnectivityManager.WIFI_STATE_DISCONNECTED); + mLooper.dispatchAll(); + // Verify there is no connection due to currently having no cached candidates. + verify(mClientModeImpl, never()).startConnectToNetwork( + CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); + + // Move time forward and verify that a delayed partial scan is scheduled. + when(mClock.getElapsedSinceBootMillis()).thenReturn(HIGH_MVMT_SCAN_DELAY_MS + 1L); + mAlarmManager.dispatch(WifiConnectivityManager.DELAYED_PARTIAL_SCAN_TIMER_TAG); + mLooper.dispatchAll(); + + verify(mWifiScanner).startScan((ScanSettings) argThat(new WifiPartialScanSettingMatcher()), + any(), any(), any()); + } + + private class WifiPartialScanSettingMatcher implements ArgumentMatcher<ScanSettings> { + @Override + public boolean matches(ScanSettings scanSettings) { + return scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED + && scanSettings.channels[0].frequency == TEST_FREQUENCY; + } + } + + /** + * Verify that in the high movement mobility state, when the RSSI delta of a BSSID from + * 2 consecutive scans becomes greater than a threshold, the candidate get ignored from + * network selection. + */ + @Test + public void testHighMovementRssiFilter() { + when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); + // Enable high movement optimization + mResources.setBoolean(R.bool.config_wifiHighMovementNetworkSelectionOptimizationEnabled, + true); + mWifiConnectivityManager.setDeviceMobilityState( + WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT); + + // Set WiFi to disconnected state to trigger scan + mWifiConnectivityManager.handleConnectionStateChanged( + WifiConnectivityManager.WIFI_STATE_DISCONNECTED); + mLooper.dispatchAll(); + + // Verify there is no connection due to currently having no cached candidates. + verify(mClientModeImpl, never()).startConnectToNetwork( + CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); + + // Move time past HIGH_MVMT_SCAN_DELAY_MS. + when(mClock.getElapsedSinceBootMillis()).thenReturn((long) HIGH_MVMT_SCAN_DELAY_MS); + + // Mock the current Candidate to have RSSI over the filter threshold + mCandidateList.clear(); + mCandidateList.add(mCandidate2); + + // Set WiFi to disconnected state to trigger scan + mWifiConnectivityManager.handleConnectionStateChanged( + WifiConnectivityManager.WIFI_STATE_DISCONNECTED); + mLooper.dispatchAll(); + + // Verify connect is not started. + verify(mClientModeImpl, never()).startConnectToNetwork( + CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); + } + + /** * {@link OpenNetworkNotifier} handles scan results on network selection. * * Expected behavior: ONA handles scan results @@ -660,8 +812,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { @Test public void wifiDisconnected_noConnectionCandidate_openNetworkNotifierScanResultsHandled() { // no connection candidate selected - when(mWifiNS.selectNetwork(anyObject(), anyObject(), anyObject(), anyBoolean(), - anyBoolean(), anyBoolean())).thenReturn(null); + when(mWifiNS.selectNetwork(any())).thenReturn(null); List<ScanDetail> expectedOpenNetworks = new ArrayList<>(); expectedOpenNetworks.add( @@ -1652,9 +1803,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { candidateScanResult.SSID = CANDIDATE_SSID; candidateScanResult.BSSID = CANDIDATE_BSSID; candidate.getNetworkSelectionStatus().setCandidate(candidateScanResult); - - when(mWifiNS.selectNetwork(anyObject(), anyObject(), anyObject(), anyBoolean(), - anyBoolean(), anyBoolean())).thenReturn(candidate); + when(mWifiNS.selectNetwork(any())).thenReturn(candidate); // Set screen to on mWifiConnectivityManager.handleScreenStateChanged(true); @@ -1706,9 +1855,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { candidateScanResult.SSID = CANDIDATE_SSID; candidateScanResult.BSSID = CANDIDATE_BSSID; candidate.getNetworkSelectionStatus().setCandidate(candidateScanResult); - - when(mWifiNS.selectNetwork(anyObject(), anyObject(), anyObject(), anyBoolean(), - anyBoolean(), anyBoolean())).thenReturn(candidate); + when(mWifiNS.selectNetwork(any())).thenReturn(candidate); // Set screen to on mWifiConnectivityManager.handleScreenStateChanged(true); @@ -1796,9 +1943,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // Set up the scan result BSSID to be different from the config specified one. candidateScanResult.BSSID = INVALID_SCAN_RESULT_BSSID; candidate.getNetworkSelectionStatus().setCandidate(candidateScanResult); - - when(mWifiNS.selectNetwork(anyObject(), anyObject(), anyObject(), anyBoolean(), - anyBoolean(), anyBoolean())).thenReturn(candidate); + when(mWifiNS.selectNetwork(any())).thenReturn(candidate); // Set screen to on mWifiConnectivityManager.handleScreenStateChanged(true); @@ -1836,9 +1981,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // Set up the scan result BSSID to be different from the config specified one. candidateScanResult.BSSID = INVALID_SCAN_RESULT_BSSID; candidate.getNetworkSelectionStatus().setCandidate(candidateScanResult); - - when(mWifiNS.selectNetwork(anyObject(), anyObject(), anyObject(), anyBoolean(), - anyBoolean(), anyBoolean())).thenReturn(candidate); + when(mWifiNS.selectNetwork(any())).thenReturn(candidate); // Set WiFi to connected state mWifiConnectivityManager.handleConnectionStateChanged( @@ -1924,8 +2067,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mResources.setBoolean( R.bool.config_wifi_framework_use_single_radio_chain_scan_results_network_selection, false); - when(mWifiNS.selectNetwork(any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean())) - .thenReturn(null); + when(mWifiNS.selectNetwork(any())).thenReturn(null); mWifiConnectivityManager = createConnectivityManager(); mScanData = createScanDataWithDifferentRadioChainInfos(); @@ -1933,13 +2075,13 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // Capture scan details which were sent to network selector. final List<ScanDetail> capturedScanDetails = new ArrayList<>(); doAnswer(new AnswerWithArguments() { - public WifiConfiguration answer( + public List<WifiCandidates.Candidate> answer( List<ScanDetail> scanDetails, Set<String> bssidBlacklist, WifiInfo wifiInfo, boolean connected, boolean disconnected, boolean untrustedNetworkAllowed) throws Exception { capturedScanDetails.addAll(scanDetails); return null; - }}).when(mWifiNS).selectNetwork( + }}).when(mWifiNS).getCandidatesFromScan( any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean()); mWifiConnectivityManager.setTrustedConnectionAllowed(true); @@ -1980,8 +2122,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mResources.setBoolean( R.bool.config_wifi_framework_use_single_radio_chain_scan_results_network_selection, true); - when(mWifiNS.selectNetwork(any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean())) - .thenReturn(null); + when(mWifiNS.selectNetwork(any())).thenReturn(null); mWifiConnectivityManager = createConnectivityManager(); mScanData = createScanDataWithDifferentRadioChainInfos(); @@ -1989,13 +2130,13 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // Capture scan details which were sent to network selector. final List<ScanDetail> capturedScanDetails = new ArrayList<>(); doAnswer(new AnswerWithArguments() { - public WifiConfiguration answer( + public List<WifiCandidates.Candidate> answer( List<ScanDetail> scanDetails, Set<String> bssidBlacklist, WifiInfo wifiInfo, boolean connected, boolean disconnected, boolean untrustedNetworkAllowed) throws Exception { capturedScanDetails.addAll(scanDetails); return null; - }}).when(mWifiNS).selectNetwork( + }}).when(mWifiNS).getCandidatesFromScan( any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean()); mWifiConnectivityManager.setTrustedConnectionAllowed(true); diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java index 0b91ea675..dcef7e11f 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java @@ -292,8 +292,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { freqs, caps, levels, securities, mWifiConfigManager, mClock); List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); HashSet<String> blacklist = new HashSet<String>(); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, - blacklist, mWifiInfo, false, true, false); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, false); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertEquals("Expect null configuration", null, candidate); assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty()); } @@ -322,8 +323,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { freqs, caps, levels, securities, mWifiConfigManager, mClock); List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); HashSet<String> blacklist = new HashSet<String>(); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, - blacklist, mWifiInfo, false, true, false); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, false); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertEquals("Expect null configuration", null, candidate); assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty()); } @@ -353,15 +355,17 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { freqs, caps, levels, securities, mWifiConfigManager, mClock); List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); HashSet<String> blacklist = new HashSet<String>(); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, - blacklist, mWifiInfo, false, true, false); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, false); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS - 2000); // Do another network selection with CMI in CONNECTED state. - candidate = mWifiNetworkSelector.selectNetwork(scanDetails, - blacklist, mWifiInfo, true, false, false); + candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, true, false, false); + candidate = mWifiNetworkSelector.selectNetwork(candidates); assertEquals("Expect null configuration", null, candidate); assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty()); @@ -395,16 +399,18 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); HashSet<String> blacklist = new HashSet<String>(); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, - blacklist, mWifiInfo, false, true, false); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, false); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate); when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS - 2000); // Do another network selection with CMI in DISCONNECTED state. - candidate = mWifiNetworkSelector.selectNetwork(scanDetails, - blacklist, mWifiInfo, false, true, false); + candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, false); + candidate = mWifiNetworkSelector.selectNetwork(candidates); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate); @@ -439,7 +445,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); // connect to test1 - mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, false); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED); when(mWifiInfo.getNetworkId()).thenReturn(0); when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); @@ -452,8 +460,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000); // Do another network selection. - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, - blacklist, mWifiInfo, true, false, false); + candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, true, false, false); + candidate = mWifiNetworkSelector.selectNetwork(candidates); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, @@ -487,7 +496,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); // connect to test1 - mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, false); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED); when(mWifiInfo.getNetworkId()).thenReturn(0); when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); @@ -507,8 +518,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { savedConfigs[0].numNoInternetAccessReports = 5; // Do another network selection. - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, - blacklist, mWifiInfo, true, false, false); + candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, true, false, false); + candidate = mWifiNetworkSelector.selectNetwork(candidates); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, @@ -537,8 +549,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); // Do network selection. - mWifiNetworkSelector.selectNetwork(scanDetails, - blacklist, mWifiInfo, true, false, false); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, true, false, false); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); verify(mWifiMetrics).incrementNetworkSelectionFilteredBssidCount(0); verify(mWifiConfigManager).getConfiguredNetworks(); @@ -571,8 +584,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { HashSet<String> blacklist = new HashSet<String>(); blacklist.add(bssids[0]); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, - blacklist, mWifiInfo, false, true, false); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, false); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); verify(mWifiMetrics).incrementNetworkSelectionFilteredBssidCount(1); assertEquals("Expect null configuration", null, candidate); assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty()); @@ -603,8 +617,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { freqs, caps, levels, securities, mWifiConfigManager, mClock); List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); HashSet<String> blacklist = new HashSet<String>(); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, - blacklist, mWifiInfo, false, true, false); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, false); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED); when(mWifiInfo.getNetworkId()).thenReturn(0); @@ -625,8 +640,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { int[] levelsNew = {mThresholdMinimumRssi2G + 40}; scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(ssidsNew, bssidsNew, freqsNew, capsNew, levelsNew, mClock); - candidate = mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, - true, false, false); + candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, true, false, false); + candidate = mWifiNetworkSelector.selectNetwork(candidates); // The second network selection is skipped since current connected network is // missing from the scan results. @@ -714,8 +730,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { .setCandidate(scanDetailsAndConfigs.getScanDetails().get(1).getScanResult()); // With no user choice set, networkSelectorChoice should be chosen. - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, - blacklist, mWifiInfo, false, true, false); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, false); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); ArgumentCaptor<Integer> nominatorIdCaptor = ArgumentCaptor.forClass(int.class); verify(mWifiMetrics, atLeastOnce()).setNominatorForNetwork(eq(candidate.networkId), @@ -733,8 +750,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { assertTrue(mWifiNetworkSelector.setUserConnectChoice(userChoice.networkId)); // After user connect choice is set, userChoice should override networkSelectorChoice. - candidate = mWifiNetworkSelector.selectNetwork(scanDetails, - blacklist, mWifiInfo, false, true, false); + candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, false); + candidate = mWifiNetworkSelector.selectNetwork(candidates); verify(mWifiMetrics, atLeastOnce()).setNominatorForNetwork(eq(candidate.networkId), nominatorIdCaptor.capture()); @@ -780,8 +798,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { userChoice.getNetworkSelectionStatus() .setCandidate(scanDetailsAndConfigs.getScanDetails().get(1).getScanResult()); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, - blacklist, mWifiInfo, false, true, false); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, false); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); ArgumentCaptor<Integer> nominatorIdCaptor = ArgumentCaptor.forClass(int.class); verify(mWifiMetrics, atLeastOnce()).setNominatorForNetwork(eq(candidate.networkId), @@ -979,8 +998,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { HashSet<String> blacklist = new HashSet<String>(); // DummyNetworkNominator always return the first network in the scan results // for connection, so this should connect to the first network. - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, - blacklist, mWifiInfo, false, true, true); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, true); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertNotNull("Result should be not null", candidate); WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, scanDetails.get(0).getScanResult(), candidate); @@ -1002,8 +1022,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000); - candidate = mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, - true, false, false); + candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, true, false, false); + candidate = mWifiNetworkSelector.selectNetwork(candidates); // DummyNetworkNominator always return the first network in the scan results // for connection, so if network selection is performed, the first network should @@ -1036,7 +1057,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { ssids, bssids, freqs, caps, levels, mClock); HashSet<String> blacklist = new HashSet<>(); - mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, false); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>(); expectedOpenUnsavedNetworks.add(scanDetails.get(1)); assertEquals("Expect open unsaved networks", @@ -1066,8 +1089,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { ssids, bssids, freqs, caps, levels, mClock); HashSet<String> blacklist = new HashSet<>(); - mWifiNetworkSelector.selectNetwork( + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( unSavedScanDetails, blacklist, mWifiInfo, false, true, false); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertEquals("Expect open unsaved networks", unSavedScanDetails, mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks()); @@ -1077,8 +1101,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { freqs, caps, levels, securities, mWifiConfigManager, mClock); List<ScanDetail> savedScanDetails = scanDetailsAndConfigs.getScanDetails(); - mWifiNetworkSelector.selectNetwork( + candidates = mWifiNetworkSelector.getCandidatesFromScan( savedScanDetails, blacklist, mWifiInfo, false, true, false); + candidate = mWifiNetworkSelector.selectNetwork(candidates); // Saved networks are filtered out. assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks().isEmpty()); } @@ -1103,7 +1128,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { HashSet<String> blacklist = new HashSet<>(); blacklist.add(bssids[0]); - mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, false); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>(); expectedOpenUnsavedNetworks.add(scanDetails.get(1)); assertEquals("Expect open unsaved networks", @@ -1130,7 +1157,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { ssids, bssids, freqs, caps, levels, mClock); HashSet<String> blacklist = new HashSet<>(); - mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, false); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks().isEmpty()); } @@ -1168,7 +1197,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { ssids, bssids, freqs, caps, levels, mClock); HashSet<String> blacklist = new HashSet<>(); - mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, false); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>(); expectedOpenUnsavedNetworks.add(scanDetails.get(1)); expectedOpenUnsavedNetworks.add(scanDetails.get(2)); @@ -1200,7 +1231,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { ssids, bssids, freqs, caps, levels, mClock); HashSet<String> blacklist = new HashSet<>(); - mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, false); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>(); expectedOpenUnsavedNetworks.add(scanDetails.get(1)); assertEquals("Expect open unsaved networks", @@ -1225,9 +1258,10 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { mWifiNetworkSelector.registerCandidateScorer(mCandidateScorer); - WifiConfiguration selected = mWifiNetworkSelector.selectNetwork( + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( setUpTwoNetworks(-35, -40), EMPTY_BLACKLIST, mWifiInfo, false, true, true); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); verify(mCandidateScorer, atLeastOnce()).scoreCandidates(any()); } @@ -1344,7 +1378,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; int[] levels = {mThresholdMinimumRssi2G + 1, mThresholdMinimumRssi5G + 1}; int[] securities = {SECURITY_EAP, SECURITY_EAP}; - HashSet<String> blackList = new HashSet<>(); + HashSet<String> blacklist = new HashSet<>(); ScanDetailsAndWifiConfigs scanDetailsAndConfigs = WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, freqs, caps, levels, securities, mWifiConfigManager, mClock); @@ -1357,8 +1391,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { .thenReturn(existingConfig); mWifiNetworkSelector.registerNetworkNominator( new DummyNetworkNominator(0, DUMMY_NOMINATOR_ID_2)); - WifiConfiguration candidate = mWifiNetworkSelector - .selectNetwork(scanDetails, blackList, mWifiInfo, false, true, true); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, true); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); // Check if the wifiConfig is updated with the latest verify(mWifiConfigManager).addOrUpdateNetwork(existingConfig, existingConfig.creatorUid, existingConfig.creatorName); @@ -1395,8 +1430,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { freqs, caps, levels, securities, mWifiConfigManager, mClock, iesByteStream); List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, - blacklist, mWifiInfo, false, true, false); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blacklist, mWifiInfo, false, true, false); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertEquals("Expect null configuration", null, candidate); assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty()); } |