Home | History | Annotate | Download | only in wifi
      1 /*
      2  * Copyright (C) 2015 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 import static com.android.server.wifi.WifiConfigurationTestUtil.generateWifiConfig;
     23 
     24 import static org.junit.Assert.assertEquals;
     25 import static org.junit.Assert.assertSame;
     26 import static org.mockito.Matchers.any;
     27 import static org.mockito.Matchers.anyBoolean;
     28 import static org.mockito.Matchers.anyInt;
     29 import static org.mockito.Matchers.eq;
     30 import static org.mockito.Mockito.mock;
     31 import static org.mockito.Mockito.validateMockitoUsage;
     32 import static org.mockito.Mockito.verify;
     33 import static org.mockito.Mockito.when;
     34 
     35 import android.content.Context;
     36 import android.content.res.Resources;
     37 import android.net.NetworkScoreManager;
     38 import android.net.wifi.ScanResult;
     39 import android.net.wifi.WifiConfiguration;
     40 import android.net.wifi.WifiEnterpriseConfig;
     41 import android.net.wifi.WifiInfo;
     42 import android.net.wifi.WifiSsid;
     43 import android.os.SystemClock;
     44 import android.test.suitebuilder.annotation.SmallTest;
     45 import android.util.LocalLog;
     46 
     47 import com.android.internal.R;
     48 import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments;
     49 
     50 import org.junit.After;
     51 import org.junit.Before;
     52 import org.junit.Test;
     53 
     54 import java.util.ArrayList;
     55 import java.util.Arrays;
     56 import java.util.HashMap;
     57 import java.util.List;
     58 import java.util.concurrent.atomic.AtomicInteger;
     59 
     60 /**
     61  * Unit tests for {@link com.android.server.wifi.WifiQualifiedNetworkSelector}.
     62  */
     63 @SmallTest
     64 public class WifiQualifiedNetworkSelectorTest {
     65 
     66     @Before
     67     public void setUp() throws Exception {
     68         mResource = getResource();
     69         mScoreManager = getNetworkScoreManager();
     70         mScoreCache = getScoreCache();
     71         mContext = getContext();
     72         mWifiConfigManager = getWifiConfigManager();
     73         mWifiInfo = getWifiInfo();
     74         mLocalLog = getLocalLog();
     75 
     76         mWifiQualifiedNetworkSelector = new WifiQualifiedNetworkSelector(mWifiConfigManager,
     77                 mContext, mWifiInfo, mClock);
     78         mWifiQualifiedNetworkSelector.enableVerboseLogging(1);
     79         mWifiQualifiedNetworkSelector.setUserPreferredBand(1);
     80         mWifiQualifiedNetworkSelector.setWifiNetworkScoreCache(mScoreCache);
     81         when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime());
     82     }
     83 
     84     @After
     85     public void cleanup() {
     86         validateMockitoUsage();
     87     }
     88 
     89     private WifiQualifiedNetworkSelector mWifiQualifiedNetworkSelector = null;
     90     private WifiConfigManager mWifiConfigManager = null;
     91     private Context mContext;
     92     private Resources mResource;
     93     private NetworkScoreManager mScoreManager;
     94     private WifiNetworkScoreCache mScoreCache;
     95     private WifiInfo mWifiInfo;
     96     private LocalLog mLocalLog;
     97     private Clock mClock = mock(Clock.class);
     98     private static final String[] DEFAULT_SSIDS = {"\"test1\"", "\"test2\""};
     99     private static final String[] DEFAULT_BSSIDS = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
    100     private static final String TAG = "QNS Unit Test";
    101 
    102     private List<ScanDetail> getScanDetails(String[] ssids, String[] bssids, int[] frequencies,
    103                                             String[] caps, int[] levels) {
    104         List<ScanDetail> scanDetailList = new ArrayList<ScanDetail>();
    105         long timeStamp = mClock.elapsedRealtime();
    106         for (int index = 0; index < ssids.length; index++) {
    107             ScanDetail scanDetail = new ScanDetail(WifiSsid.createFromAsciiEncoded(ssids[index]),
    108                     bssids[index], caps[index], levels[index], frequencies[index], timeStamp, 0);
    109             scanDetailList.add(scanDetail);
    110         }
    111         return scanDetailList;
    112     }
    113 
    114     Context getContext() {
    115         Context context = mock(Context.class);
    116         Resources resource = mock(Resources.class);
    117 
    118         when(context.getResources()).thenReturn(mResource);
    119         when(context.getSystemService(Context.NETWORK_SCORE_SERVICE)).thenReturn(mScoreManager);
    120         return context;
    121     }
    122 
    123     Resources getResource() {
    124         Resources resource = mock(Resources.class);
    125 
    126         when(resource.getInteger(R.integer.config_wifi_framework_SECURITY_AWARD)).thenReturn(80);
    127         when(resource.getInteger(R.integer.config_wifi_framework_RSSI_SCORE_OFFSET)).thenReturn(85);
    128         when(resource.getInteger(R.integer.config_wifi_framework_SAME_BSSID_AWARD)).thenReturn(24);
    129         when(resource.getInteger(R.integer.config_wifi_framework_LAST_SELECTION_AWARD))
    130                 .thenReturn(480);
    131         when(resource.getInteger(R.integer.config_wifi_framework_PASSPOINT_SECURITY_AWARD))
    132                 .thenReturn(40);
    133         when(resource.getInteger(R.integer.config_wifi_framework_SECURITY_AWARD)).thenReturn(80);
    134         when(resource.getInteger(R.integer.config_wifi_framework_RSSI_SCORE_SLOPE)).thenReturn(4);
    135         return resource;
    136     }
    137 
    138     NetworkScoreManager getNetworkScoreManager() {
    139         NetworkScoreManager networkScoreManager = mock(NetworkScoreManager.class);
    140 
    141         return networkScoreManager;
    142     }
    143 
    144     WifiNetworkScoreCache getScoreCache() {
    145         return mock(WifiNetworkScoreCache.class);
    146     }
    147 
    148     LocalLog getLocalLog() {
    149         return new LocalLog(0);
    150     }
    151 
    152     WifiInfo getWifiInfo() {
    153         WifiInfo wifiInfo = mock(WifiInfo.class);
    154 
    155         //simulate a disconnected state
    156         when(wifiInfo.is24GHz()).thenReturn(true);
    157         when(wifiInfo.is5GHz()).thenReturn(false);
    158         when(wifiInfo.getRssi()).thenReturn(-70);
    159         when(wifiInfo.getNetworkId()).thenReturn(WifiConfiguration.INVALID_NETWORK_ID);
    160         when(wifiInfo.getBSSID()).thenReturn(null);
    161         when(wifiInfo.getNetworkId()).thenReturn(-1);
    162         return wifiInfo;
    163     }
    164 
    165     WifiConfigManager getWifiConfigManager() {
    166         WifiConfigManager wifiConfigManager = mock(WifiConfigManager.class);
    167         wifiConfigManager.mThresholdSaturatedRssi24 = new AtomicInteger(
    168                 WifiQualifiedNetworkSelector.RSSI_SATURATION_2G_BAND);
    169         wifiConfigManager.mBandAward5Ghz = new AtomicInteger(
    170                 WifiQualifiedNetworkSelector.BAND_AWARD_5GHz);
    171         wifiConfigManager.mCurrentNetworkBoost = new AtomicInteger(
    172                 WifiQualifiedNetworkSelector.SAME_NETWORK_AWARD);
    173         wifiConfigManager.mThresholdQualifiedRssi5 = new AtomicInteger(
    174                 WifiQualifiedNetworkSelector.QUALIFIED_RSSI_5G_BAND);
    175         wifiConfigManager.mThresholdMinimumRssi24 = new AtomicInteger(
    176                 WifiQualifiedNetworkSelector.MINIMUM_2G_ACCEPT_RSSI);
    177         wifiConfigManager.mThresholdMinimumRssi5 = new AtomicInteger(
    178                 WifiQualifiedNetworkSelector.MINIMUM_5G_ACCEPT_RSSI);
    179 
    180         when(wifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true);
    181         return wifiConfigManager;
    182     }
    183 
    184     /**
    185      * This API is used to generate multiple simulated saved configurations used for test
    186      *
    187      * @param ssid     array of SSID of saved configuration
    188      * @param security array  of securities of  saved configuration
    189      * @return generated new array of configurations based on input
    190      */
    191     private WifiConfiguration[] generateWifiConfigurations(String[] ssid, int[] security) {
    192         if (ssid == null || security == null || ssid.length != security.length
    193                 || ssid.length == 0) {
    194             return null;
    195         }
    196 
    197         WifiConfiguration[] configs = new WifiConfiguration[ssid.length];
    198         for (int index = 0; index < ssid.length; index++) {
    199             configs[index] = generateWifiConfig(index, 0, ssid[index], false, true, null, null,
    200                     security[index]);
    201         }
    202 
    203         return configs;
    204     }
    205 
    206     /**
    207      * set configuration to a passpoint configuration
    208      *
    209      * @param config The configuration need to be set as a passipoint configuration
    210      */
    211     private void setConfigPasspoint(WifiConfiguration config) {
    212         config.FQDN = "android.qns.unitTest";
    213         config.providerFriendlyName = "android.qns.unitTest";
    214         WifiEnterpriseConfig enterpriseConfig = mock(WifiEnterpriseConfig.class);
    215         when(enterpriseConfig.getEapMethod()).thenReturn(WifiEnterpriseConfig.Eap.PEAP);
    216 
    217     }
    218 
    219     /**
    220      * add the Configurations to WifiConfigManager (WifiConfigureStore can take them out according
    221      * to the networkd ID)
    222      *
    223      * @param configs input configuration need to be added to WifiConfigureStore
    224      */
    225     private void prepareConfigStore(final WifiConfiguration[] configs) {
    226         when(mWifiConfigManager.getWifiConfiguration(anyInt()))
    227                 .then(new AnswerWithArguments() {
    228                     public WifiConfiguration answer(int netId) {
    229                         if (netId >= 0 && netId < configs.length) {
    230                             return configs[netId];
    231                         } else {
    232                             return null;
    233                         }
    234                     }
    235                 });
    236     }
    237 
    238     /**
    239      * Link scan results to the saved configurations.
    240      *
    241      * The shorter of the 2 input params will be used to loop over so the inputs don't
    242      * need to be of equal length. If there are more scan details then configs the remaining scan
    243      * details will be associated with a NULL config.
    244      *
    245      * @param configs     saved configurations
    246      * @param scanDetails come in scan results
    247      */
    248     private void scanResultLinkConfiguration(WifiConfiguration[] configs,
    249                                              List<ScanDetail> scanDetails) {
    250         if (scanDetails.size() <= configs.length) {
    251             for (int i = 0; i < scanDetails.size(); i++) {
    252                 ScanDetail scanDetail = scanDetails.get(i);
    253                 List<WifiConfiguration> associateWithScanResult = new ArrayList<>();
    254                 associateWithScanResult.add(configs[i]);
    255                 when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(eq(scanDetail),
    256                         anyBoolean())).thenReturn(associateWithScanResult);
    257             }
    258         } else {
    259             for (int i = 0; i < configs.length; i++) {
    260                 ScanDetail scanDetail = scanDetails.get(i);
    261                 List<WifiConfiguration> associateWithScanResult = new ArrayList<>();
    262                 associateWithScanResult.add(configs[i]);
    263                 when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(eq(scanDetail),
    264                         anyBoolean())).thenReturn(associateWithScanResult);
    265             }
    266 
    267             // associated the remaining scan details with a NULL config.
    268             for (int i = configs.length; i < scanDetails.size(); i++) {
    269                 when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(eq(scanDetails.get(i)),
    270                         anyBoolean())).thenReturn(null);
    271             }
    272         }
    273     }
    274 
    275     private void configureScoreCache(List<ScanDetail> scanDetails, Integer[] scores,
    276             boolean[] meteredHints) {
    277         for (int i = 0; i < scanDetails.size(); i++) {
    278             ScanDetail scanDetail = scanDetails.get(i);
    279             Integer score = scores[i];
    280             ScanResult scanResult = scanDetail.getScanResult();
    281             if (score != null) {
    282                 when(mScoreCache.isScoredNetwork(scanResult)).thenReturn(true);
    283                 when(mScoreCache.hasScoreCurve(scanResult)).thenReturn(true);
    284                 when(mScoreCache.getNetworkScore(eq(scanResult), anyBoolean())).thenReturn(score);
    285                 when(mScoreCache.getNetworkScore(scanResult)).thenReturn(score);
    286             } else {
    287                 when(mScoreCache.isScoredNetwork(scanResult)).thenReturn(false);
    288                 when(mScoreCache.hasScoreCurve(scanResult)).thenReturn(false);
    289                 when(mScoreCache.getNetworkScore(eq(scanResult), anyBoolean())).thenReturn(
    290                         WifiNetworkScoreCache.INVALID_NETWORK_SCORE);
    291                 when(mScoreCache.getNetworkScore(scanResult)).thenReturn(
    292                         WifiNetworkScoreCache.INVALID_NETWORK_SCORE);
    293             }
    294             when(mScoreCache.getMeteredHint(scanResult)).thenReturn(meteredHints[i]);
    295         }
    296     }
    297 
    298     /**
    299      * verify whether the chosen configuration matched with the expected chosen scan result
    300      *
    301      * @param chosenScanResult the expected chosen scan result
    302      * @param candidate        the chosen configuration
    303      */
    304     private void verifySelectedResult(ScanResult chosenScanResult, WifiConfiguration candidate) {
    305         ScanResult candidateScan = candidate.getNetworkSelectionStatus().getCandidate();
    306         assertEquals("choose the wrong SSID", chosenScanResult.SSID, candidate.SSID);
    307         assertEquals("choose the wrong BSSID", chosenScanResult.BSSID, candidateScan.BSSID);
    308     }
    309 
    310     // QNS test under disconnected State
    311 
    312     /**
    313      * Case #1    choose 2GHz stronger RSSI test
    314      *
    315      * In this test. we simulate following scenario
    316      * WifiStateMachine is under disconnected state
    317      * Two networks test1, test2 are secured network
    318      * Both network are enabled, encrypted and at 2.4 GHz
    319      * test1 is with RSSI -70 test2 is with RSSI -60
    320      *
    321      * Expected behavior: test2 is chosen
    322      */
    323     @Test
    324     public void chooseNetworkDisconnected2GHighestRssi() {
    325         String[] ssids = DEFAULT_SSIDS;
    326         String[] bssids = DEFAULT_BSSIDS;
    327         int[] frequencies = {2437, 2417};
    328         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
    329         int[] levels = {-70, -60};
    330         int[] security = {SECURITY_PSK, SECURITY_PSK};
    331 
    332         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
    333 
    334         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
    335         prepareConfigStore(savedConfigs);
    336 
    337         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
    338         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
    339 
    340         scanResultLinkConfiguration(savedConfigs, scanDetails);
    341 
    342         ScanResult chosenScanResult = scanDetails.get(scanDetails.size() - 1).getScanResult();
    343 
    344         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
    345                 false, scanDetails, false, false, true, false);
    346 
    347         verifySelectedResult(chosenScanResult, candidate);
    348     }
    349 
    350     /**
    351      * Case #2    choose 5GHz Stronger RSSI Test
    352      *
    353      * In this test. we simulate following scenario
    354      * WifiStateMachine is under disconnected state
    355      * Two networks test1, test2 are secured network
    356      * Both network are enabled, encrypted and at 5 GHz
    357      * test1 is with RSSI -70 test2 is with RSSI -60
    358      *
    359      * Expected behavior: test2 is chosen
    360      */
    361     @Test
    362     public void chooseNetworkDisconnected5GHighestRssi() {
    363         String[] ssids = DEFAULT_SSIDS;
    364         String[] bssids = DEFAULT_BSSIDS;
    365         int[] frequencies = {5180, 5610};
    366         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
    367         int[] levels = {-70, -60};
    368         int[] security = {SECURITY_PSK, SECURITY_PSK};
    369 
    370         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
    371 
    372         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
    373         prepareConfigStore(savedConfigs);
    374 
    375         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
    376         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
    377         scanResultLinkConfiguration(savedConfigs, scanDetails);
    378 
    379         ScanResult chosenScanResult = scanDetails.get(scanDetails.size() - 1).getScanResult();
    380 
    381         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
    382                 false, scanDetails, false, false, true, false);
    383 
    384         verifySelectedResult(chosenScanResult, candidate);
    385     }
    386 
    387     /**
    388      * Case #3    5GHz over 2GHz bonus Test
    389      *
    390      * In this test. we simulate following scenario
    391      * WifiStateMachine is under disconnected state
    392      * Two networks test1, test2 are secured network
    393      * Both network are enabled
    394      * test1 is @ 2GHz with RSSI -60
    395      * test2 is @ 5Ghz with RSSI -65
    396      *
    397      * Expected behavior: test2 is chosen due to 5GHz bonus
    398      */
    399     @Test
    400     public void chooseNetworkDisconnect5GOver2GTest() {
    401         String[] ssids = DEFAULT_SSIDS;
    402         String[] bssids = DEFAULT_BSSIDS;
    403         int[] frequencies = {2437, 5180};
    404         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
    405         int[] levels = {-60, -65};
    406         int[] security = {SECURITY_PSK, SECURITY_PSK};
    407 
    408         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
    409         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
    410         prepareConfigStore(savedConfigs);
    411 
    412         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
    413         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
    414         scanResultLinkConfiguration(savedConfigs, scanDetails);
    415         ScanResult chosenScanResult = scanDetails.get(scanDetails.size() - 1).getScanResult();
    416 
    417         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
    418                 false, scanDetails, false, false, true, false);
    419 
    420         verifySelectedResult(chosenScanResult, candidate);
    421     }
    422 
    423     /**
    424      * Case #4    2GHz over 5GHz dur to 5GHz signal too weak test
    425      *
    426      * In this test. we simulate following scenario
    427      * WifiStateMachine is under disconnected state
    428      * Two networks test1, test2 are secured network
    429      * Both network are enabled
    430      * test1 is @ 2GHz with RSSI -60
    431      * test2 is @ 5Ghz with RSSI -75
    432      *
    433      * Expected behavior: test1 is chosen due to 5GHz signal is too weak (5GHz bonus can not
    434      * compensate)
    435      */
    436     @Test
    437     public void chooseNetworkDisconnect2GOver5GTest() {
    438         String[] ssids = DEFAULT_SSIDS;
    439         String[] bssids = DEFAULT_BSSIDS;
    440         int[] frequencies = {2437, 5180};
    441         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
    442         int[] levels = {-60, -75};
    443         int[] security = {SECURITY_PSK, SECURITY_PSK};
    444 
    445         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
    446         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
    447         prepareConfigStore(savedConfigs);
    448 
    449         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
    450         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
    451         scanResultLinkConfiguration(savedConfigs, scanDetails);
    452         ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
    453 
    454         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
    455                 false, scanDetails, false, false, true, false);
    456 
    457         verifySelectedResult(chosenScanResult, candidate);
    458     }
    459 
    460     /**
    461      * Case #5    2GHz signal Saturation test
    462      *
    463      * In this test. we simulate following scenario
    464      * WifiStateMachine is under disconnected state
    465      * Two networks test1, test2 are secured network
    466      * Both network are enabled
    467      * test1 is @ 2GHz with RSSI -50
    468      * test2 is @ 5Ghz with RSSI -65
    469      *
    470      * Expected behavior: test2 is chosen. Although the RSSI delta here is 15 too, because 2GHz RSSI
    471      * saturates at -60, the real RSSI delta is only 5, which is less than 5GHz bonus
    472      */
    473     @Test
    474     public void chooseNetworkDisconnect2GRssiSaturationTest() {
    475         String[] ssids = DEFAULT_SSIDS;
    476         String[] bssids = DEFAULT_BSSIDS;
    477         int[] frequencies = {2437, 5180};
    478         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
    479         int[] levels = {-50, -65};
    480         int[] security = {SECURITY_PSK, SECURITY_PSK};
    481 
    482         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
    483         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
    484         prepareConfigStore(savedConfigs);
    485 
    486         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
    487         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
    488         scanResultLinkConfiguration(savedConfigs, scanDetails);
    489         ScanResult chosenScanResult = scanDetails.get(scanDetails.size() - 1).getScanResult();
    490 
    491         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
    492                 false, scanDetails, false, false, true, false);
    493 
    494         verifySelectedResult(chosenScanResult, candidate);
    495     }
    496 
    497     /**
    498      * Case #6    Minimum RSSI test
    499      *
    500      * In this test. we simulate following scenario
    501      * WifiStateMachine is under disconnected state
    502      * Two networks test1, test2 are secured network
    503      * Both network are enabled
    504      * test1 is @ 2GHz with RSSI -86
    505      * test2 is @ 5Ghz with RSSI -83
    506      *
    507      * Expected behavior: no QNS is made because both network are below the minimum threshold, null
    508      */
    509     @Test
    510     public void chooseNetworkMinimumRssiTest() {
    511         String[] ssids = DEFAULT_SSIDS;
    512         String[] bssids = DEFAULT_BSSIDS;
    513         int[] frequencies = {2437, 5180};
    514         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
    515         int[] levels = {WifiQualifiedNetworkSelector.MINIMUM_2G_ACCEPT_RSSI - 1,
    516                 WifiQualifiedNetworkSelector.MINIMUM_5G_ACCEPT_RSSI - 1};
    517         int[] security = {SECURITY_EAP, SECURITY_PSK};
    518 
    519         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
    520         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
    521         prepareConfigStore(savedConfigs);
    522 
    523         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
    524         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
    525         scanResultLinkConfiguration(savedConfigs, scanDetails);
    526 
    527         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
    528                 false, scanDetails, false, false, true, false);
    529 
    530         assertEquals("choose the wrong SSID", null, candidate);
    531     }
    532 
    533     /**
    534      * Case #7    encrypted network over passpoint network
    535      *
    536      * In this test. we simulate following scenario
    537      * WifiStateMachine is under disconnected state
    538      * Two networks test1 is secured network, test2 are passpoint network
    539      * Both network are enabled and at 2.4 GHz. Both have RSSI of -70
    540      *
    541      * Expected behavior: test1 is chosen since secured network has higher priority than passpoint
    542      * network
    543      */
    544     @Test
    545     public void chooseNetworkSecurityOverPassPoint() {
    546         String[] ssids = DEFAULT_SSIDS;
    547         String[] bssids = DEFAULT_BSSIDS;
    548         int[] frequencies = {2437, 2437};
    549         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]"};
    550         int[] levels = {-70, -70};
    551         int[] security = {SECURITY_EAP, SECURITY_NONE};
    552 
    553         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
    554         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
    555         setConfigPasspoint(savedConfigs[1]);
    556         prepareConfigStore(savedConfigs);
    557 
    558         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
    559         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
    560         scanResultLinkConfiguration(savedConfigs, scanDetails);
    561         ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
    562 
    563         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
    564                 false, scanDetails, false, false, true, false);
    565 
    566         verifySelectedResult(chosenScanResult, candidate);
    567     }
    568 
    569     /**
    570      * Case #8    passpoint network over open network
    571      *
    572      * In this test. we simulate following scenario
    573      * WifiStateMachine is under disconnected state
    574      * Two networks test1 is passpoint network, test2 is open network
    575      * Both network are enabled and at 2.4 GHz. Both have RSSI of -70
    576      *
    577      * Expected behavior: test1 is chosen since passpoint network has higher priority than open
    578      * network
    579      */
    580     @Test
    581     public void chooseNetworkPasspointOverOpen() {
    582         String[] ssids = {"\"test1\"", "\"test2\""};
    583         String[] bssids = {"6c:f3:7f:ae:8c:f8", "6c:f3:7f:ae:8c:f4"};
    584         int[] frequencies = {2437, 2437};
    585         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
    586         int[] levels = {-70, -70};
    587         int[] security = {SECURITY_NONE, SECURITY_NONE};
    588 
    589         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
    590         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
    591         setConfigPasspoint(savedConfigs[0]);
    592         prepareConfigStore(savedConfigs);
    593 
    594         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
    595         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
    596         scanResultLinkConfiguration(savedConfigs, scanDetails);
    597         ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
    598 
    599         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
    600                 false, scanDetails, false, false, true, false);
    601 
    602         verifySelectedResult(chosenScanResult, candidate);
    603     }
    604 
    605     /**
    606      * Case #9    secure network over open network
    607      *
    608      * In this test. we simulate following scenario
    609      * WifiStateMachine is under disconnected state
    610      * Two networks test1 is secure network, test2 is open network
    611      * Both network are enabled and at 2.4 GHz. Both have RSSI of -70
    612      *
    613      * Expected behavior: test1 is chosen since secured network has higher priority than open
    614      * network
    615      */
    616     @Test
    617     public void chooseNetworkSecureOverOpen() {
    618         String[] ssids = DEFAULT_SSIDS;
    619         String[] bssids = DEFAULT_BSSIDS;
    620         int[] frequencies = {2437, 2437};
    621         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
    622         int[] levels = {-70, -70};
    623         int[] security = {SECURITY_PSK, SECURITY_NONE};
    624 
    625         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
    626         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
    627         prepareConfigStore(savedConfigs);
    628 
    629         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
    630         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
    631         scanResultLinkConfiguration(savedConfigs, scanDetails);
    632         ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
    633 
    634         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
    635                 false, scanDetails, false, false, true, false);
    636         verifySelectedResult(chosenScanResult, candidate);
    637     }
    638 
    639     /**
    640      * Case #10    first time user select a network
    641      *
    642      * In this test. we simulate following scenario
    643      * There are three saved networks: test1, test2 and test3. Now user select the network test3
    644      * check test3 has been saved in test1's and test2's ConnectChoice
    645      *
    646      * Expected behavior: test1's and test2's ConnectChoice should be test3, test3's ConnectChoice
    647      * should be null
    648      */
    649     @Test
    650     public void userSelectsNetworkForFirstTime() {
    651         String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\""};
    652         int[] security = {SECURITY_PSK, SECURITY_PSK, SECURITY_NONE};
    653 
    654         final WifiConfiguration[] configs = generateWifiConfigurations(ssids, security);
    655         prepareConfigStore(configs);
    656         when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(configs));
    657         for (WifiConfiguration network : configs) {
    658             WifiConfiguration.NetworkSelectionStatus status = network.getNetworkSelectionStatus();
    659             status.setSeenInLastQualifiedNetworkSelection(true);
    660         }
    661 
    662         mWifiQualifiedNetworkSelector.userSelectNetwork(configs.length - 1, true);
    663         String key = configs[configs.length - 1].configKey();
    664         for (int index = 0; index < configs.length; index++) {
    665             WifiConfiguration config = configs[index];
    666             WifiConfiguration.NetworkSelectionStatus status = config.getNetworkSelectionStatus();
    667             if (index == configs.length - 1) {
    668                 assertEquals("User selected network should not have prefernce over it", null,
    669                         status.getConnectChoice());
    670             } else {
    671                 assertEquals("Wrong user preference", key, status.getConnectChoice());
    672             }
    673         }
    674     }
    675 
    676     /**
    677      * Case #11    choose user selected network
    678      *
    679      * In this test, we simulate following scenario:
    680      * WifiStateMachine is under disconnected state
    681      * There are three networks: test1, test2, test3 and test3 is the user preference
    682      * All three networks are enabled
    683      * test1 is @ 2.4GHz with RSSI -50 PSK
    684      * test2 is @ 5Ghz with RSSI -65 PSK
    685      * test3 is @ 2.4GHz with RSSI -55 open
    686      *
    687      * Expected behavior: test3 is chosen since it is user selected network. It overcome all other
    688      * priorities
    689      */
    690     @Test
    691     public void chooseUserPreferredNetwork() {
    692         String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\""};
    693         int[] security = {SECURITY_PSK, SECURITY_PSK, SECURITY_NONE};
    694 
    695         final WifiConfiguration[] configs = generateWifiConfigurations(ssids, security);
    696         prepareConfigStore(configs);
    697         for (WifiConfiguration network : configs) {
    698             WifiConfiguration.NetworkSelectionStatus status = network.getNetworkSelectionStatus();
    699             status.setSeenInLastQualifiedNetworkSelection(true);
    700         }
    701 
    702         when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(configs));
    703 
    704         //set user preference
    705         mWifiQualifiedNetworkSelector.userSelectNetwork(ssids.length - 1, true);
    706         //Generate mocked recent scan results
    707         String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "6c:f3:7f:ae:8c:f5"};
    708         int[] frequencies = {2437, 5180, 2437};
    709         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]", "NONE"};
    710         int[] levels = {-50, -65, -55};
    711 
    712         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
    713         scanResultLinkConfiguration(configs, scanDetails);
    714 
    715         ScanResult chosenScanResult = scanDetails.get(scanDetails.size() - 1).getScanResult();
    716         when(mWifiConfigManager.getWifiConfiguration(configs[2].configKey()))
    717                 .thenReturn(configs[2]);
    718 
    719         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
    720                 false, scanDetails, false, false, true, false);
    721         verifySelectedResult(chosenScanResult, candidate);
    722     }
    723 
    724     /**
    725      * Case #12    enable a blacklisted BSSID
    726      *
    727      * In this test, we simulate following scenario:
    728      * For two Aps, BSSIDA and BSSIDB. Disable BSSIDA, then check whether BSSIDA is disabled and
    729      * BSSIDB is enabled. Then enable BSSIDA, check whether both BSSIDs are enabled.
    730      */
    731     @Test
    732     public void enableBssidTest() {
    733         String bssidA = "6c:f3:7f:ae:8c:f3";
    734         String bssidB = "6c:f3:7f:ae:8c:f4";
    735         //check by default these two BSSIDs should be enabled
    736         assertEquals("bssidA should be enabled by default",
    737                 mWifiQualifiedNetworkSelector.isBssidDisabled(bssidA), false);
    738         assertEquals("bssidB should be enabled by default",
    739                 mWifiQualifiedNetworkSelector.isBssidDisabled(bssidB), false);
    740 
    741         //disable bssidA 3 times, check whether A is dsiabled and B is still enabled
    742         mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssidA, false);
    743         assertEquals("bssidA should be disabled",
    744                 mWifiQualifiedNetworkSelector.isBssidDisabled(bssidA), false);
    745         mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssidA, false);
    746         assertEquals("bssidA should be disabled",
    747                 mWifiQualifiedNetworkSelector.isBssidDisabled(bssidA), false);
    748         mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssidA, false);
    749         assertEquals("bssidA should be disabled",
    750                 mWifiQualifiedNetworkSelector.isBssidDisabled(bssidA), true);
    751         assertEquals("bssidB should still be enabled",
    752                 mWifiQualifiedNetworkSelector.isBssidDisabled(bssidB), false);
    753 
    754         //re-enable bssidA, check whether A is dsiabled and B is still enabled
    755         mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssidA, true);
    756         assertEquals("bssidA should be enabled by default",
    757                 mWifiQualifiedNetworkSelector.isBssidDisabled(bssidA), false);
    758         assertEquals("bssidB should be enabled by default",
    759                 mWifiQualifiedNetworkSelector.isBssidDisabled(bssidB), false);
    760 
    761         //make sure illegal input will not cause crash
    762         mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(null, false);
    763         mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(null, true);
    764     }
    765 
    766     /**
    767      * Case #13    do not choose the BSSID has been disabled
    768      *
    769      * In this test. we simulate following scenario:
    770      * WifiStateMachine is under disconnected state
    771      * Two networks test1, test2 are secured network and found in scan results
    772      * Both network are enabled
    773      * test1 is @ 2GHz with RSSI -65
    774      * test2 is @ 5Ghz with RSSI -50
    775      * test2's BSSID is disabled
    776      *
    777      * expected return test1 since test2's BSSID has been disabled
    778      */
    779     @Test
    780     public void networkChooseWithOneBssidDisabled() {
    781         String[] ssids = DEFAULT_SSIDS;
    782         String[] bssids = DEFAULT_BSSIDS;
    783         int[] frequencies = {2437, 5180};
    784         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
    785         int[] levels = {-65, -50};
    786         int[] security = {SECURITY_PSK, SECURITY_PSK};
    787 
    788         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
    789         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
    790         prepareConfigStore(savedConfigs);
    791 
    792         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
    793         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
    794         scanResultLinkConfiguration(savedConfigs, scanDetails);
    795         ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
    796 
    797         mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssids[1], false);
    798         mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssids[1], false);
    799         mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssids[1], false);
    800         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
    801                 false, scanDetails, false, false, true, false);
    802 
    803         verifySelectedResult(chosenScanResult, candidate);
    804     }
    805 
    806     /**
    807      * Case #14    re-choose the disabled BSSID after it is re-enabled
    808      *
    809      * In this test. we simulate following scenario:
    810      * WifiStateMachine is under disconnected state
    811      * Two networks test1, test2 are secured network and found in scan results
    812      * Both network are enabled
    813      * test1 is @ 2GHz with RSSI -65
    814      * test2 is @ 5Ghz with RSSI -50
    815      * test2's BSSID is disabled
    816      *
    817      * expected return test2 since test2's BSSID has been enabled again
    818      */
    819     @Test
    820     public void networkChooseWithOneBssidReenaabled() {
    821         String[] ssids = DEFAULT_SSIDS;
    822         String[] bssids = DEFAULT_BSSIDS;
    823         int[] frequencies = {2437, 5180};
    824         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
    825         int[] levels = {-65, -50};
    826         int[] security = {SECURITY_PSK, SECURITY_PSK};
    827 
    828         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
    829         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
    830         prepareConfigStore(savedConfigs);
    831 
    832         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
    833         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
    834         scanResultLinkConfiguration(savedConfigs, scanDetails);
    835         ScanResult chosenScanResult = scanDetails.get(1).getScanResult();
    836 
    837         mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssids[1], false);
    838         mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssids[1], false);
    839         mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssids[1], false);
    840         //re-enable it
    841         mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssids[1], true);
    842         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
    843                 false, scanDetails, false, false, true, false);
    844 
    845         verifySelectedResult(chosenScanResult, candidate);
    846     }
    847 
    848     /**
    849      * Case #15    re-choose the disabled BSSID after its disability has expired
    850      *
    851      * In this test. we simulate following scenario:
    852      * WifiStateMachine is under disconnected state
    853      * Two networks test1, test2 are secured network and found in scan results
    854      * Both network are enabled
    855      * test1 is @ 2GHz with RSSI -65
    856      * test2 is @ 5Ghz with RSSI -50
    857      * test2's BSSID is disabled
    858      *
    859      * expected return test2 since test2's BSSID has been enabled again
    860      */
    861     @Test
    862     public void networkChooseWithOneBssidDisableExpire() {
    863         String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\""};
    864         String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "6c:f3:7f:ae:8c:f5"};
    865         int[] frequencies = {2437, 5180, 5180};
    866         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]",
    867                 "[WPA2-EAP-CCMP][ESS][ESS]"};
    868         int[] levels = {-65, -50, -60};
    869         int[] security = {SECURITY_PSK, SECURITY_PSK, SECURITY_PSK};
    870 
    871         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
    872         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
    873         prepareConfigStore(savedConfigs);
    874 
    875         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
    876         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
    877         scanResultLinkConfiguration(savedConfigs, scanDetails);
    878         ScanResult chosenScanResult = scanDetails.get(1).getScanResult();
    879 
    880         for (int index = 0; index < WifiQualifiedNetworkSelector.BSSID_BLACKLIST_THRESHOLD;
    881                 index++) {
    882             mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssids[1], false);
    883             mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssids[2], false);
    884         }
    885 
    886         //re-enable it
    887         when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime()
    888                 + WifiQualifiedNetworkSelector.BSSID_BLACKLIST_EXPIRE_TIME);
    889         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
    890                 false, scanDetails, false, false, true, false);
    891 
    892         verifySelectedResult(chosenScanResult, candidate);
    893     }
    894     /**
    895      * Case #16    do not choose the SSID has been disabled
    896      *
    897      * In this test. we simulate following scenario:
    898      * WifiStateMachine is under disconnected state
    899      * Two networks test1, test2 are secured network and found in scan results
    900      * Both network are enabled
    901      * test1 is @ 2GHz with RSSI -65
    902      * test2 is @ 5Ghz with RSSI -50
    903      * test2's SSID is disabled
    904      *
    905      * expected return test1 since test2's SSID has been disabled
    906      */
    907     @Test
    908     public void networkChooseWithOneSsidDisabled() {
    909         String[] ssids = DEFAULT_SSIDS;
    910         String[] bssids = DEFAULT_BSSIDS;
    911         int[] frequencies = {2437, 5180};
    912         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
    913         int[] levels = {-65, -50};
    914         int[] security = {SECURITY_PSK, SECURITY_PSK};
    915 
    916         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
    917         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
    918         prepareConfigStore(savedConfigs);
    919 
    920         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
    921         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
    922         scanResultLinkConfiguration(savedConfigs, scanDetails);
    923         ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
    924 
    925         when(mWifiConfigManager.tryEnableQualifiedNetwork(anyInt())).thenReturn(true);
    926         savedConfigs[1].getNetworkSelectionStatus().setNetworkSelectionStatus(
    927                 WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED);
    928         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
    929                 false, scanDetails, false, false, true, false);
    930 
    931         verifySelectedResult(chosenScanResult, candidate);
    932     }
    933 
    934     /**
    935      * Case #17    do not make QNS is link is bouncing now
    936      *
    937      * In this test. we simulate following scenario:
    938      * WifiStateMachine is under disconnected state and currently is under link bouncing
    939      * Two networks test1, test2 are secured network and found in scan results
    940      * Both network are enabled
    941      * test1 is @ 2GHz with RSSI -50
    942      * test2 is @ 5Ghz with RSSI -50
    943      *
    944      * expected return null
    945      */
    946     @Test
    947     public void noQNSWhenLinkBouncingDisconnected() {
    948         String[] ssids = DEFAULT_SSIDS;
    949         String[] bssids = DEFAULT_BSSIDS;
    950         int[] frequencies = {2437, 5180};
    951         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
    952         int[] levels = {WifiQualifiedNetworkSelector.MINIMUM_2G_ACCEPT_RSSI - 1,
    953                 WifiQualifiedNetworkSelector.MINIMUM_5G_ACCEPT_RSSI - 1};
    954         int[] security = {SECURITY_PSK, SECURITY_PSK};
    955 
    956         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
    957         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
    958         prepareConfigStore(savedConfigs);
    959 
    960         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
    961         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
    962         scanResultLinkConfiguration(savedConfigs, scanDetails);
    963 
    964         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
    965                 false, scanDetails, true, false, true, false);
    966 
    967         assertEquals("choose the wrong network", null, candidate);
    968     }
    969 
    970     /**
    971      * Case #18    QNS with very short gap
    972      *
    973      * In this test. we simulate following scenario:
    974      * WifiStateMachine is under disconnected state
    975      * If last QNS is made in less than MINIMUM_QUALIFIED_NETWORK_SELECTION_INTERVAL, we
    976      * still should make new QNS since it is disconnected now
    977      *
    978      * expect return test1 because of band bonus
    979      */
    980     @Test
    981     public void networkSelectionInShortGap() {
    982         String[] ssids = DEFAULT_SSIDS;
    983         String[] bssids = DEFAULT_BSSIDS;
    984         int[] frequencies = {2437, 5180};
    985         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
    986         int[] levels = {-50, -65};
    987         int[] security = {SECURITY_PSK, SECURITY_PSK};
    988 
    989         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
    990         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
    991         prepareConfigStore(savedConfigs);
    992 
    993         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
    994         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
    995         scanResultLinkConfiguration(savedConfigs, scanDetails);
    996         //first QNS
    997         mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false,
    998                 false, true, false);
    999         //immediately second QNS
   1000         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
   1001                 false, scanDetails, false, false, true, false);
   1002         ScanResult chosenScanResult = scanDetails.get(1).getScanResult();
   1003 
   1004         verifySelectedResult(chosenScanResult, candidate);
   1005     }
   1006 
   1007     //Unit test for Connected State
   1008 
   1009     /**
   1010      * Case #19    no QNS with very short gap when connected
   1011      * In this test. we simulate following scenario:
   1012      * WifiStateMachine is under connected state and test2 is connected
   1013      * When WifiStateMachine is already in connected state, if last QNS is made in less than
   1014      * MINIMUM_QUALIFIED_NETWORK_SELECTION_INTERVAL, no new QNS should be made
   1015      *
   1016      * expect return NULL
   1017      */
   1018     @Test
   1019     public void noNetworkSelectionDueToShortGap() {
   1020         String[] ssids = DEFAULT_SSIDS;
   1021         String[] bssids = DEFAULT_BSSIDS;
   1022         int[] frequencies = {2437, 5180};
   1023         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
   1024         int[] levels = {-50, -65};
   1025         int[] security = {SECURITY_PSK, SECURITY_PSK};
   1026 
   1027         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1028         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
   1029         prepareConfigStore(savedConfigs);
   1030 
   1031         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
   1032         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
   1033         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1034         //first QNS
   1035         mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false,
   1036                 false, true, false);
   1037         //immediately second QNS
   1038         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
   1039                 false, scanDetails, false, true, false, false);
   1040         ScanResult chosenScanResult = scanDetails.get(1).getScanResult();
   1041         assertEquals("choose the wrong BSSID", null, candidate);
   1042     }
   1043 
   1044     /**
   1045      * Case #20    force QNS with very short gap under connection
   1046      * In this test. we simulate following scenario:
   1047      * WifiStateMachine is under connected state and test2 is connected
   1048      * When WifiStateMachine is already in connected state, if last QNS is made in less than
   1049      * MINIMUM_QUALIFIED_NETWORK_SELECTION_INTERVAL, no new QNS should be made. However, if we force
   1050      * to make new QNS, QNS still will be made
   1051      *
   1052      * expect return test2 since it is the current connected one (bonus)
   1053      */
   1054     @Test
   1055     public void forceNetworkSelectionInShortGap() {
   1056         String[] ssids = DEFAULT_SSIDS;
   1057         String[] bssids = DEFAULT_BSSIDS;
   1058         int[] frequencies = {2437, 5180};
   1059         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
   1060         int[] levels = {-50, -65};
   1061         int[] security = {SECURITY_PSK, SECURITY_PSK};
   1062 
   1063         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1064         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
   1065         prepareConfigStore(savedConfigs);
   1066 
   1067         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
   1068         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
   1069         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1070         //first QNS
   1071         mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false,
   1072                 false, true, false);
   1073         //immediately second QNS
   1074         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(true,
   1075                 false, scanDetails, false, true, false, false);
   1076         ScanResult chosenScanResult = scanDetails.get(1).getScanResult();
   1077 
   1078         verifySelectedResult(chosenScanResult, candidate);
   1079     }
   1080 
   1081     /**
   1082      * Case #21    no QNS when connected and user do not allow switch when connected
   1083      *
   1084      * In this test. we simulate following scenario:
   1085      * WifiStateMachine is under connected state and test2 is connected
   1086      * if user does not allow switch network when connected, do not make new QNS when connected
   1087      *
   1088      * expect return NULL
   1089      */
   1090     @Test
   1091     public void noNewNetworkSelectionDuetoUserDisableSwitchWhenConnected() {
   1092         String[] ssids = DEFAULT_SSIDS;
   1093         String[] bssids = DEFAULT_BSSIDS;
   1094         int[] frequencies = {2437, 5180};
   1095         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
   1096         int[] levels = {-50, -65};
   1097         int[] security = {SECURITY_PSK, SECURITY_PSK};
   1098 
   1099         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1100         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
   1101         prepareConfigStore(savedConfigs);
   1102 
   1103         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
   1104         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
   1105         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1106 
   1107         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
   1108                 false, scanDetails, false, true, false, false);
   1109         assertEquals("choose the wrong BSSID", null, candidate);
   1110         assertEquals("Should receive zero filteredScanDetails", 0,
   1111                 mWifiQualifiedNetworkSelector.getFilteredScanDetails().size());
   1112     }
   1113 
   1114     /**
   1115      * Case #22    no new QNS if current network is qualified already
   1116      *
   1117      * In this test. we simulate following scenario:
   1118      * WifiStateMachine is under connected state and test2 is connected
   1119      * If current connected network is Qualified already, do not make new QNS
   1120      * simulated current connected network as:
   1121      * 5GHz, RSSI = WifiQualifiedNetworkSelector.QUALIFIED_RSSI_5G_BAND, secured
   1122      *
   1123      * expected return null
   1124      */
   1125     @Test
   1126     public void noNewQNSCurrentNetworkQualified() {
   1127         String[] ssids = DEFAULT_SSIDS;
   1128         String[] bssids = DEFAULT_BSSIDS;
   1129         int[] frequencies = {2437, 5180};
   1130         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
   1131         int[] levels = {-65, WifiQualifiedNetworkSelector.QUALIFIED_RSSI_5G_BAND};
   1132         int[] security = {SECURITY_PSK, SECURITY_PSK};
   1133 
   1134         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1135         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
   1136         prepareConfigStore(savedConfigs);
   1137 
   1138         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
   1139         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
   1140         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1141 
   1142         //first time, connect to test2 due to 5GHz bonus
   1143         mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false,
   1144                 false, true, false);
   1145         when(mWifiInfo.getNetworkId()).thenReturn(1);
   1146         when(mWifiInfo.getBSSID()).thenReturn(bssids[1]);
   1147         when(mWifiInfo.is24GHz()).thenReturn(false);
   1148         when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true);
   1149         when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000);
   1150 
   1151         levels[0] = -50; // if there is QNS, test1 will be chosen
   1152         scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1153         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1154 
   1155         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
   1156                 false, scanDetails, false, true, false, false);
   1157         assertEquals("choose the wrong BSSID", null, candidate);
   1158     }
   1159 
   1160     /**
   1161      * Case #23    No new QNS when link bouncing when connected
   1162      *
   1163      * In this test. we simulate following scenario:
   1164      * WifiStateMachine is under connected state and test2 is connected
   1165      * no new QNS when link is bouncing
   1166      *
   1167      * expected return null
   1168      */
   1169     @Test
   1170     public void noNewQNSLinkBouncing() {
   1171         String[] ssids = DEFAULT_SSIDS;
   1172         String[] bssids = DEFAULT_BSSIDS;
   1173         int[] frequencies = {2437, 5180};
   1174         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
   1175         int[] levels = {-70, -75};
   1176         int[] security = {SECURITY_PSK, SECURITY_PSK};
   1177 
   1178         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1179         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
   1180         prepareConfigStore(savedConfigs);
   1181 
   1182         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
   1183         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
   1184         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1185 
   1186         //first connect to test2 due to 5GHz bonus
   1187         mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false,
   1188                 false, true, false);
   1189         when(mWifiInfo.getNetworkId()).thenReturn(1);
   1190         when(mWifiInfo.getBSSID()).thenReturn(bssids[1]);
   1191         when(mWifiInfo.is24GHz()).thenReturn(false);
   1192         when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000);
   1193         when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true);
   1194 
   1195         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
   1196                 false, scanDetails, true, true, false, false);
   1197         assertEquals("choose the wrong BSSID", null, candidate);
   1198     }
   1199 
   1200     /**
   1201      * Case #24    Qualified network need to be on 5GHz
   1202      *
   1203      * In this test. we simulate following scenario:
   1204      * WifiStateMachine is under connected state and connected to test2
   1205      * if current connected network is not 5GHz, then it is not qualified. We should make new QNS
   1206      *
   1207      * expected result: return test1
   1208      */
   1209     @Test
   1210     public void currentNetworkNotQualifiedDueToBandMismatch() {
   1211         String[] ssids = DEFAULT_SSIDS;
   1212         String[] bssids = DEFAULT_BSSIDS;
   1213         int[] frequencies = {2437, 2437};
   1214         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
   1215         int[] levels = {-50, -65};
   1216         int[] security = {SECURITY_PSK, SECURITY_PSK};
   1217 
   1218         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1219         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
   1220         prepareConfigStore(savedConfigs);
   1221 
   1222         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
   1223         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
   1224         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1225         when(mWifiInfo.getNetworkId()).thenReturn(0);
   1226         when(mWifiInfo.getBSSID()).thenReturn(bssids[0]);
   1227         when(mWifiInfo.is24GHz()).thenReturn(true);
   1228         //connect to config2 first
   1229         mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false,
   1230                 false, true, false);
   1231 
   1232         when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000);
   1233         when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true);
   1234 
   1235         ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
   1236         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
   1237                 false, scanDetails, false, true, false, false);
   1238         verifySelectedResult(chosenScanResult, candidate);
   1239     }
   1240 
   1241     /**
   1242      * Case #25    Qualified network need to be secured
   1243      *
   1244      * In this test. we simulate following scenario:
   1245      * WifiStateMachine is under connected state and current connects to test2
   1246      * if current connected network is open network, then it is not qualified. We should make new
   1247      * QNS
   1248      *
   1249      * expected result: return test1 since test1 has higher RSSI
   1250      */
   1251     @Test
   1252     public void currentNetworkNotQualifiedDueToOpenNetwork() {
   1253         String[] ssids = DEFAULT_SSIDS;
   1254         String[] bssids = DEFAULT_BSSIDS;
   1255         int[] frequencies = {5400, 5400};
   1256         String[] caps = {"[ESS]", "[ESS]"};
   1257         int[] levels = {-70, -65};
   1258         int[] security = {SECURITY_NONE, SECURITY_NONE};
   1259 
   1260         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1261         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
   1262         prepareConfigStore(savedConfigs);
   1263 
   1264         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
   1265         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
   1266         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1267 
   1268         //first connect to test2 because of RSSI
   1269         mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false,
   1270                 false, true, false);
   1271         when(mWifiInfo.getNetworkId()).thenReturn(1);
   1272         when(mWifiInfo.getBSSID()).thenReturn(bssids[1]);
   1273         when(mWifiInfo.is24GHz()).thenReturn(false);
   1274         when(mWifiInfo.is5GHz()).thenReturn(true);
   1275         when(mWifiConfigManager.isOpenNetwork(savedConfigs[1])).thenReturn(true);
   1276         when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000);
   1277         when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true);
   1278         levels[0] = -60;
   1279         scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1280         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1281 
   1282         ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
   1283         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
   1284                 false, scanDetails, false, true, false, false);
   1285         verifySelectedResult(chosenScanResult, candidate);
   1286     }
   1287 
   1288     /**
   1289      * Case #26    ephemeral network can not be qualified network
   1290      *
   1291      * In this test. we simulate following scenario:
   1292      * WifiStateMachine is under connected state and current connected to test2
   1293      * if current connected network is ephemeral network, then it is not qualified. We should make
   1294      * new QNS
   1295      *
   1296      * expected result: return test1 (since test2 is ephemeral)
   1297      */
   1298     @Test
   1299     public void currentNetworkNotQualifiedDueToEphemeral() {
   1300         String[] ssids = DEFAULT_SSIDS;
   1301         String[] bssids = DEFAULT_BSSIDS;
   1302         int[] frequencies = {5200, 5200};
   1303         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
   1304         int[] levels = {-100, -50};
   1305         int[] security = {SECURITY_PSK, SECURITY_PSK};
   1306 
   1307         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1308         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
   1309         savedConfigs[1].ephemeral = true;
   1310         prepareConfigStore(savedConfigs);
   1311 
   1312         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
   1313         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
   1314         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1315 
   1316         //first connect to test2 since test1's RSSI is negligible
   1317         mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false,
   1318                 false, true, false);
   1319         when(mWifiInfo.getNetworkId()).thenReturn(1);
   1320         when(mWifiInfo.getBSSID()).thenReturn(bssids[1]);
   1321         when(mWifiInfo.is24GHz()).thenReturn(false);
   1322 
   1323         levels[0] = -70;
   1324         scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1325         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1326         when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true);
   1327         when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000);
   1328 
   1329         ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
   1330         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
   1331                 false, scanDetails, false, true, false, false);
   1332         verifySelectedResult(chosenScanResult, candidate);
   1333     }
   1334 
   1335     /**
   1336      * Case #27    low signal network can not be Qualified network (5GHz)
   1337      *
   1338      * In this test. we simulate following scenario:
   1339      * WifiStateMachine is under connected state and current connected to test2
   1340      * if current connected network's rssi is too low, then it is not qualified. We should
   1341      * make new QNS
   1342      *
   1343      * expected result: return test1
   1344      */
   1345     @Test
   1346     public void currentNetworkNotQualifiedDueToLow5GRssi() {
   1347         String[] ssids = DEFAULT_SSIDS;
   1348         String[] bssids = DEFAULT_BSSIDS;
   1349         int[] frequencies = {5200, 5200};
   1350         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
   1351         int[] levels = {-80, WifiQualifiedNetworkSelector.QUALIFIED_RSSI_5G_BAND - 1};
   1352         int[] security = {SECURITY_PSK, SECURITY_PSK};
   1353 
   1354         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1355         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
   1356         prepareConfigStore(savedConfigs);
   1357 
   1358         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
   1359         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
   1360         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1361 
   1362         mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false,
   1363                 false, true, false);
   1364         when(mWifiInfo.getNetworkId()).thenReturn(1);
   1365         when(mWifiInfo.getBSSID()).thenReturn(bssids[1]);
   1366         when(mWifiInfo.getRssi()).thenReturn(levels[1]);
   1367         when(mWifiInfo.is24GHz()).thenReturn(false);
   1368         when(mWifiInfo.is5GHz()).thenReturn(true);
   1369 
   1370         when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true);
   1371         when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000);
   1372         levels[0] = -60;
   1373         scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1374         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1375         ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
   1376 
   1377         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
   1378                 false, scanDetails, false, true, false, false);
   1379         verifySelectedResult(chosenScanResult, candidate);
   1380     }
   1381 
   1382     /**
   1383      * Case #28    low signal network can not be Qualified network (2.4GHz)
   1384      *
   1385      * In this test. we simulate following scenario:
   1386      * WifiStateMachine is under connected state and current connected to test2
   1387      * if current connected network's rssi is too low, then it is not qualified. We should
   1388      * make new QNS
   1389      *
   1390      * expected result: return test1
   1391      */
   1392     @Test
   1393     public void currentNetworkNotQualifiedDueToLow2GRssi() {
   1394         String[] ssids = DEFAULT_SSIDS;
   1395         String[] bssids = DEFAULT_BSSIDS;
   1396         int[] frequencies = {2437, 2437};
   1397         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
   1398         int[] levels = {-100, WifiQualifiedNetworkSelector.QUALIFIED_RSSI_24G_BAND - 1};
   1399         int[] security = {SECURITY_PSK, SECURITY_PSK};
   1400 
   1401         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1402         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
   1403         prepareConfigStore(savedConfigs);
   1404         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
   1405         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
   1406         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1407 
   1408         mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false,
   1409                 false, true, false);
   1410 
   1411         when(mWifiInfo.getNetworkId()).thenReturn(1);
   1412         when(mWifiInfo.getBSSID()).thenReturn(bssids[1]);
   1413         when(mWifiInfo.getRssi()).thenReturn(levels[1]);
   1414         when(mWifiInfo.is24GHz()).thenReturn(false);
   1415         when(mWifiInfo.is5GHz()).thenReturn(true);
   1416 
   1417         when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true);
   1418         levels[0] = -60;
   1419         scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1420         when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000);
   1421         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1422 
   1423         ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
   1424         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
   1425                 false, scanDetails, false, true, false, false);
   1426         verifySelectedResult(chosenScanResult, candidate);
   1427     }
   1428 
   1429     /**
   1430      * Case #29    Choose current network due to current network bonus
   1431      *
   1432      * In this test. we simulate following scenario:
   1433      * WifiStateMachine is under connected state and current connected to test2
   1434      * To connect to a network which is not linked to current connected network, unless this network
   1435      * is more than 10 db higher than current network, we should not switch. So although test2 has a
   1436      * lower signal, we still choose test2
   1437      *
   1438      * expected result: return test2
   1439      */
   1440     @Test
   1441     public void currentNetworkStayDueToSameNetworkBonus() {
   1442         String[] ssids = DEFAULT_SSIDS;
   1443         String[] bssids = DEFAULT_BSSIDS;
   1444         int[] frequencies = {2437, 2437};
   1445         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
   1446         int[] levels = {-100, -80};
   1447         int[] security = {SECURITY_PSK, SECURITY_PSK};
   1448 
   1449         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1450         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
   1451         prepareConfigStore(savedConfigs);
   1452 
   1453         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
   1454         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
   1455         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1456 
   1457         mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false,
   1458                 false, true, false);
   1459         when(mWifiInfo.getNetworkId()).thenReturn(1);
   1460         when(mWifiInfo.getBSSID()).thenReturn(bssids[1]);
   1461         when(mWifiInfo.is24GHz()).thenReturn(true);
   1462 
   1463         when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true);
   1464         levels[0] = -80 + WifiQualifiedNetworkSelector.SAME_BSSID_AWARD / 4
   1465                 + WifiQualifiedNetworkSelector.SAME_NETWORK_AWARD / 4 - 1;
   1466         scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1467         when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000);
   1468         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1469 
   1470         ScanResult chosenScanResult = scanDetails.get(1).getScanResult();
   1471         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
   1472                 false, scanDetails, false, true, false, false);
   1473         verifySelectedResult(chosenScanResult, candidate);
   1474     }
   1475 
   1476     /**
   1477      * Case #30    choose another network due to current network's signal is too low
   1478      *
   1479      * In this test. we simulate following scenario:
   1480      * WifiStateMachine is under connected state and current connected to test2
   1481      * To connect to a network which is not linked to current connected network, if this network
   1482      * is more than 10 db higher than current network, we should switch
   1483      *
   1484      * expected new result: return test1
   1485      */
   1486     @Test
   1487     public void switchNetworkStayDueToCurrentNetworkRssiLow() {
   1488         String[] ssids = DEFAULT_SSIDS;
   1489         String[] bssids = DEFAULT_BSSIDS;
   1490         int[] frequencies = {2437, 2437};
   1491         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
   1492         int[] levels = {-100, -80};
   1493         int[] security = {SECURITY_PSK, SECURITY_PSK};
   1494 
   1495         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1496         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
   1497         prepareConfigStore(savedConfigs);
   1498 
   1499         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
   1500         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
   1501         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1502         mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false,
   1503                 false, true, false);
   1504 
   1505         when(mWifiInfo.getNetworkId()).thenReturn(1);
   1506         when(mWifiInfo.getBSSID()).thenReturn(bssids[1]);
   1507         when(mWifiInfo.is24GHz()).thenReturn(true);
   1508 
   1509         when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true);
   1510         levels[0] = -80 + WifiQualifiedNetworkSelector.SAME_BSSID_AWARD / 4
   1511                 + WifiQualifiedNetworkSelector.SAME_NETWORK_AWARD / 4 + 1;
   1512         scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1513         when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000);
   1514         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1515 
   1516         ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
   1517         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
   1518                 false, scanDetails, false, true, false, false);
   1519         verifySelectedResult(chosenScanResult, candidate);
   1520     }
   1521 
   1522     /**
   1523      * Case #31    Choose current BSSID due to current BSSID bonus
   1524      *
   1525      * In this test. we simulate following scenario:
   1526      * WifiStateMachine is under connected state and current connected to test2
   1527      * Linked network will be treated as same network. To connect to a network which is linked to
   1528      * current connected network, unless this network is more than 6 db higher than current network,
   1529      * we should not switch AP and stick to current BSSID
   1530      *
   1531      * expected result: return test2
   1532      */
   1533     @Test
   1534     public void currentBssidStayDueToSameBSSIDBonus() {
   1535         String[] ssids = DEFAULT_SSIDS;
   1536         String[] bssids = DEFAULT_BSSIDS;
   1537         int[] frequencies = {2437, 2437};
   1538         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
   1539         int[] levels = {-100, -80};
   1540         int[] security = {SECURITY_PSK, SECURITY_PSK};
   1541 
   1542         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1543         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
   1544         //link two configuration
   1545         savedConfigs[0].linkedConfigurations = new HashMap<String, Integer>();
   1546         savedConfigs[1].linkedConfigurations = new HashMap<String, Integer>();
   1547         savedConfigs[0].linkedConfigurations.put(savedConfigs[1].configKey(), 1);
   1548         savedConfigs[1].linkedConfigurations.put(savedConfigs[0].configKey(), 1);
   1549         prepareConfigStore(savedConfigs);
   1550 
   1551         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
   1552         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
   1553         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1554         mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false,
   1555                 false, true, false);
   1556 
   1557         when(mWifiInfo.getNetworkId()).thenReturn(1);
   1558         when(mWifiInfo.getBSSID()).thenReturn(bssids[1]);
   1559         when(mWifiInfo.is24GHz()).thenReturn(true);
   1560 
   1561         when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true);
   1562         levels[0] = -80 + WifiQualifiedNetworkSelector.SAME_NETWORK_AWARD / 4 - 1;
   1563         scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1564         when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000);
   1565         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1566 
   1567         ScanResult chosenScanResult = scanDetails.get(1).getScanResult();
   1568         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
   1569                 false, scanDetails, false, true, false, false);
   1570         verifySelectedResult(chosenScanResult, candidate);
   1571     }
   1572 
   1573     /**
   1574      * Case #32    Choose another BSSID due to current BSSID's rssi is too low
   1575      *
   1576      * In this test. we simulate following scenario:
   1577      * WifiStateMachine is under connected state and current connected to test2
   1578      * Linked network will be treated as same network. To connect to a network which is linked to
   1579      * current connected network, unless this network is more than 6 db higher than current network,
   1580      * we should not switch AP and stick to current BSSID
   1581      *
   1582      * expected result: return test2
   1583      */
   1584     @Test
   1585     public void swithBssidDueToLowRssi() {
   1586         String[] ssids = DEFAULT_SSIDS;
   1587         String[] bssids = DEFAULT_BSSIDS;
   1588         int[] frequencies = {2437, 2437};
   1589         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"};
   1590         int[] levels = {-100, -80};
   1591         int[] security = {SECURITY_PSK, SECURITY_PSK};
   1592 
   1593         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1594         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
   1595         //link two configuration
   1596         savedConfigs[0].linkedConfigurations = new HashMap<String, Integer>();
   1597         savedConfigs[1].linkedConfigurations = new HashMap<String, Integer>();
   1598         savedConfigs[0].linkedConfigurations.put(savedConfigs[1].configKey(), 1);
   1599         savedConfigs[1].linkedConfigurations.put(savedConfigs[0].configKey(), 1);
   1600         prepareConfigStore(savedConfigs);
   1601 
   1602         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
   1603         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
   1604         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1605         mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false,
   1606                 false, true, false);
   1607 
   1608         when(mWifiInfo.getNetworkId()).thenReturn(1);
   1609         when(mWifiInfo.getBSSID()).thenReturn(bssids[1]);
   1610         when(mWifiInfo.is24GHz()).thenReturn(true);
   1611 
   1612         when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true);
   1613         levels[0] = -80 + WifiQualifiedNetworkSelector.SAME_BSSID_AWARD / 4 + 1;
   1614         scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1615         when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000);
   1616         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1617 
   1618         ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
   1619         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
   1620                 false, scanDetails, false, true, false, false);
   1621         verifySelectedResult(chosenScanResult, candidate);
   1622     }
   1623 
   1624     /**
   1625      * Case #33  Choose an ephemeral network with a good score because no saved networks
   1626      *           are available.
   1627      *
   1628      * In this test. we simulate following scenario:
   1629      * WifiStateMachine is not connected to any network.
   1630      * selectQualifiedNetwork() is called with 2 scan results, test1 and test2.
   1631      * test1 is an enterprise network w/o a score.
   1632      * test2 is an open network with a good score. Additionally it's a metered network.
   1633      * isUntrustedConnectionsAllowed is set to true.
   1634      *
   1635      * expected result: return test2 with meteredHint set to True.
   1636      */
   1637     @Test
   1638     public void selectQualifiedNetworkChoosesEphemeral() {
   1639         String[] ssids = DEFAULT_SSIDS;
   1640         String[] bssids = DEFAULT_BSSIDS;
   1641         int[] frequencies = {5200, 5200};
   1642         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]"};
   1643         int[] levels = {-70, -70};
   1644         Integer[] scores = {null, 120};
   1645         boolean[] meteredHints = {false, true};
   1646 
   1647         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1648         configureScoreCache(scanDetails, scores, meteredHints);
   1649 
   1650         // No saved networks.
   1651         when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(any(ScanDetail.class),
   1652                 anyBoolean())).thenReturn(null);
   1653 
   1654         WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class);
   1655         // Setup the config as an invalid candidate. This is done to workaround a Mockito issue.
   1656         // Basically Mockito is unable to mock package-private methods in classes loaded from a
   1657         // different Jar (like all of the framework code) which results in the actual saveNetwork()
   1658         // method being invoked in this case. Because the config is invalid it quickly returns.
   1659         unTrustedNetworkCandidate.SSID = null;
   1660         unTrustedNetworkCandidate.networkId = WifiConfiguration.INVALID_NETWORK_ID;
   1661         ScanResult untrustedScanResult = scanDetails.get(1).getScanResult();
   1662         when(mWifiConfigManager
   1663                 .wifiConfigurationFromScanResult(untrustedScanResult))
   1664                 .thenReturn(unTrustedNetworkCandidate);
   1665 
   1666         WifiConfiguration.NetworkSelectionStatus selectionStatus =
   1667                 mock(WifiConfiguration.NetworkSelectionStatus.class);
   1668         when(unTrustedNetworkCandidate.getNetworkSelectionStatus()).thenReturn(selectionStatus);
   1669         when(selectionStatus.getCandidate()).thenReturn(untrustedScanResult);
   1670 
   1671         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(
   1672                 false /* forceSelectNetwork */,
   1673                 true /* isUntrustedConnectionsAllowed */,
   1674                 scanDetails,
   1675                 false, /* isLinkDebouncing */
   1676                 false, /* isConnected */
   1677                 true, /* isDisconnected */
   1678                 false /* isSupplicantTransient */);
   1679         verify(selectionStatus).setCandidate(untrustedScanResult);
   1680         assertSame(unTrustedNetworkCandidate, candidate);
   1681         assertEquals(meteredHints[1], candidate.meteredHint);
   1682     }
   1683 
   1684     /**
   1685      * Case #34    Test Filtering of potential candidate scanDetails (Untrusted allowed)
   1686      *
   1687      * In this test. we simulate following scenario
   1688      * WifiStateMachine is under disconnected state
   1689      * test1 is @ 2GHz with RSSI -60
   1690      * test2 is @ 5Ghz with RSSI -86, (below minimum threshold)
   1691      * test3 is @ 5Ghz with RSSI -50, however it has no associated saved config
   1692      * test4 is @ 2Ghz with RSSI -62, no associated config, but is Ephemeral
   1693      *
   1694      * Expected behavior: test1 is chosen due to 5GHz signal is too weak (5GHz bonus can not
   1695      * compensate).
   1696      * test1 & test4's scanDetails are returned by 'getFilteredScanDetail()'
   1697      */
   1698     @Test
   1699     public void testGetFilteredScanDetailsReturnsOnlyConsideredScanDetails_untrustedAllowed() {
   1700         String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\"", "\"test4\""};
   1701         String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "de:ad:ba:b1:e5:55",
   1702                 "c0:ff:ee:ee:e3:ee"};
   1703         int[] frequencies = {2437, 5180, 5180, 2437};
   1704         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]",
   1705                 "[WPA2-EAP-CCMP][ESS]"};
   1706         int[] levels = {-60, -86, -50, -62};
   1707         int[] security = {SECURITY_PSK, SECURITY_PSK, SECURITY_PSK, SECURITY_PSK};
   1708         boolean[] meteredHints = {false, false, false, true};
   1709         Integer[] scores = {null, null, null, 120};
   1710 
   1711         //Create all 4 scanDetails
   1712         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1713 
   1714         //Setup NetworkScoreCache for detecting ephemeral networks ("test4")
   1715         configureScoreCache(scanDetails, scores, meteredHints);
   1716         WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class);
   1717         unTrustedNetworkCandidate.SSID = null;
   1718         unTrustedNetworkCandidate.networkId = WifiConfiguration.INVALID_NETWORK_ID;
   1719         ScanResult untrustedScanResult = scanDetails.get(3).getScanResult();
   1720         when(mWifiConfigManager
   1721                 .wifiConfigurationFromScanResult(untrustedScanResult))
   1722                 .thenReturn(unTrustedNetworkCandidate);
   1723         WifiConfiguration.NetworkSelectionStatus selectionStatus =
   1724                         mock(WifiConfiguration.NetworkSelectionStatus.class);
   1725         when(unTrustedNetworkCandidate.getNetworkSelectionStatus()).thenReturn(selectionStatus);
   1726 
   1727         //Set up associated configs for test1 & test2
   1728         WifiConfiguration[] savedConfigs = generateWifiConfigurations(
   1729                 Arrays.copyOfRange(ssids, 0, 2), Arrays.copyOfRange(security, 0, 2));
   1730         prepareConfigStore(savedConfigs);
   1731         List<ScanDetail> savedScanDetails = new ArrayList<ScanDetail>(scanDetails.subList(0, 2));
   1732         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
   1733         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
   1734         scanResultLinkConfiguration(savedConfigs, savedScanDetails);
   1735 
   1736         //Force mock ConfigManager to return null (and not an empty list) for "test3" & "test4"
   1737         when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(eq(scanDetails.get(2)),
   1738                 anyBoolean())).thenReturn(null);
   1739         when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(eq(scanDetails.get(3)),
   1740                 anyBoolean())).thenReturn(null);
   1741 
   1742         ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
   1743 
   1744         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(
   1745                 false /* forceSelectNetwork */,
   1746                 true /* isUntrustedConnectionsAllowed */,
   1747                 scanDetails,
   1748                 false, /* isLinkDebouncing */
   1749                 false, /* isConnected */
   1750                 true, /* isDisconnected */
   1751                 false /* isSupplicantTransient */);
   1752 
   1753         verifySelectedResult(chosenScanResult, candidate);
   1754         //Verify two scanDetails returned in the filteredScanDetails
   1755         assertEquals(2, mWifiQualifiedNetworkSelector.getFilteredScanDetails().size());
   1756         assertEquals(mWifiQualifiedNetworkSelector.getFilteredScanDetails().get(0).first.toString(),
   1757                 scanDetails.get(0).toString());
   1758         assertEquals(mWifiQualifiedNetworkSelector.getFilteredScanDetails().get(1).first.toString(),
   1759                 scanDetails.get(3).toString());
   1760     }
   1761 
   1762 
   1763     /**
   1764      * Case #35    Test Filtering of potential candidate scanDetails (Untrusted disallowed)
   1765      *
   1766      * In this test. we simulate following scenario
   1767      * WifiStateMachine is under disconnected state
   1768      * test1 is @ 2GHz with RSSI -60
   1769      * test2 is @ 5Ghz with RSSI -86, (below minimum threshold)
   1770      * test3 is @ 5Ghz with RSSI -50, however it has no associated saved config
   1771      * test4 is @ 2Ghz with RSSI -62, no associated config, but is Ephemeral
   1772      *
   1773      * Expected behavior: test1 is chosen due to 5GHz signal is too weak (5GHz bonus can not
   1774      * compensate).
   1775      * test1 & test4's scanDetails are returned by 'getFilteredScanDetail()'
   1776      */
   1777     @Test
   1778     public void testGetFilteredScanDetailsReturnsOnlyConsideredScanDetails_untrustedDisallowed() {
   1779         String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\"", "\"test4\""};
   1780         String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "de:ad:ba:b1:e5:55",
   1781                 "c0:ff:ee:ee:e3:ee"};
   1782         int[] frequencies = {2437, 5180, 5180, 2437};
   1783         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]",
   1784                 "[WPA2-EAP-CCMP][ESS]"};
   1785         int[] levels = {-60, -86, -50, -62};
   1786         int[] security = {SECURITY_PSK, SECURITY_PSK, SECURITY_PSK, SECURITY_PSK};
   1787         boolean[] meteredHints = {false, false, false, true};
   1788         Integer[] scores = {null, null, null, 120};
   1789 
   1790         //Create all 4 scanDetails
   1791         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1792 
   1793         //Setup NetworkScoreCache for detecting ephemeral networks ("test4")
   1794         configureScoreCache(scanDetails, scores, meteredHints);
   1795         WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class);
   1796         unTrustedNetworkCandidate.SSID = null;
   1797         unTrustedNetworkCandidate.networkId = WifiConfiguration.INVALID_NETWORK_ID;
   1798         ScanResult untrustedScanResult = scanDetails.get(3).getScanResult();
   1799         when(mWifiConfigManager
   1800                 .wifiConfigurationFromScanResult(untrustedScanResult))
   1801                 .thenReturn(unTrustedNetworkCandidate);
   1802         WifiConfiguration.NetworkSelectionStatus selectionStatus =
   1803                         mock(WifiConfiguration.NetworkSelectionStatus.class);
   1804         when(unTrustedNetworkCandidate.getNetworkSelectionStatus()).thenReturn(selectionStatus);
   1805 
   1806         //Set up associated configs for test1 & test2
   1807         WifiConfiguration[] savedConfigs = generateWifiConfigurations(
   1808                 Arrays.copyOfRange(ssids, 0, 2), Arrays.copyOfRange(security, 0, 2));
   1809         prepareConfigStore(savedConfigs);
   1810         List<ScanDetail> savedScanDetails = new ArrayList<ScanDetail>(scanDetails.subList(0, 2));
   1811         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
   1812         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
   1813         scanResultLinkConfiguration(savedConfigs, savedScanDetails);
   1814 
   1815         //Force mock ConfigManager to return null (and not an empty list) for "test3" & "test4"
   1816         when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(eq(scanDetails.get(2)),
   1817                 anyBoolean())).thenReturn(null);
   1818         when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(eq(scanDetails.get(3)),
   1819                 anyBoolean())).thenReturn(null);
   1820 
   1821         ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
   1822 
   1823         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(
   1824                 false /* forceSelectNetwork */,
   1825                 false /* isUntrustedConnectionsAllowed */,
   1826                 scanDetails,
   1827                 false, /* isLinkDebouncing */
   1828                 false, /* isConnected */
   1829                 true, /* isDisconnected */
   1830                 false /* isSupplicantTransient */);
   1831 
   1832         verifySelectedResult(chosenScanResult, candidate);
   1833         //Verify two scanDetails returned in the filteredScanDetails
   1834         assertEquals(1, mWifiQualifiedNetworkSelector.getFilteredScanDetails().size());
   1835         assertEquals(mWifiQualifiedNetworkSelector.getFilteredScanDetails().get(0).first.toString(),
   1836                 scanDetails.get(0).toString());
   1837     }
   1838 
   1839     /**
   1840      * Case #36  Ignore an ephemeral network if it was previously deleted.
   1841      *
   1842      * In this test. we simulate following scenario:
   1843      * WifiStateMachine is not connected to any network.
   1844      * selectQualifiedNetwork() is called with 2 scan results, test1 and test2.
   1845      * test1 is an open network with a low score. Additionally it's a metered network.
   1846      * test2 is an open network with a good score but was previously deleted.
   1847      * isUntrustedConnectionsAllowed is set to true.
   1848      *
   1849      * expected result: return test1 with meteredHint set to True.
   1850      */
   1851     @Test
   1852     public void selectQualifiedNetworkDoesNotChooseDeletedEphemeral() {
   1853         String[] ssids = DEFAULT_SSIDS;
   1854         String[] bssids = DEFAULT_BSSIDS;
   1855         int[] frequencies = {5200, 5200};
   1856         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]"};
   1857         int[] levels = {-70, -70};
   1858         Integer[] scores = {20, 120};
   1859         boolean[] meteredHints = {true, false};
   1860 
   1861         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1862         configureScoreCache(scanDetails, scores, meteredHints);
   1863 
   1864         // No saved networks.
   1865         when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(any(ScanDetail.class),
   1866                 anyBoolean())).thenReturn(null);
   1867 
   1868         WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class);
   1869         // Setup the config as an invalid candidate. This is done to workaround a Mockito issue.
   1870         // Basically Mockito is unable to mock package-private methods in classes loaded from a
   1871         // different Jar (like all of the framework code) which results in the actual saveNetwork()
   1872         // method being invoked in this case. Because the config is invalid it quickly returns.
   1873         unTrustedNetworkCandidate.SSID = null;
   1874         unTrustedNetworkCandidate.networkId = WifiConfiguration.INVALID_NETWORK_ID;
   1875         ScanResult untrustedScanResult = scanDetails.get(0).getScanResult();
   1876         when(mWifiConfigManager
   1877                 .wifiConfigurationFromScanResult(untrustedScanResult))
   1878                 .thenReturn(unTrustedNetworkCandidate);
   1879 
   1880         // The second scan result is for an ephemeral network which was previously deleted
   1881         when(mWifiConfigManager
   1882                 .wasEphemeralNetworkDeleted(scanDetails.get(0).getScanResult().SSID))
   1883                 .thenReturn(false);
   1884         when(mWifiConfigManager
   1885                 .wasEphemeralNetworkDeleted(scanDetails.get(1).getScanResult().SSID))
   1886                 .thenReturn(true);
   1887 
   1888         WifiConfiguration.NetworkSelectionStatus selectionStatus =
   1889                 mock(WifiConfiguration.NetworkSelectionStatus.class);
   1890         when(unTrustedNetworkCandidate.getNetworkSelectionStatus()).thenReturn(selectionStatus);
   1891         when(selectionStatus.getCandidate()).thenReturn(untrustedScanResult);
   1892 
   1893         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(
   1894                 false /* forceSelectNetwork */,
   1895                 true /* isUntrustedConnectionsAllowed */,
   1896                 scanDetails,
   1897                 false, /* isLinkDebouncing */
   1898                 false, /* isConnected */
   1899                 true, /* isDisconnected */
   1900                 false /* isSupplicantTransient */);
   1901         verify(selectionStatus).setCandidate(untrustedScanResult);
   1902         assertSame(candidate, unTrustedNetworkCandidate);
   1903         assertEquals(meteredHints[0], candidate.meteredHint);
   1904     }
   1905 
   1906     /**
   1907      * Case #37  Choose the saved config that doesn't qualify for external scoring.
   1908      *
   1909      * In this test. we simulate following scenario:
   1910      * WifiStateMachine is not connected to any network.
   1911      * selectQualifiedNetwork() is called with 2 scan results, test1 and test2.
   1912      * test1 is a saved network.
   1913      * test2 is a saved network with useExternalScores set to true and a very high score.
   1914      *
   1915      * expected result: return test1 because saved networks that don't request external scoring
   1916      *                  have a higher priority.
   1917      */
   1918     @Test
   1919     public void selectQualifiedNetworkPrefersSavedWithoutExternalScores() {
   1920         String[] ssids = DEFAULT_SSIDS;
   1921         String[] bssids = DEFAULT_BSSIDS;
   1922         int[] frequencies = {5200, 5200};
   1923         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]"};
   1924         int[] security = {SECURITY_PSK, SECURITY_PSK};
   1925         int[] levels = {-70, -70};
   1926         Integer[] scores = {null, 120};
   1927         boolean[] meteredHints = {false, true};
   1928 
   1929         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1930         configureScoreCache(scanDetails, scores, meteredHints);
   1931 
   1932         WifiConfiguration[] savedConfigs = generateWifiConfigurations(DEFAULT_SSIDS, security);
   1933         savedConfigs[1].useExternalScores = true; // test2 is set to use external scores.
   1934         prepareConfigStore(savedConfigs);
   1935         when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(savedConfigs));
   1936         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1937 
   1938         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(
   1939                 false /* forceSelectNetwork */,
   1940                 false /* isUntrustedConnectionsAllowed */,
   1941                 scanDetails,
   1942                 false, /* isLinkDebouncing */
   1943                 false, /* isConnected */
   1944                 true, /* isDisconnected */
   1945                 false /* isSupplicantTransient */);
   1946         verifySelectedResult(scanDetails.get(0).getScanResult(), candidate);
   1947         assertSame(candidate, savedConfigs[0]);
   1948     }
   1949 
   1950     /**
   1951      * Case #38  Choose the saved config that does qualify for external scoring when other saved
   1952      *           networks are not available.
   1953      *
   1954      * In this test. we simulate following scenario:
   1955      * WifiStateMachine is not connected to any network.
   1956      * selectQualifiedNetwork() is called with 2 scan results, test1 and test2.
   1957      * test1 is a saved network with useExternalScores set to true and a very high score.
   1958      * test2 is a saved network but not in range (not included in the scan results).
   1959      *
   1960      * expected result: return test1 because there are no better saved networks within range.
   1961      */
   1962     @Test
   1963     public void selectQualifiedNetworkSelectsSavedWithExternalScores() {
   1964         String[] ssids = {"\"test1\""};
   1965         String[] bssids = {"6c:f3:7f:ae:8c:f3"};
   1966         int[] frequencies = {5200};
   1967         String[] caps = {"[WPA2-EAP-CCMP][ESS]"};
   1968         int[] security = {SECURITY_PSK, SECURITY_PSK};
   1969         int[] levels = {-70};
   1970         Integer[] scores = {120};
   1971         boolean[] meteredHints = {false};
   1972 
   1973         // Scan details only contains 1 ssid, test1.
   1974         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   1975         configureScoreCache(scanDetails, scores, meteredHints);
   1976 
   1977         // The saved config contains 2 ssids, test1 & test2.
   1978         WifiConfiguration[] savedConfigs = generateWifiConfigurations(DEFAULT_SSIDS, security);
   1979         savedConfigs[0].useExternalScores = true; // test1 is set to use external scores.
   1980         prepareConfigStore(savedConfigs);
   1981         when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(savedConfigs));
   1982         scanResultLinkConfiguration(savedConfigs, scanDetails);
   1983 
   1984         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(
   1985                 false /* forceSelectNetwork */,
   1986                 false /* isUntrustedConnectionsAllowed */,
   1987                 scanDetails,
   1988                 false, /* isLinkDebouncing */
   1989                 false, /* isConnected */
   1990                 true, /* isDisconnected */
   1991                 false /* isSupplicantTransient */);
   1992         verifySelectedResult(scanDetails.get(0).getScanResult(), candidate);
   1993         assertSame(candidate, savedConfigs[0]);
   1994     }
   1995 
   1996     /**
   1997      * Case #39  Choose the saved config that does qualify for external scoring over the
   1998      *           untrusted network with the same score.
   1999      *
   2000      * In this test. we simulate following scenario:
   2001      * WifiStateMachine is not connected to any network.
   2002      * selectQualifiedNetwork() is called with 2 scan results, test1 and test2.
   2003      * test1 is a saved network with useExternalScores set to true and the same score as test1.
   2004      * test2 is NOT saved network but in range with a good external score.
   2005      *
   2006      * expected result: return test1 because the tie goes to the saved network.
   2007      */
   2008     @Test
   2009     public void selectQualifiedNetworkPrefersSavedWithExternalScoresOverUntrusted() {
   2010         String[] ssids = DEFAULT_SSIDS;
   2011         String[] bssids = DEFAULT_BSSIDS;
   2012         int[] frequencies = {5200, 5200};
   2013         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]"};
   2014         int[] security = {SECURITY_PSK, SECURITY_PSK};
   2015         int[] levels = {-70, -70};
   2016         Integer[] scores = {120, 120};
   2017         boolean[] meteredHints = {false, true};
   2018 
   2019         // Both networks are in the scan results.
   2020         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   2021         configureScoreCache(scanDetails, scores, meteredHints);
   2022 
   2023         // Set up the associated configs only for test1
   2024         WifiConfiguration[] savedConfigs = generateWifiConfigurations(
   2025                 Arrays.copyOfRange(ssids, 0, 1), Arrays.copyOfRange(security, 0, 1));
   2026         savedConfigs[0].useExternalScores = true; // test1 is set to use external scores.
   2027         prepareConfigStore(savedConfigs);
   2028         when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(savedConfigs));
   2029         scanResultLinkConfiguration(savedConfigs, scanDetails);
   2030         WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class);
   2031         when(mWifiConfigManager
   2032                 .wifiConfigurationFromScanResult(scanDetails.get(1).getScanResult()))
   2033                 .thenReturn(unTrustedNetworkCandidate);
   2034 
   2035         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(
   2036                 false /* forceSelectNetwork */,
   2037                 true /* isUntrustedConnectionsAllowed */,
   2038                 scanDetails,
   2039                 false, /* isLinkDebouncing */
   2040                 false, /* isConnected */
   2041                 true, /* isDisconnected */
   2042                 false /* isSupplicantTransient */);
   2043         verifySelectedResult(scanDetails.get(0).getScanResult(), candidate);
   2044         assertSame(candidate, savedConfigs[0]);
   2045     }
   2046 
   2047     /**
   2048      * Case #40  Choose the ephemeral config over the saved config that does qualify for external
   2049      *           scoring because the untrusted network has a higher score.
   2050      *
   2051      * In this test. we simulate following scenario:
   2052      * WifiStateMachine is not connected to any network.
   2053      * selectQualifiedNetwork() is called with 2 scan results, test1 and test2.
   2054      * test1 is a saved network with useExternalScores set to true and a low score.
   2055      * test2 is NOT saved network but in range with a good external score.
   2056      *
   2057      * expected result: return test2 because it has a better score.
   2058      */
   2059     @Test
   2060     public void selectQualifiedNetworkPrefersUntrustedOverScoredSaved() {
   2061         String[] ssids = DEFAULT_SSIDS;
   2062         String[] bssids = DEFAULT_BSSIDS;
   2063         int[] frequencies = {5200, 5200};
   2064         String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]"};
   2065         int[] security = {SECURITY_PSK, SECURITY_PSK};
   2066         int[] levels = {-70, -70};
   2067         Integer[] scores = {10, 120};
   2068         boolean[] meteredHints = {false, true};
   2069 
   2070         // Both networks are in the scan results.
   2071         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   2072         configureScoreCache(scanDetails, scores, meteredHints);
   2073 
   2074         // Set up the associated configs only for test1
   2075         WifiConfiguration[] savedConfigs = generateWifiConfigurations(
   2076                 Arrays.copyOfRange(ssids, 0, 1), Arrays.copyOfRange(security, 0, 1));
   2077         savedConfigs[0].useExternalScores = true; // test1 is set to use external scores.
   2078         prepareConfigStore(savedConfigs);
   2079         when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(savedConfigs));
   2080         scanResultLinkConfiguration(savedConfigs, scanDetails);
   2081         WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class);
   2082         unTrustedNetworkCandidate.SSID = null;
   2083         unTrustedNetworkCandidate.networkId = WifiConfiguration.INVALID_NETWORK_ID;
   2084         ScanResult untrustedScanResult = scanDetails.get(1).getScanResult();
   2085         when(mWifiConfigManager
   2086                 .wifiConfigurationFromScanResult(untrustedScanResult))
   2087                 .thenReturn(unTrustedNetworkCandidate);
   2088         WifiConfiguration.NetworkSelectionStatus selectionStatus =
   2089                 mock(WifiConfiguration.NetworkSelectionStatus.class);
   2090         when(unTrustedNetworkCandidate.getNetworkSelectionStatus()).thenReturn(selectionStatus);
   2091         when(selectionStatus.getCandidate()).thenReturn(untrustedScanResult);
   2092 
   2093         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(
   2094                 false /* forceSelectNetwork */,
   2095                 true /* isUntrustedConnectionsAllowed */,
   2096                 scanDetails,
   2097                 false, /* isLinkDebouncing */
   2098                 false, /* isConnected */
   2099                 true, /* isDisconnected */
   2100                 false /* isSupplicantTransient */);
   2101         verify(selectionStatus).setCandidate(untrustedScanResult);
   2102         assertSame(unTrustedNetworkCandidate, candidate);
   2103     }
   2104 
   2105     /**
   2106      * Case #41 Ensure the ExternalScoreEvaluator correctly selects the untrusted network.
   2107      *
   2108      * In this test. we simulate following scenario:
   2109      * The ExternalScoreEvaluator is asked to evaluate 1 untrusted network and 1 saved network.
   2110      * The untrusted network has the higher score.
   2111      *
   2112      * expected result: The untrusted network is determined to be the best network.
   2113      */
   2114     @Test
   2115     public void externalScoreEvaluator_untrustedIsBest() {
   2116         WifiQualifiedNetworkSelector.ExternalScoreEvaluator evaluator =
   2117                 new WifiQualifiedNetworkSelector.ExternalScoreEvaluator(mLocalLog, true);
   2118         ScanResult untrustedScanResult = new ScanResult();
   2119         int untrustedScore = 100;
   2120         evaluator.evalUntrustedCandidate(untrustedScore, untrustedScanResult);
   2121 
   2122         ScanResult savedScanResult = new ScanResult();
   2123         int savedScore = 50;
   2124         WifiConfiguration savedConfig = new WifiConfiguration();
   2125         evaluator.evalSavedCandidate(savedScore, savedConfig, savedScanResult);
   2126         assertEquals(WifiQualifiedNetworkSelector.ExternalScoreEvaluator
   2127                 .BestCandidateType.UNTRUSTED_NETWORK, evaluator.getBestCandidateType());
   2128         assertEquals(untrustedScore, evaluator.getHighScore());
   2129         assertSame(untrustedScanResult, evaluator.getScanResultCandidate());
   2130     }
   2131 
   2132     /**
   2133      * Case #42 Ensure the ExternalScoreEvaluator correctly selects the saved network.
   2134      *
   2135      * In this test. we simulate following scenario:
   2136      * The ExternalScoreEvaluator is asked to evaluate 1 untrusted network and 1 saved network.
   2137      * The saved network has the higher score.
   2138      *
   2139      * expected result: The saved network is determined to be the best network.
   2140      */
   2141     @Test
   2142     public void externalScoreEvaluator_savedIsBest() {
   2143         WifiQualifiedNetworkSelector.ExternalScoreEvaluator evaluator =
   2144                 new WifiQualifiedNetworkSelector.ExternalScoreEvaluator(mLocalLog, true);
   2145         ScanResult untrustedScanResult = new ScanResult();
   2146         int untrustedScore = 50;
   2147         evaluator.evalUntrustedCandidate(untrustedScore, untrustedScanResult);
   2148 
   2149         ScanResult savedScanResult = new ScanResult();
   2150         int savedScore = 100;
   2151         WifiConfiguration savedConfig = new WifiConfiguration();
   2152         evaluator.evalSavedCandidate(savedScore, savedConfig, savedScanResult);
   2153         assertEquals(WifiQualifiedNetworkSelector.ExternalScoreEvaluator
   2154                 .BestCandidateType.SAVED_NETWORK, evaluator.getBestCandidateType());
   2155         assertEquals(savedScore, evaluator.getHighScore());
   2156         assertSame(savedScanResult, evaluator.getScanResultCandidate());
   2157     }
   2158 
   2159     /**
   2160      * Case #43 Ensure the ExternalScoreEvaluator correctly selects the saved network if a
   2161      *          tie occurs.
   2162      *
   2163      * In this test. we simulate following scenario:
   2164      * The ExternalScoreEvaluator is asked to evaluate 1 untrusted network and 1 saved network.
   2165      * Both networks have the same score.
   2166      *
   2167      * expected result: The saved network is determined to be the best network.
   2168      */
   2169     @Test
   2170     public void externalScoreEvaluator_tieScores() {
   2171         WifiQualifiedNetworkSelector.ExternalScoreEvaluator evaluator =
   2172                 new WifiQualifiedNetworkSelector.ExternalScoreEvaluator(mLocalLog, true);
   2173         ScanResult untrustedScanResult = new ScanResult();
   2174         int untrustedScore = 100;
   2175         evaluator.evalUntrustedCandidate(untrustedScore, untrustedScanResult);
   2176 
   2177         ScanResult savedScanResult = new ScanResult();
   2178         int savedScore = 100;
   2179         WifiConfiguration savedConfig = new WifiConfiguration();
   2180         evaluator.evalSavedCandidate(savedScore, savedConfig, savedScanResult);
   2181         assertEquals(WifiQualifiedNetworkSelector.ExternalScoreEvaluator
   2182                 .BestCandidateType.SAVED_NETWORK, evaluator.getBestCandidateType());
   2183         assertEquals(savedScore, evaluator.getHighScore());
   2184         assertSame(savedScanResult, evaluator.getScanResultCandidate());
   2185     }
   2186 
   2187     /**
   2188      * Case #44 Ensure the ExternalScoreEvaluator correctly selects the saved network out of
   2189      *          multiple options.
   2190      *
   2191      * In this test. we simulate following scenario:
   2192      * The ExternalScoreEvaluator is asked to evaluate 2 untrusted networks and 2 saved networks.
   2193      * The high scores are equal and the low scores differ.
   2194      *
   2195      * expected result: The saved network is determined to be the best network.
   2196      */
   2197     @Test
   2198     public void externalScoreEvaluator_multipleScores() {
   2199         WifiQualifiedNetworkSelector.ExternalScoreEvaluator evaluator =
   2200                 new WifiQualifiedNetworkSelector.ExternalScoreEvaluator(mLocalLog, true);
   2201         ScanResult untrustedScanResult = new ScanResult();
   2202         int untrustedScore = 100;
   2203         evaluator.evalUntrustedCandidate(untrustedScore, untrustedScanResult);
   2204         evaluator.evalUntrustedCandidate(80, new ScanResult());
   2205 
   2206         ScanResult savedScanResult = new ScanResult();
   2207         int savedScore = 100;
   2208         WifiConfiguration savedConfig = new WifiConfiguration();
   2209         evaluator.evalSavedCandidate(savedScore, savedConfig, savedScanResult);
   2210         evaluator.evalSavedCandidate(90, new WifiConfiguration(), new ScanResult());
   2211         assertEquals(WifiQualifiedNetworkSelector.ExternalScoreEvaluator
   2212                 .BestCandidateType.SAVED_NETWORK, evaluator.getBestCandidateType());
   2213         assertEquals(savedScore, evaluator.getHighScore());
   2214         assertSame(savedScanResult, evaluator.getScanResultCandidate());
   2215     }
   2216 
   2217     /**
   2218      * Case #45 Ensure the ExternalScoreEvaluator correctly handles NULL score inputs.
   2219      *
   2220      * In this test we simulate following scenario:
   2221      * The ExternalScoreEvaluator is asked to evaluate both types of candidates with NULL scores.
   2222      *
   2223      * expected result: No crashes. The best candidate type is returned as NONE.
   2224      */
   2225     @Test
   2226     public void externalScoreEvaluator_nullScores() {
   2227         WifiQualifiedNetworkSelector.ExternalScoreEvaluator evaluator =
   2228                 new WifiQualifiedNetworkSelector.ExternalScoreEvaluator(mLocalLog, true);
   2229         evaluator.evalUntrustedCandidate(null, new ScanResult());
   2230         assertEquals(WifiQualifiedNetworkSelector.ExternalScoreEvaluator
   2231                 .BestCandidateType.NONE, evaluator.getBestCandidateType());
   2232         evaluator.evalSavedCandidate(null, new WifiConfiguration(), new ScanResult());
   2233         assertEquals(WifiQualifiedNetworkSelector.ExternalScoreEvaluator
   2234                 .BestCandidateType.NONE, evaluator.getBestCandidateType());
   2235     }
   2236 
   2237     /**
   2238      * Case #46   Choose 2.4GHz BSSID with stronger RSSI value over
   2239      *            5GHz BSSID with weaker RSSI value
   2240      *
   2241      * In this test. we simulate following scenario:
   2242      * Two APs are found in scan results
   2243      * BSSID1 is @ 5GHz with RSSI -82
   2244      * BSSID2 is @ 2Ghz with RSSI -72
   2245      * These two BSSIDs get exactly the same QNS score
   2246      *
   2247      * expect BSSID2 to be chosen as it has stronger RSSI value
   2248      */
   2249     @Test
   2250     public void chooseStrongerRssiOver5GHz() {
   2251         String[] ssids = {"\"test1\"", "\"test1\""};
   2252         String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
   2253         int[] frequencies = {5220, 2437};
   2254         String[] caps = {"[ESS]", "[ESS]"};
   2255         int[] levels = {-82, -72};
   2256         int[] security = {SECURITY_NONE, SECURITY_NONE};
   2257 
   2258         List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
   2259         WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
   2260         prepareConfigStore(savedConfigs);
   2261 
   2262         final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
   2263         when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
   2264         scanResultLinkConfiguration(savedConfigs, scanDetails);
   2265 
   2266         ScanResult chosenScanResult = scanDetails.get(1).getScanResult();
   2267 
   2268         WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
   2269                 false, scanDetails, false, false, true, false);
   2270 
   2271         verifySelectedResult(chosenScanResult, candidate);
   2272     }
   2273 }
   2274