1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wifi;
18
19import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_EAP;
20import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_NONE;
21import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_PSK;
22
23import static org.junit.Assert.*;
24import static org.mockito.Mockito.*;
25
26import android.content.Context;
27import android.net.wifi.ScanResult;
28import android.net.wifi.WifiConfiguration;
29import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
30import android.net.wifi.WifiInfo;
31import android.os.SystemClock;
32import android.support.test.filters.SmallTest;
33import android.util.LocalLog;
34import android.util.Pair;
35
36import com.android.internal.R;
37import com.android.server.wifi.WifiNetworkSelectorTestUtil.ScanDetailsAndWifiConfigs;
38
39import org.junit.After;
40import org.junit.Before;
41import org.junit.Test;
42import org.mockito.Mock;
43import org.mockito.MockitoAnnotations;
44import org.mockito.Spy;
45
46import java.util.ArrayList;
47import java.util.HashSet;
48import java.util.List;
49
50/**
51 * Unit tests for {@link com.android.server.wifi.WifiNetworkSelector}.
52 */
53@SmallTest
54public class WifiNetworkSelectorTest {
55
56    private static final int RSSI_BUMP = 1;
57
58    /** Sets up test. */
59    @Before
60    public void setUp() throws Exception {
61        MockitoAnnotations.initMocks(this);
62        setupContext();
63        setupResources();
64        setupWifiConfigManager();
65        setupWifiInfo();
66        mLocalLog = new LocalLog(512);
67
68        mWifiNetworkSelector = new WifiNetworkSelector(mContext,
69                new ScoringParams(mContext),
70                mWifiConfigManager, mClock,
71                mLocalLog);
72        mWifiNetworkSelector.registerNetworkEvaluator(mDummyEvaluator, 1);
73        mDummyEvaluator.setEvaluatorToSelectCandidate(true);
74        when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime());
75        when(mCarrierNetworkConfig.isCarrierNetwork(any())).thenReturn(true);
76    }
77
78    /** Cleans up test. */
79    @After
80    public void cleanup() {
81        validateMockitoUsage();
82    }
83
84    /**
85     * All this dummy network evaluator does is to pick the very first network
86     * in the scan results.
87     */
88    public class DummyNetworkEvaluator implements WifiNetworkSelector.NetworkEvaluator {
89        private static final String NAME = "DummyNetworkEvaluator";
90
91        private boolean mEvaluatorShouldSelectCandidate = true;
92
93        @Override
94        public String getName() {
95            return NAME;
96        }
97
98        @Override
99        public void update(List<ScanDetail> scanDetails) {}
100
101        /**
102         * Sets whether the evaluator should return a candidate for connection or null.
103         */
104        public void setEvaluatorToSelectCandidate(boolean shouldSelectCandidate) {
105            mEvaluatorShouldSelectCandidate = shouldSelectCandidate;
106        }
107
108        /**
109         * This NetworkEvaluator can be configured to return a candidate or null.  If returning a
110         * candidate, the first entry in the provided scanDetails will be selected. This requires
111         * that the mock WifiConfigManager be set up to return a WifiConfiguration for the first
112         * scanDetail entry, through
113         * {@link WifiNetworkSelectorTestUtil#setupScanDetailsAndConfigStore}.
114         */
115        @Override
116        public WifiConfiguration evaluateNetworks(List<ScanDetail> scanDetails,
117                    WifiConfiguration currentNetwork, String currentBssid, boolean connected,
118                    boolean untrustedNetworkAllowed,
119                    List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks) {
120            if (!mEvaluatorShouldSelectCandidate) {
121                return null;
122            }
123            ScanDetail scanDetail = scanDetails.get(0);
124            mWifiConfigManager.setNetworkCandidateScanResult(0, scanDetail.getScanResult(), 100);
125
126            assertNotNull("Saved network must not be null",
127                    mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(scanDetail));
128
129            return mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(scanDetail);
130        }
131    }
132
133    private WifiNetworkSelector mWifiNetworkSelector = null;
134    private DummyNetworkEvaluator mDummyEvaluator = new DummyNetworkEvaluator();
135    @Mock private WifiConfigManager mWifiConfigManager;
136    @Mock private Context mContext;
137    @Mock private CarrierNetworkConfig mCarrierNetworkConfig;
138
139    // For simulating the resources, we use a Spy on a MockResource
140    // (which is really more of a stub than a mock, in spite if its name).
141    // This is so that we get errors on any calls that we have not explicitly set up.
142    @Spy private MockResources mResource = new MockResources();
143    @Mock private WifiInfo mWifiInfo;
144    @Mock private Clock mClock;
145    private LocalLog mLocalLog;
146    private int mThresholdMinimumRssi2G;
147    private int mThresholdMinimumRssi5G;
148    private int mThresholdQualifiedRssi2G;
149    private int mThresholdQualifiedRssi5G;
150    private int mStayOnNetworkMinimumTxRate;
151    private int mStayOnNetworkMinimumRxRate;
152
153    private void setupContext() {
154        when(mContext.getResources()).thenReturn(mResource);
155    }
156
157    private int setupIntegerResource(int resourceName, int value) {
158        doReturn(value).when(mResource).getInteger(resourceName);
159        return value;
160    }
161
162    private void setupResources() {
163        doReturn(true).when(mResource).getBoolean(
164                R.bool.config_wifi_framework_enable_associated_network_selection);
165
166        mThresholdMinimumRssi2G = setupIntegerResource(
167                R.integer.config_wifi_framework_wifi_score_entry_rssi_threshold_24GHz, -79);
168        mThresholdMinimumRssi5G = setupIntegerResource(
169                R.integer.config_wifi_framework_wifi_score_entry_rssi_threshold_5GHz, -76);
170        mThresholdQualifiedRssi2G = setupIntegerResource(
171                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz, -73);
172        mThresholdQualifiedRssi5G = setupIntegerResource(
173                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz, -70);
174        mStayOnNetworkMinimumTxRate = setupIntegerResource(
175                R.integer.config_wifi_framework_min_tx_rate_for_staying_on_network, 16);
176        mStayOnNetworkMinimumRxRate = setupIntegerResource(
177                R.integer.config_wifi_framework_min_rx_rate_for_staying_on_network, 16);
178    }
179
180    private void setupWifiInfo() {
181        // simulate a disconnected state
182        when(mWifiInfo.is24GHz()).thenReturn(true);
183        when(mWifiInfo.is5GHz()).thenReturn(false);
184        when(mWifiInfo.getFrequency()).thenReturn(2400);
185        when(mWifiInfo.getRssi()).thenReturn(-70);
186        when(mWifiInfo.getNetworkId()).thenReturn(WifiConfiguration.INVALID_NETWORK_ID);
187        when(mWifiInfo.getBSSID()).thenReturn(null);
188    }
189
190    private void setupWifiConfigManager() {
191        when(mWifiConfigManager.getLastSelectedNetwork())
192                .thenReturn(WifiConfiguration.INVALID_NETWORK_ID);
193    }
194
195    /**
196     * No network selection if scan result is empty.
197     *
198     * WifiStateMachine is in disconnected state.
199     * scanDetails is empty.
200     *
201     * Expected behavior: no network recommended by Network Selector
202     */
203    @Test
204    public void emptyScanResults() {
205        String[] ssids = new String[0];
206        String[] bssids = new String[0];
207        int[] freqs = new int[0];
208        String[] caps = new String[0];
209        int[] levels = new int[0];
210        int[] securities = new int[0];
211
212        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
213                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
214                    freqs, caps, levels, securities, mWifiConfigManager, mClock);
215        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
216        HashSet<String> blacklist = new HashSet<String>();
217        WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
218                blacklist, mWifiInfo, false, true, false);
219        assertEquals("Expect null configuration", null, candidate);
220        assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty());
221    }
222
223
224    /**
225     * No network selection if the RSSI values in scan result are too low.
226     *
227     * WifiStateMachine is in disconnected state.
228     * scanDetails contains a 2.4GHz and a 5GHz network, but both with RSSI lower than
229     * the threshold
230     *
231     * Expected behavior: no network recommended by Network Selector
232     */
233    @Test
234    public void verifyMinimumRssiThreshold() {
235        String[] ssids = {"\"test1\"", "\"test2\""};
236        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
237        int[] freqs = {2437, 5180};
238        String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
239        int[] levels = {mThresholdMinimumRssi2G - 1, mThresholdMinimumRssi5G - 1};
240        int[] securities = {SECURITY_PSK, SECURITY_PSK};
241
242        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
243                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
244                    freqs, caps, levels, securities, mWifiConfigManager, mClock);
245        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
246        HashSet<String> blacklist = new HashSet<String>();
247        WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
248                blacklist, mWifiInfo, false, true, false);
249        assertEquals("Expect null configuration", null, candidate);
250        assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty());
251    }
252
253    /**
254     * No network selection if WiFi is connected and it is too short from last
255     * network selection.
256     *
257     * WifiStateMachine is in connected state.
258     * scanDetails contains two valid networks.
259     * Perform a network seletion right after the first one.
260     *
261     * Expected behavior: no network recommended by Network Selector
262     */
263    @Test
264    public void verifyMinimumTimeGapWhenConnected() {
265        String[] ssids = {"\"test1\"", "\"test2\""};
266        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
267        int[] freqs = {2437, 5180};
268        String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
269        int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
270        int[] securities = {SECURITY_PSK, SECURITY_PSK};
271
272        // Make a network selection.
273        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
274                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
275                    freqs, caps, levels, securities, mWifiConfigManager, mClock);
276        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
277        HashSet<String> blacklist = new HashSet<String>();
278        WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
279                blacklist, mWifiInfo, false, true, false);
280
281        when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
282                + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS - 2000);
283
284        // Do another network selection with WSM in CONNECTED state.
285        candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
286                blacklist, mWifiInfo, true, false, false);
287
288        assertEquals("Expect null configuration", null, candidate);
289        assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty());
290    }
291
292    /**
293     * Perform network selection if WiFi is disconnected even if it is too short from last
294     * network selection.
295     *
296     * WifiStateMachine is in disconnected state.
297     * scanDetails contains two valid networks.
298     * Perform a network seletion right after the first one.
299     *
300     * Expected behavior: the first network is recommended by Network Selector
301     */
302    @Test
303    public void verifyNoMinimumTimeGapWhenDisconnected() {
304        String[] ssids = {"\"test1\"", "\"test2\""};
305        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
306        int[] freqs = {2437, 5180};
307        String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
308        int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
309        int[] securities = {SECURITY_PSK, SECURITY_PSK};
310
311        // Make a network selection.
312        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
313                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
314                    freqs, caps, levels, securities, mWifiConfigManager, mClock);
315        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
316        WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
317        HashSet<String> blacklist = new HashSet<String>();
318        WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
319                blacklist, mWifiInfo, false, true, false);
320        WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate);
321
322        when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
323                + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS - 2000);
324
325        // Do another network selection with WSM in DISCONNECTED state.
326        candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
327                blacklist, mWifiInfo, false, true, false);
328
329        ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
330        WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate);
331        WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
332                chosenScanResult, candidate);
333    }
334
335    /**
336     * New network selection is performed if the currently connected network
337     * is a open one.
338     *
339     * WifiStateMachine is connected to a open network.
340     * scanDetails contains a valid networks.
341     * Perform a network seletion after the first one.
342     *
343     * Expected behavior: the first network is recommended by Network Selector
344     */
345    @Test
346    public void openNetworkIsNotSufficient() {
347        String[] ssids = {"\"test1\""};
348        String[] bssids = {"6c:f3:7f:ae:8c:f3"};
349        int[] freqs = {5180};
350        String[] caps = {"[ESS]"};
351        int[] levels = {mThresholdQualifiedRssi5G + 8};
352        int[] securities = {SECURITY_NONE};
353
354        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
355                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
356                    freqs, caps, levels, securities, mWifiConfigManager, mClock);
357        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
358        HashSet<String> blacklist = new HashSet<String>();
359        WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
360
361        // connect to test1
362        mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
363        when(mWifiInfo.getNetworkId()).thenReturn(0);
364        when(mWifiInfo.getBSSID()).thenReturn(bssids[0]);
365        when(mWifiInfo.is24GHz()).thenReturn(false);
366        when(mWifiInfo.is5GHz()).thenReturn(true);
367        when(mWifiInfo.getFrequency()).thenReturn(5000);
368
369        when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
370                + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000);
371
372        // Do another network selection.
373        WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
374                blacklist, mWifiInfo, true, false, false);
375
376        ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
377        WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate);
378        WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
379                chosenScanResult, candidate);
380    }
381
382    /**
383     * New network selection is performed if the currently connected network
384     * has low RSSI value.
385     *
386     * WifiStateMachine is connected to a low RSSI 5GHz network.
387     * scanDetails contains a valid networks.
388     * Perform a network seletion after the first one.
389     *
390     * Expected behavior: the first network is recommended by Network Selector
391     */
392    @Test
393    public void lowRssi5GNetworkIsNotSufficient() {
394        String[] ssids = {"\"test1\""};
395        String[] bssids = {"6c:f3:7f:ae:8c:f3"};
396        int[] freqs = {5180};
397        String[] caps = {"[WPA2-EAP-CCMP][ESS]"};
398        int[] levels = {mThresholdQualifiedRssi5G - 2};
399        int[] securities = {SECURITY_PSK};
400
401        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
402                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
403                    freqs, caps, levels, securities, mWifiConfigManager, mClock);
404        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
405        HashSet<String> blacklist = new HashSet<String>();
406        WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
407
408        // connect to test1
409        mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
410        when(mWifiInfo.getNetworkId()).thenReturn(0);
411        when(mWifiInfo.getBSSID()).thenReturn(bssids[0]);
412        when(mWifiInfo.is24GHz()).thenReturn(false);
413        when(mWifiInfo.is5GHz()).thenReturn(true);
414        when(mWifiInfo.getFrequency()).thenReturn(5000);
415        when(mWifiInfo.getRssi()).thenReturn(levels[0]);
416
417        when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
418                + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000);
419
420        // Do another network selection.
421        WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
422                blacklist, mWifiInfo, true, false, false);
423
424        ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
425        WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
426                chosenScanResult, candidate);
427    }
428
429    /**
430     * New network selection is performed if the currently connected network
431     * has no internet access and the user did not explicitly choose to stay connected.
432     *
433     * WifiStateMachine is connected to a network with no internet connectivity.
434     * scanDetails contains a valid networks.
435     * Perform a network selection after the first one.
436     *
437     * Expected behavior: the first network is recommended by Network Selector
438     */
439    @Test
440    public void noInternetAccessNetworkIsNotSufficient() {
441        String[] ssids = {"\"test1\""};
442        String[] bssids = {"6c:f3:7f:ae:8c:f3"};
443        int[] freqs = {5180};
444        String[] caps = {"[WPA2-EAP-CCMP][ESS]"};
445        int[] levels = {mThresholdQualifiedRssi5G + 5};
446        int[] securities = {SECURITY_PSK};
447
448        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
449                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
450                        freqs, caps, levels, securities, mWifiConfigManager, mClock);
451        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
452        HashSet<String> blacklist = new HashSet<String>();
453        WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
454
455        // connect to test1
456        mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
457        when(mWifiInfo.getNetworkId()).thenReturn(0);
458        when(mWifiInfo.getBSSID()).thenReturn(bssids[0]);
459        when(mWifiInfo.is24GHz()).thenReturn(false);
460        when(mWifiInfo.is5GHz()).thenReturn(true);
461        when(mWifiInfo.getFrequency()).thenReturn(5000);
462        when(mWifiInfo.getRssi()).thenReturn(levels[0]);
463
464        when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
465                + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000);
466
467        // Increment the network's no internet access reports.
468        savedConfigs[0].numNoInternetAccessReports = 5;
469
470        // Do another network selection.
471        WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
472                blacklist, mWifiInfo, true, false, false);
473
474        ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
475        WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
476                chosenScanResult, candidate);
477    }
478
479    /**
480     * Blacklisted BSSID is filtered out for network selection.
481     *
482     * WifiStateMachine is disconnected.
483     * scanDetails contains a network which is blacklisted.
484     *
485     * Expected behavior: no network recommended by Network Selector
486     */
487    @Test
488    public void filterOutBlacklistedBssid() {
489        String[] ssids = {"\"test1\""};
490        String[] bssids = {"6c:f3:7f:ae:8c:f3"};
491        int[] freqs = {5180};
492        String[] caps = {"[WPA2-EAP-CCMP][ESS]"};
493        int[] levels = {mThresholdQualifiedRssi5G + 8};
494        int[] securities = {SECURITY_PSK};
495
496        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
497                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
498                    freqs, caps, levels, securities, mWifiConfigManager, mClock);
499        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
500        HashSet<String> blacklist = new HashSet<String>();
501        blacklist.add(bssids[0]);
502
503        WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
504                blacklist, mWifiInfo, false, true, false);
505        assertEquals("Expect null configuration", null, candidate);
506        assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty());
507    }
508
509    /**
510     * Wifi network selector doesn't recommend any network if the currently connected one
511     * doesn't show up in the scan results.
512     *
513     * WifiStateMachine is under connected state and 2.4GHz test1 is connected.
514     * The second scan results contains only test2 which now has a stronger RSSI than test1.
515     * Test1 is not in the second scan results.
516     *
517     * Expected behavior: no network recommended by Network Selector
518     */
519    @Test
520    public void noSelectionWhenCurrentNetworkNotInScanResults() {
521        String[] ssids = {"\"test1\"", "\"test2\""};
522        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
523        int[] freqs = {2437, 2457};
524        String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
525        int[] levels = {mThresholdMinimumRssi2G + 20, mThresholdMinimumRssi2G + RSSI_BUMP};
526        int[] securities = {SECURITY_PSK, SECURITY_PSK};
527
528        // Make a network selection to connect to test1.
529        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
530                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
531                    freqs, caps, levels, securities, mWifiConfigManager, mClock);
532        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
533        HashSet<String> blacklist = new HashSet<String>();
534        WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
535                blacklist, mWifiInfo, false, true, false);
536
537        when(mWifiInfo.getNetworkId()).thenReturn(0);
538        when(mWifiInfo.getBSSID()).thenReturn(bssids[0]);
539        when(mWifiInfo.is24GHz()).thenReturn(true);
540        when(mWifiInfo.is5GHz()).thenReturn(false);
541        when(mWifiInfo.getFrequency()).thenReturn(2400);
542        when(mWifiInfo.getRssi()).thenReturn(levels[0]);
543        when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
544                + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000);
545
546        // Prepare the second scan results which have no test1.
547        String[] ssidsNew = {"\"test2\""};
548        String[] bssidsNew = {"6c:f3:7f:ae:8c:f4"};
549        int[] freqsNew = {2457};
550        String[] capsNew = {"[WPA2-EAP-CCMP][ESS]"};
551        int[] levelsNew = {mThresholdMinimumRssi2G + 40};
552        scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(ssidsNew, bssidsNew,
553                freqsNew, capsNew, levelsNew, mClock);
554        candidate = mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo,
555                true, false, false);
556
557        // The second network selection is skipped since current connected network is
558        // missing from the scan results.
559        assertEquals("Expect null configuration", null, candidate);
560        assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty());
561    }
562
563    /**
564     * Ensures that settings the user connect choice updates the
565     * NetworkSelectionStatus#mConnectChoice for all other WifiConfigurations in range in the last
566     * round of network selection.
567     *
568     * Expected behavior: WifiConfiguration.NetworkSelectionStatus#mConnectChoice is set to
569     *                    test1's configkey for test2. test3's WifiConfiguration is unchanged.
570     */
571    @Test
572    public void setUserConnectChoice() {
573        String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\""};
574        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "6c:f3:7f:ae:8c:f5"};
575        int[] freqs = {2437, 5180, 5181};
576        String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
577        int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP,
578                mThresholdMinimumRssi5G + RSSI_BUMP};
579        int[] securities = {SECURITY_PSK, SECURITY_PSK, SECURITY_PSK};
580
581        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
582                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
583                        freqs, caps, levels, securities, mWifiConfigManager, mClock);
584
585        WifiConfiguration selectedWifiConfig = scanDetailsAndConfigs.getWifiConfigs()[0];
586        selectedWifiConfig.getNetworkSelectionStatus()
587                .setCandidate(scanDetailsAndConfigs.getScanDetails().get(0).getScanResult());
588        selectedWifiConfig.getNetworkSelectionStatus().setNetworkSelectionStatus(
589                NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED);
590        selectedWifiConfig.getNetworkSelectionStatus().setConnectChoice("bogusKey");
591
592        WifiConfiguration configInLastNetworkSelection = scanDetailsAndConfigs.getWifiConfigs()[1];
593        configInLastNetworkSelection.getNetworkSelectionStatus()
594                .setSeenInLastQualifiedNetworkSelection(true);
595
596        WifiConfiguration configNotInLastNetworkSelection =
597                scanDetailsAndConfigs.getWifiConfigs()[2];
598
599        assertTrue(mWifiNetworkSelector.setUserConnectChoice(selectedWifiConfig.networkId));
600
601        verify(mWifiConfigManager).updateNetworkSelectionStatus(selectedWifiConfig.networkId,
602                NetworkSelectionStatus.NETWORK_SELECTION_ENABLE);
603        verify(mWifiConfigManager).clearNetworkConnectChoice(selectedWifiConfig.networkId);
604        verify(mWifiConfigManager).setNetworkConnectChoice(configInLastNetworkSelection.networkId,
605                selectedWifiConfig.configKey(), mClock.getWallClockMillis());
606        verify(mWifiConfigManager, never()).setNetworkConnectChoice(
607                configNotInLastNetworkSelection.networkId, selectedWifiConfig.configKey(),
608                mClock.getWallClockMillis());
609    }
610
611    /**
612     * If two qualified networks, test1 and test2, are in range when the user selects test2 over
613     * test1, WifiNetworkSelector will override the NetworkSelector's choice to connect to test1
614     * with test2.
615     *
616     * Expected behavior: test2 is the recommended network
617     */
618    @Test
619    public void userConnectChoiceOverridesNetworkEvaluators() {
620        String[] ssids = {"\"test1\"", "\"test2\""};
621        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
622        int[] freqs = {2437, 5180};
623        String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
624        int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
625        int[] securities = {SECURITY_PSK, SECURITY_PSK};
626
627        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
628                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
629                        freqs, caps, levels, securities, mWifiConfigManager, mClock);
630        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
631        HashSet<String> blacklist = new HashSet<String>();
632
633        // DummyEvaluator always selects the first network in the list.
634        WifiConfiguration networkSelectorChoice = scanDetailsAndConfigs.getWifiConfigs()[0];
635        networkSelectorChoice.getNetworkSelectionStatus()
636                .setSeenInLastQualifiedNetworkSelection(true);
637
638        WifiConfiguration userChoice = scanDetailsAndConfigs.getWifiConfigs()[1];
639        userChoice.getNetworkSelectionStatus()
640                .setCandidate(scanDetailsAndConfigs.getScanDetails().get(1).getScanResult());
641
642        // With no user choice set, networkSelectorChoice should be chosen.
643        WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
644                blacklist, mWifiInfo, false, true, false);
645
646        WifiConfigurationTestUtil.assertConfigurationEqual(networkSelectorChoice, candidate);
647
648        when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
649                + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000);
650
651        assertTrue(mWifiNetworkSelector.setUserConnectChoice(userChoice.networkId));
652
653        // After user connect choice is set, userChoice should override networkSelectorChoice.
654        candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
655                blacklist, mWifiInfo, false, true, false);
656
657        WifiConfigurationTestUtil.assertConfigurationEqual(userChoice, candidate);
658    }
659
660    /**
661     * Wifi network selector doesn't recommend any network if the currently connected 2.4Ghz
662     * network is high quality and no 5GHz networks are available
663     *
664     * WifiStateMachine is under connected state and 2.4GHz test1 is connected.
665     *
666     * Expected behavior: no network selection is performed
667     */
668    @Test
669    public void test2GhzQualifiedNo5GhzAvailable() {
670        // Rssi after connected.
671        when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi2G + 1);
672        // No streaming traffic.
673        mWifiInfo.txSuccessRate = 0.0;
674        mWifiInfo.rxSuccessRate = 0.0;
675
676        // Do not perform selection on 2GHz if current network is good and no 5GHz available
677        testStayOrTryToSwitch(
678                mThresholdQualifiedRssi2G + 1 /* rssi before connected */,
679                false /* not a 5G network */,
680                false /* not open network */,
681                // Should not try to switch.
682                false);
683    }
684
685    /**
686     * Wifi network selector performs network selection even when the 2Ghz network is high
687     * quality whenever 5Ghz networks are available.
688     *
689     * WifiStateMachine is under connected state and 2.4GHz test1 is connected.
690     * The scan results contain a 5Ghz network, which forces network selection.
691     * Test1 is not in the second scan results.
692     *
693     * Expected behavior: network selection is performed
694     */
695    @Test
696    public void test2GhzHighQuality5GhzAvailable() {
697        // Rssi after connected.
698        when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi2G + 1);
699        // No streaming traffic.
700        mWifiInfo.txSuccessRate = 0.0;
701        mWifiInfo.rxSuccessRate = 0.0;
702
703        // When on 2GHz, even with "good" signal strength, run selection if 5GHz available
704        testStayOrTryToSwitch(
705                // Parameters for network1:
706                mThresholdQualifiedRssi2G + 1 /* rssi before connected */,
707                false /* not a 5G network */,
708                false /* not open network */,
709                // Parameters for network2:
710                mThresholdQualifiedRssi5G + 1 /* rssi */,
711                true /* a 5G network */,
712                false /* not open network */,
713                // Should try to switch.
714                true);
715    }
716
717    /**
718     * Wifi network selector performs network selection when connected to a 5Ghz network that
719     * has an insufficient RSSI.
720     *
721     * WifiStateMachine is under connected state and 5GHz test1 is connected.
722     *
723     * Expected behavior: network selection is performed
724     */
725    @Test
726    public void test5GhzNotQualifiedLowRssi() {
727        // Rssi after connected.
728        when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi5G - 1);
729        // No streaming traffic.
730        mWifiInfo.txSuccessRate = 0.0;
731        mWifiInfo.rxSuccessRate = 0.0;
732
733        // Run Selection when the current 5Ghz network has low RSSI.
734        testStayOrTryToSwitch(
735                mThresholdQualifiedRssi5G + 1 /* rssi before connected */,
736                true /* a 5G network */,
737                false /* not open network */,
738                // Should try to switch.
739                true);
740    }
741
742    /**
743     * Wifi network selector will not run selection when on a 5Ghz network that is of sufficent
744     * Quality (high-enough RSSI).
745     *
746     * WifiStateMachine is under connected state and 5GHz test1 is connected.
747     *
748     * Expected behavior: network selection is not performed
749     */
750    @Test
751    public void test5GhzQualified() {
752        // Rssi after connected.
753        when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi5G + 1);
754        // No streaming traffic.
755        mWifiInfo.txSuccessRate = 0.0;
756        mWifiInfo.rxSuccessRate = 0.0;
757
758        // Connected to a high quality 5Ghz network, so the other result is irrelevant
759        testStayOrTryToSwitch(
760                mThresholdQualifiedRssi5G + 1 /* rssi before connected */,
761                true /* a 5G network */,
762                false /* not open network */,
763                // Should not try to switch.
764                false);
765    }
766
767    /**
768     * New network selection is performed if the currently connected network
769     * band is 2G and there is no sign of streaming traffic.
770     *
771     * Expected behavior: Network Selector perform network selection after connected
772     * to the first one.
773     */
774    @Test
775    public void band2GNetworkIsNotSufficientWhenNoOngoingTrafficAnd5GhzAvailable() {
776        // Rssi after connected.
777        when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi2G + 1);
778        // No streaming traffic.
779        mWifiInfo.txSuccessRate = 0.0;
780        mWifiInfo.rxSuccessRate = 0.0;
781
782        testStayOrTryToSwitch(
783                // Parameters for network1:
784                mThresholdQualifiedRssi2G + 1 /* rssi before connected */,
785                false /* not a 5G network */,
786                false /* not open network */,
787                // Parameters for network2:
788                mThresholdQualifiedRssi5G + 1 /* rssi */,
789                true /* a 5G network */,
790                false /* not open network */,
791                // Should try to switch.
792                true);
793    }
794
795    /**
796     * New network selection is performed if the currently connected network
797     * band is 2G with bad rssi.
798     *
799     * Expected behavior: Network Selector perform network selection after connected
800     * to the first one.
801     */
802    @Test
803    public void band2GNetworkIsNotSufficientWithBadRssi() {
804        // Rssi after connected.
805        when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi2G - 1);
806        // No streaming traffic.
807        mWifiInfo.txSuccessRate = 0.0;
808        mWifiInfo.rxSuccessRate = 0.0;
809
810        testStayOrTryToSwitch(
811                mThresholdQualifiedRssi2G + 1 /* rssi before connected */,
812                false /* not a 5G network */,
813                false /* not open network */,
814                // Should try to switch.
815                true);
816    }
817
818    /**
819     * New network selection is not performed if the currently connected 2G network
820     * has good Rssi and sign of streaming tx traffic.
821     *
822     * Expected behavior: Network selector does not perform network selection.
823     */
824    @Test
825    public void band2GNetworkIsSufficientWhenOnGoingTxTrafficCombinedWithGoodRssi() {
826        // Rssi after connected.
827        when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi2G + 1);
828        // Streaming traffic
829        mWifiInfo.txSuccessRate = ((double) (mStayOnNetworkMinimumTxRate + 1));
830        mWifiInfo.rxSuccessRate = 0.0;
831
832        testStayOrTryToSwitch(
833                mThresholdQualifiedRssi2G + 1 /* rssi before connected */,
834                false /* not a 5G network */,
835                true /* open network */,
836                // Should not try to switch.
837                false);
838    }
839
840    /**
841     * New network selection is not performed if the currently connected 2G network
842     * has good Rssi and sign of streaming rx traffic.
843     *
844     * Expected behavior: Network selector does not perform network selection.
845     */
846    @Test
847    public void band2GNetworkIsSufficientWhenOnGoingRxTrafficCombinedWithGoodRssi() {
848        // Rssi after connected.
849        when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi2G + 1);
850        // Streaming traffic
851        mWifiInfo.txSuccessRate = 0.0;
852        mWifiInfo.rxSuccessRate = ((double) (mStayOnNetworkMinimumRxRate + 1));
853
854        testStayOrTryToSwitch(
855                mThresholdQualifiedRssi2G + 1 /* rssi before connected */,
856                false /* not a 5G network */,
857                true /* open network */,
858                // Should not try to switch.
859                false);
860    }
861
862    /**
863     * New network selection is not performed if the currently connected 5G network
864     * has good Rssi and sign of streaming tx traffic.
865     *
866     * Expected behavior: Network selector does not perform network selection.
867     */
868    @Test
869    public void band5GNetworkIsSufficientWhenOnGoingTxTrafficCombinedWithGoodRssi() {
870        // Rssi after connected.
871        when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi5G + 1);
872        // Streaming traffic
873        mWifiInfo.txSuccessRate = ((double) (mStayOnNetworkMinimumTxRate + 1));
874        mWifiInfo.rxSuccessRate = 0.0;
875
876        testStayOrTryToSwitch(
877                mThresholdQualifiedRssi5G + 1 /* rssi before connected */,
878                true /* a 5G network */,
879                true /* open network */,
880                // Should not try to switch.
881                false);
882    }
883
884    /**
885     * New network selection is not performed if the currently connected 5G network
886     * has good Rssi and sign of streaming rx traffic.
887     *
888     * Expected behavior: Network selector does not perform network selection.
889     */
890    @Test
891    public void band5GNetworkIsSufficientWhenOnGoingRxTrafficCombinedWithGoodRssi() {
892        // Rssi after connected.
893        when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi5G + 1);
894        // Streaming traffic
895        mWifiInfo.txSuccessRate = 0.0;
896        mWifiInfo.rxSuccessRate = ((double) (mStayOnNetworkMinimumRxRate + 1));
897
898        testStayOrTryToSwitch(
899                mThresholdQualifiedRssi5G + 1 /* rssi before connected */,
900                true /* a 5G network */,
901                true /* open network */,
902                // Should not try to switch.
903                false);
904    }
905
906    /**
907     * This is a meta-test that given two scan results of various types, will
908     * determine whether or not network selection should be performed.
909     *
910     * It sets up two networks, connects to the first, and then ensures that
911     * both are available in the scan results for the NetworkSelector.
912     */
913    private void testStayOrTryToSwitch(
914            int rssiNetwork1, boolean is5GHzNetwork1, boolean isOpenNetwork1,
915            int rssiNetwork2, boolean is5GHzNetwork2, boolean isOpenNetwork2,
916            boolean shouldSelect) {
917        String[] ssids = {"\"test1\"", "\"test2\""};
918        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
919        int[] freqs = {is5GHzNetwork1 ? 5180 : 2437, is5GHzNetwork2 ? 5180 : 2437};
920        String[] caps = {isOpenNetwork1 ? "[ESS]" : "[WPA2-EAP-CCMP][ESS]",
921                         isOpenNetwork2 ? "[ESS]" : "[WPA2-EAP-CCMP][ESS]"};
922        int[] levels = {rssiNetwork1, rssiNetwork2};
923        int[] securities = {isOpenNetwork1 ? SECURITY_NONE : SECURITY_PSK,
924                            isOpenNetwork2 ? SECURITY_NONE : SECURITY_PSK};
925        testStayOrTryToSwitchImpl(ssids, bssids, freqs, caps, levels, securities, shouldSelect);
926    }
927
928    /**
929     * This is a meta-test that given one scan results, will
930     * determine whether or not network selection should be performed.
931     *
932     * It sets up two networks, connects to the first, and then ensures that
933     * the scan results for the NetworkSelector.
934     */
935    private void testStayOrTryToSwitch(
936            int rssi, boolean is5GHz, boolean isOpenNetwork,
937            boolean shouldSelect) {
938        String[] ssids = {"\"test1\""};
939        String[] bssids = {"6c:f3:7f:ae:8c:f3"};
940        int[] freqs = {is5GHz ? 5180 : 2437};
941        String[] caps = {isOpenNetwork ? "[ESS]" : "[WPA2-EAP-CCMP][ESS]"};
942        int[] levels = {rssi};
943        int[] securities = {isOpenNetwork ? SECURITY_NONE : SECURITY_PSK};
944        testStayOrTryToSwitchImpl(ssids, bssids, freqs, caps, levels, securities, shouldSelect);
945    }
946
947    private void testStayOrTryToSwitchImpl(String[] ssids, String[] bssids, int[] freqs,
948            String[] caps, int[] levels, int[] securities,
949            boolean shouldSelect) {
950        // Make a network selection to connect to test1.
951        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
952                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
953                        freqs, caps, levels, securities, mWifiConfigManager, mClock);
954        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
955        HashSet<String> blacklist = new HashSet<String>();
956        // DummyNetworkEvaluator always return the first network in the scan results
957        // for connection, so this should connect to the first network.
958        WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(
959                scanDetails,
960                blacklist, mWifiInfo, false, true, true);
961        assertNotNull("Result should be not null", candidate);
962        WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
963                scanDetails.get(0).getScanResult(), candidate);
964
965        when(mWifiInfo.getNetworkId()).thenReturn(0);
966        when(mWifiInfo.getBSSID()).thenReturn(bssids[0]);
967        when(mWifiInfo.is24GHz()).thenReturn(!ScanResult.is5GHz(freqs[0]));
968        when(mWifiInfo.is5GHz()).thenReturn(ScanResult.is5GHz(freqs[0]));
969        when(mWifiInfo.getFrequency()).thenReturn(freqs[0]);
970
971        when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
972                + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000);
973
974        candidate = mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo,
975                true, false, false);
976
977        // DummyNetworkEvaluator always return the first network in the scan results
978        // for connection, so if nework selection is performed, the first network should
979        // be returned as candidate.
980        if (shouldSelect) {
981            assertNotNull("Result should be not null", candidate);
982            WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
983                    scanDetails.get(0).getScanResult(), candidate);
984        } else {
985            assertEquals("Expect null configuration", null, candidate);
986        }
987    }
988
989    /**
990     * {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} should filter out
991     * networks that are not open after network selection is made.
992     *
993     * Expected behavior: return open networks only
994     */
995    @Test
996    public void getfilterOpenUnsavedNetworks_filtersForOpenNetworks() {
997        String[] ssids = {"\"test1\"", "\"test2\""};
998        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
999        int[] freqs = {2437, 5180};
1000        String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]"};
1001        int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
1002        mDummyEvaluator.setEvaluatorToSelectCandidate(false);
1003
1004        List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
1005                ssids, bssids, freqs, caps, levels, mClock);
1006        HashSet<String> blacklist = new HashSet<>();
1007
1008        mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
1009        List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>();
1010        expectedOpenUnsavedNetworks.add(scanDetails.get(1));
1011        assertEquals("Expect open unsaved networks",
1012                expectedOpenUnsavedNetworks,
1013                mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks());
1014    }
1015
1016    /**
1017     * {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} should filter out
1018     * saved networks after network selection is made. This should return an empty list when there
1019     * are no unsaved networks available.
1020     *
1021     * Expected behavior: return unsaved networks only. Return empty list if there are no unsaved
1022     * networks.
1023     */
1024    @Test
1025    public void getfilterOpenUnsavedNetworks_filtersOutSavedNetworks() {
1026        String[] ssids = {"\"test1\""};
1027        String[] bssids = {"6c:f3:7f:ae:8c:f3"};
1028        int[] freqs = {2437, 5180};
1029        String[] caps = {"[ESS]"};
1030        int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP};
1031        int[] securities = {SECURITY_NONE};
1032        mDummyEvaluator.setEvaluatorToSelectCandidate(false);
1033
1034        List<ScanDetail> unSavedScanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
1035                ssids, bssids, freqs, caps, levels, mClock);
1036        HashSet<String> blacklist = new HashSet<>();
1037
1038        mWifiNetworkSelector.selectNetwork(
1039                unSavedScanDetails, blacklist, mWifiInfo, false, true, false);
1040        assertEquals("Expect open unsaved networks",
1041                unSavedScanDetails,
1042                mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks());
1043
1044        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
1045                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
1046                        freqs, caps, levels, securities, mWifiConfigManager, mClock);
1047        List<ScanDetail> savedScanDetails = scanDetailsAndConfigs.getScanDetails();
1048
1049        mWifiNetworkSelector.selectNetwork(
1050                savedScanDetails, blacklist, mWifiInfo, false, true, false);
1051        // Saved networks are filtered out.
1052        assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks().isEmpty());
1053    }
1054
1055    /**
1056     * {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} should filter out
1057     * bssid blacklisted networks.
1058     *
1059     * Expected behavior: do not return blacklisted network
1060     */
1061    @Test
1062    public void getfilterOpenUnsavedNetworks_filtersOutBlacklistedNetworks() {
1063        String[] ssids = {"\"test1\"", "\"test2\""};
1064        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
1065        int[] freqs = {2437, 5180};
1066        String[] caps = {"[ESS]", "[ESS]"};
1067        int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
1068        mDummyEvaluator.setEvaluatorToSelectCandidate(false);
1069
1070        List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
1071                ssids, bssids, freqs, caps, levels, mClock);
1072        HashSet<String> blacklist = new HashSet<>();
1073        blacklist.add(bssids[0]);
1074
1075        mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
1076        List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>();
1077        expectedOpenUnsavedNetworks.add(scanDetails.get(1));
1078        assertEquals("Expect open unsaved networks",
1079                expectedOpenUnsavedNetworks,
1080                mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks());
1081    }
1082
1083    /**
1084     * {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} should return
1085     * empty list when there are no open networks after network selection is made.
1086     *
1087     * Expected behavior: return empty list
1088     */
1089    @Test
1090    public void getfilterOpenUnsavedNetworks_returnsEmptyListWhenNoOpenNetworksPresent() {
1091        String[] ssids = {"\"test1\"", "\"test2\""};
1092        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
1093        int[] freqs = {2437, 5180};
1094        String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
1095        int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
1096        mDummyEvaluator.setEvaluatorToSelectCandidate(false);
1097
1098        List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
1099                ssids, bssids, freqs, caps, levels, mClock);
1100        HashSet<String> blacklist = new HashSet<>();
1101
1102        mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
1103        assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks().isEmpty());
1104    }
1105
1106    /**
1107     * {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} should return
1108     * empty list when no network selection has been made.
1109     *
1110     * Expected behavior: return empty list
1111     */
1112    @Test
1113    public void getfilterOpenUnsavedNetworks_returnsEmptyListWhenNoNetworkSelectionMade() {
1114        assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks().isEmpty());
1115    }
1116
1117    /**
1118     * {@link WifiNetworkSelector#getFilteredScanDetailsForCarrierUnsavedNetworks()} should filter
1119     * out networks that are not EAP after network selection is made.
1120     *
1121     * Expected behavior: return EAP networks only
1122     */
1123    @Test
1124    public void getfilterCarrierUnsavedNetworks_filtersForEapNetworks() {
1125        String[] ssids = {"\"test1\"", "\"test2\""};
1126        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
1127        int[] freqs = {2437, 5180};
1128        String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]"};
1129        int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
1130        mDummyEvaluator.setEvaluatorToSelectCandidate(false);
1131
1132        List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
1133                ssids, bssids, freqs, caps, levels, mClock);
1134        HashSet<String> blacklist = new HashSet<>();
1135
1136        mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
1137        List<ScanDetail> expectedCarrierUnsavedNetworks = new ArrayList<>();
1138        expectedCarrierUnsavedNetworks.add(scanDetails.get(0));
1139        assertEquals("Expect carrier unsaved networks",
1140                expectedCarrierUnsavedNetworks,
1141                mWifiNetworkSelector.getFilteredScanDetailsForCarrierUnsavedNetworks(
1142                        mCarrierNetworkConfig));
1143    }
1144
1145    /**
1146     * {@link WifiNetworkSelector#getFilteredScanDetailsForCarrierUnsavedNetworks()} should filter
1147     * out saved networks after network selection is made. This should return an empty list when
1148     * there are no unsaved networks available.
1149     *
1150     * Expected behavior: return unsaved networks only. Return empty list if there are no unsaved
1151     * networks.
1152     */
1153    @Test
1154    public void getfilterCarrierUnsavedNetworks_filtersOutSavedNetworks() {
1155        String[] ssids = {"\"test1\""};
1156        String[] bssids = {"6c:f3:7f:ae:8c:f3"};
1157        int[] freqs = {2437, 5180};
1158        String[] caps = {"[EAP][ESS]"};
1159        int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP};
1160        int[] securities = {SECURITY_EAP};
1161        mDummyEvaluator.setEvaluatorToSelectCandidate(false);
1162
1163        List<ScanDetail> unSavedScanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
1164                ssids, bssids, freqs, caps, levels, mClock);
1165        HashSet<String> blacklist = new HashSet<>();
1166
1167        mWifiNetworkSelector.selectNetwork(
1168                unSavedScanDetails, blacklist, mWifiInfo, false, true, false);
1169        assertEquals("Expect carrier unsaved networks",
1170                unSavedScanDetails,
1171                mWifiNetworkSelector.getFilteredScanDetailsForCarrierUnsavedNetworks(
1172                        mCarrierNetworkConfig));
1173
1174        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
1175                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
1176                        freqs, caps, levels, securities, mWifiConfigManager, mClock);
1177        List<ScanDetail> savedScanDetails = scanDetailsAndConfigs.getScanDetails();
1178
1179        mWifiNetworkSelector.selectNetwork(
1180                savedScanDetails, blacklist, mWifiInfo, false, true, false);
1181        // Saved networks are filtered out.
1182        assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForCarrierUnsavedNetworks(
1183                mCarrierNetworkConfig).isEmpty());
1184    }
1185
1186    /**
1187     * {@link WifiNetworkSelector#getFilteredScanDetailsForCarrierUnsavedNetworks()} should filter
1188     * out bssid blacklisted networks.
1189     *
1190     * Expected behavior: do not return blacklisted network
1191     */
1192    @Test
1193    public void getfilterCarrierUnsavedNetworks_filtersOutBlacklistedNetworks() {
1194        String[] ssids = {"\"test1\"", "\"test2\""};
1195        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
1196        int[] freqs = {2437, 5180};
1197        String[] caps = {"[EAP][ESS]", "[EAP]"};
1198        int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
1199        mDummyEvaluator.setEvaluatorToSelectCandidate(false);
1200
1201        List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
1202                ssids, bssids, freqs, caps, levels, mClock);
1203        HashSet<String> blacklist = new HashSet<>();
1204        blacklist.add(bssids[0]);
1205
1206        mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
1207        List<ScanDetail> expectedCarrierUnsavedNetworks = new ArrayList<>();
1208        expectedCarrierUnsavedNetworks.add(scanDetails.get(1));
1209        assertEquals("Expect carrier unsaved networks",
1210                expectedCarrierUnsavedNetworks,
1211                mWifiNetworkSelector.getFilteredScanDetailsForCarrierUnsavedNetworks(
1212                        mCarrierNetworkConfig));
1213    }
1214
1215    /**
1216     * {@link WifiNetworkSelector#getFilteredScanDetailsForCarrierUnsavedNetworks()} should return
1217     * empty list when there are no EAP encrypted networks after network selection is made.
1218     *
1219     * Expected behavior: return empty list
1220     */
1221    @Test
1222    public void getfilterCarrierUnsavedNetworks_returnsEmptyListWhenNoEAPNetworksPresent() {
1223        String[] ssids = {"\"test1\"", "\"test2\""};
1224        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
1225        int[] freqs = {2437, 5180};
1226        String[] caps = {"[ESS]", "[WPA2-CCMP][ESS]"};
1227        int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
1228        mDummyEvaluator.setEvaluatorToSelectCandidate(false);
1229
1230        List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
1231                ssids, bssids, freqs, caps, levels, mClock);
1232        HashSet<String> blacklist = new HashSet<>();
1233
1234        mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
1235        assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForCarrierUnsavedNetworks(
1236                mCarrierNetworkConfig).isEmpty());
1237    }
1238
1239    /**
1240     * {@link WifiNetworkSelector#getFilteredScanDetailsForCarrierUnsavedNetworks()} should return
1241     * empty list when there are no carrier networks after network selection is made.
1242     *
1243     * Expected behavior: return empty list
1244     */
1245    @Test
1246    public void getfilterCarrierUnsavedNetworks_returnsEmptyListWhenNoCarrierNetworksPresent() {
1247        String[] ssids = {"\"test1\"", "\"test2\""};
1248        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
1249        int[] freqs = {2437, 5180};
1250        String[] caps = {"[EAP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
1251        int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
1252        mDummyEvaluator.setEvaluatorToSelectCandidate(false);
1253
1254        List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
1255                ssids, bssids, freqs, caps, levels, mClock);
1256        HashSet<String> blacklist = new HashSet<>();
1257
1258        mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
1259
1260        when(mCarrierNetworkConfig.isCarrierNetwork(any())).thenReturn(false);
1261        assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForCarrierUnsavedNetworks(
1262                mCarrierNetworkConfig).isEmpty());
1263    }
1264
1265    /**
1266     * {@link WifiNetworkSelector#getFilteredScanDetailsForCarrierUnsavedNetworks()} should return
1267     * empty list when no network selection has been made.
1268     *
1269     * Expected behavior: return empty list
1270     */
1271    @Test
1272    public void getfilterCarrierUnsavedNetworks_returnsEmptyListWhenNoNetworkSelectionMade() {
1273        assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForCarrierUnsavedNetworks(
1274                mCarrierNetworkConfig).isEmpty());
1275    }
1276}
1277
1278