Home | History | Annotate | Download | only in wifi
      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 
     17 package com.android.server.wifi;
     18 
     19 import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_EAP;
     20 import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_NONE;
     21 import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_PSK;
     22 
     23 import static org.junit.Assert.*;
     24 import static org.mockito.Mockito.*;
     25 
     26 import android.content.Context;
     27 import android.net.wifi.ScanResult;
     28 import android.net.wifi.WifiConfiguration;
     29 import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
     30 import android.net.wifi.WifiInfo;
     31 import android.os.SystemClock;
     32 import android.support.test.filters.SmallTest;
     33 import android.util.LocalLog;
     34 import android.util.Pair;
     35 
     36 import com.android.internal.R;
     37 import com.android.server.wifi.WifiNetworkSelectorTestUtil.ScanDetailsAndWifiConfigs;
     38 
     39 import org.junit.After;
     40 import org.junit.Before;
     41 import org.junit.Test;
     42 import org.mockito.Mock;
     43 import org.mockito.MockitoAnnotations;
     44 import org.mockito.Spy;
     45 
     46 import java.util.ArrayList;
     47 import java.util.HashSet;
     48 import java.util.List;
     49 
     50 /**
     51  * Unit tests for {@link com.android.server.wifi.WifiNetworkSelector}.
     52  */
     53 @SmallTest
     54 public 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