/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.server.wifi; import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_EAP; import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_NONE; import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_PSK; import static com.android.server.wifi.WifiConfigurationTestUtil.generateWifiConfig; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import org.mockito.AdditionalAnswers; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.validateMockitoUsage; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Resources; import android.net.NetworkScoreManager; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiInfo; import android.net.wifi.WifiSsid; import android.os.SystemClock; import android.os.UserManager; import android.test.suitebuilder.annotation.SmallTest; import android.util.LocalLog; import com.android.server.wifi.NetworkUpdateResult; import com.android.internal.R; import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments; import com.android.server.wifi.util.ScanDetailUtil; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; /** * Unit tests for {@link com.android.server.wifi.WifiQualifiedNetworkSelector}. */ @SmallTest public class WifiQualifiedNetworkSelectorTest { @Before public void setUp() throws Exception { mResource = getResource(); mScoreManager = getNetworkScoreManager(); mScoreCache = getScoreCache(); mContext = getContext(); mWifiConfigManager = getWifiConfigManager(); mWifiInfo = getWifiInfo(); mLocalLog = getLocalLog(); mWifiQualifiedNetworkSelector = new WifiQualifiedNetworkSelector(mWifiConfigManager, mContext, mWifiInfo, mClock); mWifiQualifiedNetworkSelector.enableVerboseLogging(1); mWifiQualifiedNetworkSelector.setUserPreferredBand(1); mWifiQualifiedNetworkSelector.setWifiNetworkScoreCache(mScoreCache); when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime()); //setup Carrier Networks int eapType = 4; WifiConfiguration wifiConfig = new WifiConfiguration(); wifiConfig.SSID = "\"TEST1\""; wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); wifiConfig.enterpriseConfig = new WifiEnterpriseConfig(); wifiConfig.enterpriseConfig.setEapMethod(eapType); mCarrierConfiguredNetworks.add(wifiConfig); WifiConfiguration wifiConfig1 = new WifiConfiguration(); wifiConfig1.SSID = "\"TEST2\""; wifiConfig1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); wifiConfig1.enterpriseConfig = new WifiEnterpriseConfig(); wifiConfig1.enterpriseConfig.setEapMethod(eapType); mCarrierConfiguredNetworks.add(wifiConfig1); WifiConfiguration wifiConfig2 = new WifiConfiguration(); wifiConfig2.SSID = "\"TEST3\""; wifiConfig2.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); wifiConfig2.enterpriseConfig = new WifiEnterpriseConfig(); wifiConfig2.enterpriseConfig.setEapMethod(eapType); mCarrierConfiguredNetworks.add(wifiConfig2); mWifiQualifiedNetworkSelector.setCarrierConfiguredNetworks(mCarrierConfiguredNetworks); } @After public void cleanup() { validateMockitoUsage(); } private WifiQualifiedNetworkSelector mWifiQualifiedNetworkSelector = null; private WifiConfigManager mWifiConfigManager = null; private Context mContext; private Resources mResource; private NetworkScoreManager mScoreManager; private WifiNetworkScoreCache mScoreCache; private WifiInfo mWifiInfo; private LocalLog mLocalLog; private Clock mClock = mock(Clock.class); private static final String[] DEFAULT_SSIDS = {"\"test1\"", "\"test2\""}; private static final String[] DEFAULT_BSSIDS = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; private static final String TAG = "QNS Unit Test"; List mCarrierConfiguredNetworks = new ArrayList(); private List getScanDetails(String[] ssids, String[] bssids, int[] frequencies, String[] caps, int[] levels) { List scanDetailList = new ArrayList(); long timeStamp = mClock.elapsedRealtime(); for (int index = 0; index < ssids.length; index++) { ScanDetail scanDetail = new ScanDetail(WifiSsid.createFromAsciiEncoded(ssids[index]), bssids[index], caps[index], levels[index], frequencies[index], timeStamp, 0); scanDetailList.add(scanDetail); } return scanDetailList; } Context getContext() { Context context = mock(Context.class); Resources resource = mock(Resources.class); when(context.getResources()).thenReturn(mResource); when(context.getSystemService(Context.NETWORK_SCORE_SERVICE)).thenReturn(mScoreManager); return context; } Resources getResource() { Resources resource = mock(Resources.class); when(resource.getInteger(R.integer.config_wifi_framework_SECURITY_AWARD)).thenReturn(80); when(resource.getInteger(R.integer.config_wifi_framework_RSSI_SCORE_OFFSET)).thenReturn(85); when(resource.getInteger(R.integer.config_wifi_framework_SAME_BSSID_AWARD)).thenReturn(24); when(resource.getInteger(R.integer.config_wifi_framework_LAST_SELECTION_AWARD)) .thenReturn(480); when(resource.getInteger(R.integer.config_wifi_framework_PASSPOINT_SECURITY_AWARD)) .thenReturn(40); when(resource.getInteger(R.integer.config_wifi_framework_SECURITY_AWARD)).thenReturn(80); when(resource.getInteger(R.integer.config_wifi_framework_RSSI_SCORE_SLOPE)).thenReturn(4); return resource; } NetworkScoreManager getNetworkScoreManager() { NetworkScoreManager networkScoreManager = mock(NetworkScoreManager.class); return networkScoreManager; } WifiNetworkScoreCache getScoreCache() { return mock(WifiNetworkScoreCache.class); } LocalLog getLocalLog() { return new LocalLog(0); } WifiInfo getWifiInfo() { WifiInfo wifiInfo = mock(WifiInfo.class); //simulate a disconnected state when(wifiInfo.is24GHz()).thenReturn(true); when(wifiInfo.is5GHz()).thenReturn(false); when(wifiInfo.getRssi()).thenReturn(-70); when(wifiInfo.getNetworkId()).thenReturn(WifiConfiguration.INVALID_NETWORK_ID); when(wifiInfo.getBSSID()).thenReturn(null); when(wifiInfo.getNetworkId()).thenReturn(-1); return wifiInfo; } WifiConfigManager getWifiConfigManager() { WifiConfigManager wifiConfigManager = mock(WifiConfigManager.class); wifiConfigManager.mThresholdSaturatedRssi24 = new AtomicInteger( WifiQualifiedNetworkSelector.RSSI_SATURATION_2G_BAND); wifiConfigManager.mBandAward5Ghz = new AtomicInteger( WifiQualifiedNetworkSelector.BAND_AWARD_5GHz); wifiConfigManager.mCurrentNetworkBoost = new AtomicInteger( WifiQualifiedNetworkSelector.SAME_NETWORK_AWARD); wifiConfigManager.mThresholdQualifiedRssi5 = new AtomicInteger( WifiQualifiedNetworkSelector.QUALIFIED_RSSI_5G_BAND); wifiConfigManager.mThresholdMinimumRssi24 = new AtomicInteger( WifiQualifiedNetworkSelector.MINIMUM_2G_ACCEPT_RSSI); wifiConfigManager.mThresholdMinimumRssi5 = new AtomicInteger( WifiQualifiedNetworkSelector.MINIMUM_5G_ACCEPT_RSSI); when(wifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true); return wifiConfigManager; } /** * This API is used to generate multiple simulated saved configurations used for test * * @param ssid array of SSID of saved configuration * @param security array of securities of saved configuration * @return generated new array of configurations based on input */ private WifiConfiguration[] generateWifiConfigurations(String[] ssid, int[] security) { if (ssid == null || security == null || ssid.length != security.length || ssid.length == 0) { return null; } WifiConfiguration[] configs = new WifiConfiguration[ssid.length]; for (int index = 0; index < ssid.length; index++) { configs[index] = generateWifiConfig(index, 0, ssid[index], false, true, null, null, security[index]); } return configs; } /** * set configuration to a passpoint configuration * * @param config The configuration need to be set as a passipoint configuration */ private void setConfigPasspoint(WifiConfiguration config) { config.FQDN = "android.qns.unitTest"; config.providerFriendlyName = "android.qns.unitTest"; WifiEnterpriseConfig enterpriseConfig = mock(WifiEnterpriseConfig.class); when(enterpriseConfig.getEapMethod()).thenReturn(WifiEnterpriseConfig.Eap.PEAP); } /** * add the Configurations to WifiConfigManager (WifiConfigureStore can take them out according * to the networkd ID) * * @param configs input configuration need to be added to WifiConfigureStore */ private void prepareConfigStore(final WifiConfiguration[] configs) { when(mWifiConfigManager.getWifiConfiguration(anyInt())) .then(new AnswerWithArguments() { public WifiConfiguration answer(int netId) { if (netId >= 0 && netId < configs.length) { return configs[netId]; } else { return null; } } }); } /** * Link scan results to the saved configurations. * * The shorter of the 2 input params will be used to loop over so the inputs don't * need to be of equal length. If there are more scan details then configs the remaining scan * details will be associated with a NULL config. * * @param configs saved configurations * @param scanDetails come in scan results */ private void scanResultLinkConfiguration(WifiConfiguration[] configs, List scanDetails) { if (scanDetails.size() <= configs.length) { for (int i = 0; i < scanDetails.size(); i++) { ScanDetail scanDetail = scanDetails.get(i); List associateWithScanResult = new ArrayList<>(); associateWithScanResult.add(configs[i]); when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(eq(scanDetail), anyBoolean())).thenReturn(associateWithScanResult); } } else { for (int i = 0; i < configs.length; i++) { ScanDetail scanDetail = scanDetails.get(i); List associateWithScanResult = new ArrayList<>(); associateWithScanResult.add(configs[i]); when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(eq(scanDetail), anyBoolean())).thenReturn(associateWithScanResult); } // associated the remaining scan details with a NULL config. for (int i = configs.length; i < scanDetails.size(); i++) { when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(eq(scanDetails.get(i)), anyBoolean())).thenReturn(null); } } } private void configureScoreCache(List scanDetails, Integer[] scores, boolean[] meteredHints) { for (int i = 0; i < scanDetails.size(); i++) { ScanDetail scanDetail = scanDetails.get(i); Integer score = scores[i]; ScanResult scanResult = scanDetail.getScanResult(); if (score != null) { when(mScoreCache.isScoredNetwork(scanResult)).thenReturn(true); when(mScoreCache.hasScoreCurve(scanResult)).thenReturn(true); when(mScoreCache.getNetworkScore(eq(scanResult), anyBoolean())).thenReturn(score); when(mScoreCache.getNetworkScore(scanResult)).thenReturn(score); } else { when(mScoreCache.isScoredNetwork(scanResult)).thenReturn(false); when(mScoreCache.hasScoreCurve(scanResult)).thenReturn(false); when(mScoreCache.getNetworkScore(eq(scanResult), anyBoolean())).thenReturn( WifiNetworkScoreCache.INVALID_NETWORK_SCORE); when(mScoreCache.getNetworkScore(scanResult)).thenReturn( WifiNetworkScoreCache.INVALID_NETWORK_SCORE); } when(mScoreCache.getMeteredHint(scanResult)).thenReturn(meteredHints[i]); } } /** * verify whether the chosen configuration matched with the expected chosen scan result * * @param chosenScanResult the expected chosen scan result * @param candidate the chosen configuration */ private void verifySelectedResult(ScanResult chosenScanResult, WifiConfiguration candidate) { ScanResult candidateScan = candidate.getNetworkSelectionStatus().getCandidate(); assertEquals("choose the wrong SSID", chosenScanResult.SSID, candidate.SSID); assertEquals("choose the wrong BSSID", chosenScanResult.BSSID, candidateScan.BSSID); } // QNS test under disconnected State /** * Case #1 choose 2GHz stronger RSSI test * * In this test. we simulate following scenario * WifiStateMachine is under disconnected state * Two networks test1, test2 are secured network * Both network are enabled, encrypted and at 2.4 GHz * test1 is with RSSI -70 test2 is with RSSI -60 * * Expected behavior: test2 is chosen */ @Test public void chooseNetworkDisconnected2GHighestRssi() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 2417}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-70, -60}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(scanDetails.size() - 1).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #2 choose 5GHz Stronger RSSI Test * * In this test. we simulate following scenario * WifiStateMachine is under disconnected state * Two networks test1, test2 are secured network * Both network are enabled, encrypted and at 5 GHz * test1 is with RSSI -70 test2 is with RSSI -60 * * Expected behavior: test2 is chosen */ @Test public void chooseNetworkDisconnected5GHighestRssi() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {5180, 5610}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-70, -60}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(scanDetails.size() - 1).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #3 5GHz over 2GHz bonus Test * * In this test. we simulate following scenario * WifiStateMachine is under disconnected state * Two networks test1, test2 are secured network * Both network are enabled * test1 is @ 2GHz with RSSI -60 * test2 is @ 5Ghz with RSSI -65 * * Expected behavior: test2 is chosen due to 5GHz bonus */ @Test public void chooseNetworkDisconnect5GOver2GTest() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 5180}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-60, -65}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(scanDetails.size() - 1).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #4 2GHz over 5GHz dur to 5GHz signal too weak test * * In this test. we simulate following scenario * WifiStateMachine is under disconnected state * Two networks test1, test2 are secured network * Both network are enabled * test1 is @ 2GHz with RSSI -60 * test2 is @ 5Ghz with RSSI -75 * * Expected behavior: test1 is chosen due to 5GHz signal is too weak (5GHz bonus can not * compensate) */ @Test public void chooseNetworkDisconnect2GOver5GTest() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 5180}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-60, -75}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #5 2GHz signal Saturation test * * In this test. we simulate following scenario * WifiStateMachine is under disconnected state * Two networks test1, test2 are secured network * Both network are enabled * test1 is @ 2GHz with RSSI -50 * test2 is @ 5Ghz with RSSI -65 * * Expected behavior: test2 is chosen. Although the RSSI delta here is 15 too, because 2GHz RSSI * saturates at -60, the real RSSI delta is only 5, which is less than 5GHz bonus */ @Test public void chooseNetworkDisconnect2GRssiSaturationTest() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 5180}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-50, -65}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(scanDetails.size() - 1).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #6 Minimum RSSI test * * In this test. we simulate following scenario * WifiStateMachine is under disconnected state * Two networks test1, test2 are secured network * Both network are enabled * test1 is @ 2GHz with RSSI -86 * test2 is @ 5Ghz with RSSI -83 * * Expected behavior: no QNS is made because both network are below the minimum threshold, null */ @Test public void chooseNetworkMinimumRssiTest() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 5180}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {WifiQualifiedNetworkSelector.MINIMUM_2G_ACCEPT_RSSI - 1, WifiQualifiedNetworkSelector.MINIMUM_5G_ACCEPT_RSSI - 1}; int[] security = {SECURITY_EAP, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); assertEquals("choose the wrong SSID", null, candidate); } /** * Case #7 encrypted network over passpoint network * * In this test. we simulate following scenario * WifiStateMachine is under disconnected state * Two networks test1 is secured network, test2 are passpoint network * Both network are enabled and at 2.4 GHz. Both have RSSI of -70 * * Expected behavior: test1 is chosen since secured network has higher priority than passpoint * network */ @Test public void chooseNetworkSecurityOverPassPoint() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 2437}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]"}; int[] levels = {-70, -70}; int[] security = {SECURITY_EAP, SECURITY_NONE}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); setConfigPasspoint(savedConfigs[1]); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #8 passpoint network over open network * * In this test. we simulate following scenario * WifiStateMachine is under disconnected state * Two networks test1 is passpoint network, test2 is open network * Both network are enabled and at 2.4 GHz. Both have RSSI of -70 * * Expected behavior: test1 is chosen since passpoint network has higher priority than open * network */ @Test public void chooseNetworkPasspointOverOpen() { String[] ssids = {"\"test1\"", "\"test2\""}; String[] bssids = {"6c:f3:7f:ae:8c:f8", "6c:f3:7f:ae:8c:f4"}; int[] frequencies = {2437, 2437}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-70, -70}; int[] security = {SECURITY_NONE, SECURITY_NONE}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); setConfigPasspoint(savedConfigs[0]); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #9 secure network over open network * * In this test. we simulate following scenario * WifiStateMachine is under disconnected state * Two networks test1 is secure network, test2 is open network * Both network are enabled and at 2.4 GHz. Both have RSSI of -70 * * Expected behavior: test1 is chosen since secured network has higher priority than open * network */ @Test public void chooseNetworkSecureOverOpen() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 2437}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-70, -70}; int[] security = {SECURITY_PSK, SECURITY_NONE}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #10 first time user select a network * * In this test. we simulate following scenario * There are three saved networks: test1, test2 and test3. Now user select the network test3 * check test3 has been saved in test1's and test2's ConnectChoice * * Expected behavior: test1's and test2's ConnectChoice should be test3, test3's ConnectChoice * should be null */ @Test public void userSelectsNetworkForFirstTime() { String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\""}; int[] security = {SECURITY_PSK, SECURITY_PSK, SECURITY_NONE}; final WifiConfiguration[] configs = generateWifiConfigurations(ssids, security); prepareConfigStore(configs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(configs)); for (WifiConfiguration network : configs) { WifiConfiguration.NetworkSelectionStatus status = network.getNetworkSelectionStatus(); status.setSeenInLastQualifiedNetworkSelection(true); } mWifiQualifiedNetworkSelector.userSelectNetwork(configs.length - 1, true); String key = configs[configs.length - 1].configKey(); for (int index = 0; index < configs.length; index++) { WifiConfiguration config = configs[index]; WifiConfiguration.NetworkSelectionStatus status = config.getNetworkSelectionStatus(); if (index == configs.length - 1) { assertEquals("User selected network should not have prefernce over it", null, status.getConnectChoice()); } else { assertEquals("Wrong user preference", key, status.getConnectChoice()); } } } /** * Case #11 choose user selected network * * In this test, we simulate following scenario: * WifiStateMachine is under disconnected state * There are three networks: test1, test2, test3 and test3 is the user preference * All three networks are enabled * test1 is @ 2.4GHz with RSSI -50 PSK * test2 is @ 5Ghz with RSSI -65 PSK * test3 is @ 2.4GHz with RSSI -55 open * * Expected behavior: test3 is chosen since it is user selected network. It overcome all other * priorities */ @Test public void chooseUserPreferredNetwork() { String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\""}; int[] security = {SECURITY_PSK, SECURITY_PSK, SECURITY_NONE}; final WifiConfiguration[] configs = generateWifiConfigurations(ssids, security); prepareConfigStore(configs); for (WifiConfiguration network : configs) { WifiConfiguration.NetworkSelectionStatus status = network.getNetworkSelectionStatus(); status.setSeenInLastQualifiedNetworkSelection(true); } when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(configs)); //set user preference mWifiQualifiedNetworkSelector.userSelectNetwork(ssids.length - 1, true); //Generate mocked recent scan results String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "6c:f3:7f:ae:8c:f5"}; int[] frequencies = {2437, 5180, 2437}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]", "NONE"}; int[] levels = {-50, -65, -55}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); scanResultLinkConfiguration(configs, scanDetails); ScanResult chosenScanResult = scanDetails.get(scanDetails.size() - 1).getScanResult(); when(mWifiConfigManager.getWifiConfiguration(configs[2].configKey())) .thenReturn(configs[2]); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #12 enable a blacklisted BSSID * * In this test, we simulate following scenario: * For two Aps, BSSIDA and BSSIDB. Disable BSSIDA, then check whether BSSIDA is disabled and * BSSIDB is enabled. Then enable BSSIDA, check whether both BSSIDs are enabled. */ @Test public void enableBssidTest() { String bssidA = "6c:f3:7f:ae:8c:f3"; String bssidB = "6c:f3:7f:ae:8c:f4"; //check by default these two BSSIDs should be enabled assertEquals("bssidA should be enabled by default", mWifiQualifiedNetworkSelector.isBssidDisabled(bssidA), false); assertEquals("bssidB should be enabled by default", mWifiQualifiedNetworkSelector.isBssidDisabled(bssidB), false); //disable bssidA 3 times, check whether A is dsiabled and B is still enabled mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssidA, false); assertEquals("bssidA should be disabled", mWifiQualifiedNetworkSelector.isBssidDisabled(bssidA), false); mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssidA, false); assertEquals("bssidA should be disabled", mWifiQualifiedNetworkSelector.isBssidDisabled(bssidA), false); mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssidA, false); assertEquals("bssidA should be disabled", mWifiQualifiedNetworkSelector.isBssidDisabled(bssidA), true); assertEquals("bssidB should still be enabled", mWifiQualifiedNetworkSelector.isBssidDisabled(bssidB), false); //re-enable bssidA, check whether A is dsiabled and B is still enabled mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssidA, true); assertEquals("bssidA should be enabled by default", mWifiQualifiedNetworkSelector.isBssidDisabled(bssidA), false); assertEquals("bssidB should be enabled by default", mWifiQualifiedNetworkSelector.isBssidDisabled(bssidB), false); //make sure illegal input will not cause crash mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(null, false); mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(null, true); } /** * Case #13 do not choose the BSSID has been disabled * * In this test. we simulate following scenario: * WifiStateMachine is under disconnected state * Two networks test1, test2 are secured network and found in scan results * Both network are enabled * test1 is @ 2GHz with RSSI -65 * test2 is @ 5Ghz with RSSI -50 * test2's BSSID is disabled * * expected return test1 since test2's BSSID has been disabled */ @Test public void networkChooseWithOneBssidDisabled() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 5180}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-65, -50}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssids[1], false); mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssids[1], false); mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssids[1], false); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #14 re-choose the disabled BSSID after it is re-enabled * * In this test. we simulate following scenario: * WifiStateMachine is under disconnected state * Two networks test1, test2 are secured network and found in scan results * Both network are enabled * test1 is @ 2GHz with RSSI -65 * test2 is @ 5Ghz with RSSI -50 * test2's BSSID is disabled * * expected return test2 since test2's BSSID has been enabled again */ @Test public void networkChooseWithOneBssidReenaabled() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 5180}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-65, -50}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssids[1], false); mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssids[1], false); mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssids[1], false); //re-enable it mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssids[1], true); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #15 re-choose the disabled BSSID after its disability has expired * * In this test. we simulate following scenario: * WifiStateMachine is under disconnected state * Two networks test1, test2 are secured network and found in scan results * Both network are enabled * test1 is @ 2GHz with RSSI -65 * test2 is @ 5Ghz with RSSI -50 * test2's BSSID is disabled * * expected return test2 since test2's BSSID has been enabled again */ @Test public void networkChooseWithOneBssidDisableExpire() { String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\""}; String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "6c:f3:7f:ae:8c:f5"}; int[] frequencies = {2437, 5180, 5180}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-65, -50, -60}; int[] security = {SECURITY_PSK, SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); for (int index = 0; index < WifiQualifiedNetworkSelector.BSSID_BLACKLIST_THRESHOLD; index++) { mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssids[1], false); mWifiQualifiedNetworkSelector.enableBssidForQualityNetworkSelection(bssids[2], false); } //re-enable it when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + WifiQualifiedNetworkSelector.BSSID_BLACKLIST_EXPIRE_TIME); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #16 do not choose the SSID has been disabled * * In this test. we simulate following scenario: * WifiStateMachine is under disconnected state * Two networks test1, test2 are secured network and found in scan results * Both network are enabled * test1 is @ 2GHz with RSSI -65 * test2 is @ 5Ghz with RSSI -50 * test2's SSID is disabled * * expected return test1 since test2's SSID has been disabled */ @Test public void networkChooseWithOneSsidDisabled() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 5180}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-65, -50}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); when(mWifiConfigManager.tryEnableQualifiedNetwork(anyInt())).thenReturn(true); savedConfigs[1].getNetworkSelectionStatus().setNetworkSelectionStatus( WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #17 do not make QNS is link is bouncing now * * In this test. we simulate following scenario: * WifiStateMachine is under disconnected state and currently is under link bouncing * Two networks test1, test2 are secured network and found in scan results * Both network are enabled * test1 is @ 2GHz with RSSI -50 * test2 is @ 5Ghz with RSSI -50 * * expected return null */ @Test public void noQNSWhenLinkBouncingDisconnected() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 5180}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {WifiQualifiedNetworkSelector.MINIMUM_2G_ACCEPT_RSSI - 1, WifiQualifiedNetworkSelector.MINIMUM_5G_ACCEPT_RSSI - 1}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, true, false, true, false); assertEquals("choose the wrong network", null, candidate); } /** * Case #18 QNS with very short gap * * In this test. we simulate following scenario: * WifiStateMachine is under disconnected state * If last QNS is made in less than MINIMUM_QUALIFIED_NETWORK_SELECTION_INTERVAL, we * still should make new QNS since it is disconnected now * * expect return test1 because of band bonus */ @Test public void networkSelectionInShortGap() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 5180}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-50, -65}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); //first QNS mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); //immediately second QNS WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); verifySelectedResult(chosenScanResult, candidate); } //Unit test for Connected State /** * Case #19 no QNS with very short gap when connected * In this test. we simulate following scenario: * WifiStateMachine is under connected state and test2 is connected * When WifiStateMachine is already in connected state, if last QNS is made in less than * MINIMUM_QUALIFIED_NETWORK_SELECTION_INTERVAL, no new QNS should be made * * expect return NULL */ @Test public void noNetworkSelectionDueToShortGap() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 5180}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-50, -65}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); //first QNS mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); //immediately second QNS WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, true, false, false); ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); assertEquals("choose the wrong BSSID", null, candidate); } /** * Case #20 force QNS with very short gap under connection * In this test. we simulate following scenario: * WifiStateMachine is under connected state and test2 is connected * When WifiStateMachine is already in connected state, if last QNS is made in less than * MINIMUM_QUALIFIED_NETWORK_SELECTION_INTERVAL, no new QNS should be made. However, if we force * to make new QNS, QNS still will be made * * expect return test2 since it is the current connected one (bonus) */ @Test public void forceNetworkSelectionInShortGap() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 5180}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-50, -65}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); //first QNS mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); when(mWifiInfo.getNetworkId()).thenReturn(1); when(mWifiInfo.getBSSID()).thenReturn(bssids[1]); when(mWifiInfo.is24GHz()).thenReturn(false); when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true); //immediately second QNS WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(true, false, scanDetails, false, true, false, false); ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); verifySelectedResult(chosenScanResult, candidate); } /** * Case #21 no QNS when connected and user do not allow switch when connected * * In this test. we simulate following scenario: * WifiStateMachine is under connected state and test2 is connected * if user does not allow switch network when connected, do not make new QNS when connected * * expect return NULL */ @Test public void noNewNetworkSelectionDuetoUserDisableSwitchWhenConnected() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 5180}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-50, -65}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, true, false, false); assertEquals("choose the wrong BSSID", null, candidate); assertEquals("Should receive zero filteredScanDetails", 0, mWifiQualifiedNetworkSelector.getFilteredScanDetails().size()); } /** * Case #22 no new QNS if current network is qualified already * * In this test. we simulate following scenario: * WifiStateMachine is under connected state and test2 is connected * If current connected network is Qualified already, do not make new QNS * simulated current connected network as: * 5GHz, RSSI = WifiQualifiedNetworkSelector.QUALIFIED_RSSI_5G_BAND, secured * * expected return null */ @Test public void noNewQNSCurrentNetworkQualified() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 5180}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-65, WifiQualifiedNetworkSelector.QUALIFIED_RSSI_5G_BAND}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); //first time, connect to test2 due to 5GHz bonus mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); when(mWifiInfo.getNetworkId()).thenReturn(1); when(mWifiInfo.getBSSID()).thenReturn(bssids[1]); when(mWifiInfo.is24GHz()).thenReturn(false); when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true); when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000); levels[0] = -50; // if there is QNS, test1 will be chosen scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); scanResultLinkConfiguration(savedConfigs, scanDetails); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, true, false, false); assertEquals("choose the wrong BSSID", null, candidate); } /** * Case #23 No new QNS when link bouncing when connected * * In this test. we simulate following scenario: * WifiStateMachine is under connected state and test2 is connected * no new QNS when link is bouncing * * expected return null */ @Test public void noNewQNSLinkBouncing() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 5180}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-70, -75}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); //first connect to test2 due to 5GHz bonus mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); when(mWifiInfo.getNetworkId()).thenReturn(1); when(mWifiInfo.getBSSID()).thenReturn(bssids[1]); when(mWifiInfo.is24GHz()).thenReturn(false); when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000); when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, true, true, false, false); assertEquals("choose the wrong BSSID", null, candidate); } /** * Case #24 Qualified network need to be on 5GHz * * In this test. we simulate following scenario: * WifiStateMachine is under connected state and connected to test2 * if current connected network is not 5GHz, then it is not qualified. We should make new QNS * * expected result: return test1 */ @Test public void currentNetworkNotQualifiedDueToBandMismatch() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 2437}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-50, -65}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); when(mWifiInfo.getNetworkId()).thenReturn(0); when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); when(mWifiInfo.is24GHz()).thenReturn(true); //connect to config2 first mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000); when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, true, false, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #25 Qualified network need to be secured * * In this test. we simulate following scenario: * WifiStateMachine is under connected state and current connects to test2 * if current connected network is open network, then it is not qualified. We should make new * QNS * * expected result: return test1 since test1 has higher RSSI */ @Test public void currentNetworkNotQualifiedDueToOpenNetwork() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {5400, 5400}; String[] caps = {"[ESS]", "[ESS]"}; int[] levels = {-70, -65}; int[] security = {SECURITY_NONE, SECURITY_NONE}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); //first connect to test2 because of RSSI mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); when(mWifiInfo.getNetworkId()).thenReturn(1); when(mWifiInfo.getBSSID()).thenReturn(bssids[1]); when(mWifiInfo.is24GHz()).thenReturn(false); when(mWifiInfo.is5GHz()).thenReturn(true); when(mWifiConfigManager.isOpenNetwork(savedConfigs[1])).thenReturn(true); when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000); when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true); levels[0] = -60; scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, true, false, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #26 ephemeral network can not be qualified network * * In this test. we simulate following scenario: * WifiStateMachine is under connected state and current connected to test2 * if current connected network is ephemeral network, then it is not qualified. We should make * new QNS * * expected result: return test1 (since test2 is ephemeral) */ @Test public void currentNetworkNotQualifiedDueToEphemeral() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {5200, 5200}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-100, -50}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); savedConfigs[1].ephemeral = true; prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); //first connect to test2 since test1's RSSI is negligible mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); when(mWifiInfo.getNetworkId()).thenReturn(1); when(mWifiInfo.getBSSID()).thenReturn(bssids[1]); when(mWifiInfo.is24GHz()).thenReturn(false); levels[0] = -70; scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); scanResultLinkConfiguration(savedConfigs, scanDetails); when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true); when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, true, false, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #27 low signal network can not be Qualified network (5GHz) * * In this test. we simulate following scenario: * WifiStateMachine is under connected state and current connected to test2 * if current connected network's rssi is too low, then it is not qualified. We should * make new QNS * * expected result: return test1 */ @Test public void currentNetworkNotQualifiedDueToLow5GRssi() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {5200, 5200}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-80, WifiQualifiedNetworkSelector.QUALIFIED_RSSI_5G_BAND - 1}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); when(mWifiInfo.getNetworkId()).thenReturn(1); when(mWifiInfo.getBSSID()).thenReturn(bssids[1]); when(mWifiInfo.getRssi()).thenReturn(levels[1]); when(mWifiInfo.is24GHz()).thenReturn(false); when(mWifiInfo.is5GHz()).thenReturn(true); when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true); when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000); levels[0] = -60; scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, true, false, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #28 low signal network can not be Qualified network (2.4GHz) * * In this test. we simulate following scenario: * WifiStateMachine is under connected state and current connected to test2 * if current connected network's rssi is too low, then it is not qualified. We should * make new QNS * * expected result: return test1 */ @Test public void currentNetworkNotQualifiedDueToLow2GRssi() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 2437}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-100, WifiQualifiedNetworkSelector.QUALIFIED_RSSI_24G_BAND - 1}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); when(mWifiInfo.getNetworkId()).thenReturn(1); when(mWifiInfo.getBSSID()).thenReturn(bssids[1]); when(mWifiInfo.getRssi()).thenReturn(levels[1]); when(mWifiInfo.is24GHz()).thenReturn(false); when(mWifiInfo.is5GHz()).thenReturn(true); when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true); levels[0] = -60; scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, true, false, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #29 Choose current network due to current network bonus * * In this test. we simulate following scenario: * WifiStateMachine is under connected state and current connected to test2 * To connect to a network which is not linked to current connected network, unless this network * is more than 10 db higher than current network, we should not switch. So although test2 has a * lower signal, we still choose test2 * * expected result: return test2 */ @Test public void currentNetworkStayDueToSameNetworkBonus() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 2437}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-100, -80}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); when(mWifiInfo.getNetworkId()).thenReturn(1); when(mWifiInfo.getBSSID()).thenReturn(bssids[1]); when(mWifiInfo.is24GHz()).thenReturn(true); when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true); levels[0] = -80 + WifiQualifiedNetworkSelector.SAME_BSSID_AWARD / 4 + WifiQualifiedNetworkSelector.SAME_NETWORK_AWARD / 4 - 1; scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, true, false, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #30 choose another network due to current network's signal is too low * * In this test. we simulate following scenario: * WifiStateMachine is under connected state and current connected to test2 * To connect to a network which is not linked to current connected network, if this network * is more than 10 db higher than current network, we should switch * * expected new result: return test1 */ @Test public void switchNetworkStayDueToCurrentNetworkRssiLow() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 2437}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-100, -80}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); when(mWifiInfo.getNetworkId()).thenReturn(1); when(mWifiInfo.getBSSID()).thenReturn(bssids[1]); when(mWifiInfo.is24GHz()).thenReturn(true); when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true); levels[0] = -80 + WifiQualifiedNetworkSelector.SAME_BSSID_AWARD / 4 + WifiQualifiedNetworkSelector.SAME_NETWORK_AWARD / 4 + 1; scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, true, false, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #31 Choose current BSSID due to current BSSID bonus * * In this test. we simulate following scenario: * WifiStateMachine is under connected state and current connected to test2 * Linked network will be treated as same network. To connect to a network which is linked to * current connected network, unless this network is more than 6 db higher than current network, * we should not switch AP and stick to current BSSID * * expected result: return test2 */ @Test public void currentBssidStayDueToSameBSSIDBonus() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 2437}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-100, -80}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); //link two configuration savedConfigs[0].linkedConfigurations = new HashMap(); savedConfigs[1].linkedConfigurations = new HashMap(); savedConfigs[0].linkedConfigurations.put(savedConfigs[1].configKey(), 1); savedConfigs[1].linkedConfigurations.put(savedConfigs[0].configKey(), 1); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); when(mWifiInfo.getNetworkId()).thenReturn(1); when(mWifiInfo.getBSSID()).thenReturn(bssids[1]); when(mWifiInfo.is24GHz()).thenReturn(true); when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true); levels[0] = -80 + WifiQualifiedNetworkSelector.SAME_NETWORK_AWARD / 4 - 1; scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, true, false, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #32 Choose another BSSID due to current BSSID's rssi is too low * * In this test. we simulate following scenario: * WifiStateMachine is under connected state and current connected to test2 * Linked network will be treated as same network. To connect to a network which is linked to * current connected network, unless this network is more than 6 db higher than current network, * we should not switch AP and stick to current BSSID * * expected result: return test2 */ @Test public void swithBssidDueToLowRssi() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {2437, 2437}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS][ESS]"}; int[] levels = {-100, -80}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); //link two configuration savedConfigs[0].linkedConfigurations = new HashMap(); savedConfigs[1].linkedConfigurations = new HashMap(); savedConfigs[0].linkedConfigurations.put(savedConfigs[1].configKey(), 1); savedConfigs[1].linkedConfigurations.put(savedConfigs[0].configKey(), 1); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); when(mWifiInfo.getNetworkId()).thenReturn(1); when(mWifiInfo.getBSSID()).thenReturn(bssids[1]); when(mWifiInfo.is24GHz()).thenReturn(true); when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true); levels[0] = -80 + WifiQualifiedNetworkSelector.SAME_BSSID_AWARD / 4 + 1; scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, true, false, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #33 Choose an ephemeral network with a good score because no saved networks * are available. * * In this test. we simulate following scenario: * WifiStateMachine is not connected to any network. * selectQualifiedNetwork() is called with 2 scan results, test1 and test2. * test1 is an enterprise network w/o a score. * test2 is an open network with a good score. Additionally it's a metered network. * isUntrustedConnectionsAllowed is set to true. * * expected result: return test2 with meteredHint set to True. */ @Test public void selectQualifiedNetworkChoosesEphemeral() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {5200, 5200}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]"}; int[] levels = {-70, -70}; Integer[] scores = {null, 120}; boolean[] meteredHints = {false, true}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); configureScoreCache(scanDetails, scores, meteredHints); // No saved networks. when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(any(ScanDetail.class), anyBoolean())).thenReturn(null); WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class); // Setup the config as an invalid candidate. This is done to workaround a Mockito issue. // Basically Mockito is unable to mock package-private methods in classes loaded from a // different Jar (like all of the framework code) which results in the actual saveNetwork() // method being invoked in this case. Because the config is invalid it quickly returns. unTrustedNetworkCandidate.SSID = null; unTrustedNetworkCandidate.networkId = WifiConfiguration.INVALID_NETWORK_ID; ScanResult untrustedScanResult = scanDetails.get(1).getScanResult(); when(mWifiConfigManager .wifiConfigurationFromScanResult(untrustedScanResult)) .thenReturn(unTrustedNetworkCandidate); WifiConfiguration.NetworkSelectionStatus selectionStatus = mock(WifiConfiguration.NetworkSelectionStatus.class); when(unTrustedNetworkCandidate.getNetworkSelectionStatus()).thenReturn(selectionStatus); when(selectionStatus.getCandidate()).thenReturn(untrustedScanResult); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork( false /* forceSelectNetwork */, true /* isUntrustedConnectionsAllowed */, scanDetails, false, /* isLinkDebouncing */ false, /* isConnected */ true, /* isDisconnected */ false /* isSupplicantTransient */); verify(selectionStatus).setCandidate(untrustedScanResult); assertSame(unTrustedNetworkCandidate, candidate); assertEquals(meteredHints[1], candidate.meteredHint); } /** * Case #34 Test Filtering of potential candidate scanDetails (Untrusted allowed) * * In this test. we simulate following scenario * WifiStateMachine is under disconnected state * test1 is @ 2GHz with RSSI -60 * test2 is @ 5Ghz with RSSI -86, (below minimum threshold) * test3 is @ 5Ghz with RSSI -50, however it has no associated saved config * test4 is @ 2Ghz with RSSI -62, no associated config, but is Ephemeral * * Expected behavior: test1 is chosen due to 5GHz signal is too weak (5GHz bonus can not * compensate). * test1 & test4's scanDetails are returned by 'getFilteredScanDetail()' */ @Test public void testGetFilteredScanDetailsReturnsOnlyConsideredScanDetails_untrustedAllowed() { String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\"", "\"test4\""}; String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "de:ad:ba:b1:e5:55", "c0:ff:ee:ee:e3:ee"}; int[] frequencies = {2437, 5180, 5180, 2437}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; int[] levels = {-60, -86, -50, -62}; int[] security = {SECURITY_PSK, SECURITY_PSK, SECURITY_PSK, SECURITY_PSK}; boolean[] meteredHints = {false, false, false, true}; Integer[] scores = {null, null, null, 120}; //Create all 4 scanDetails List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); //Setup NetworkScoreCache for detecting ephemeral networks ("test4") configureScoreCache(scanDetails, scores, meteredHints); WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class); unTrustedNetworkCandidate.SSID = null; unTrustedNetworkCandidate.networkId = WifiConfiguration.INVALID_NETWORK_ID; ScanResult untrustedScanResult = scanDetails.get(3).getScanResult(); when(mWifiConfigManager .wifiConfigurationFromScanResult(untrustedScanResult)) .thenReturn(unTrustedNetworkCandidate); WifiConfiguration.NetworkSelectionStatus selectionStatus = mock(WifiConfiguration.NetworkSelectionStatus.class); when(unTrustedNetworkCandidate.getNetworkSelectionStatus()).thenReturn(selectionStatus); //Set up associated configs for test1 & test2 WifiConfiguration[] savedConfigs = generateWifiConfigurations( Arrays.copyOfRange(ssids, 0, 2), Arrays.copyOfRange(security, 0, 2)); prepareConfigStore(savedConfigs); List savedScanDetails = new ArrayList(scanDetails.subList(0, 2)); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, savedScanDetails); //Force mock ConfigManager to return null (and not an empty list) for "test3" & "test4" when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(eq(scanDetails.get(2)), anyBoolean())).thenReturn(null); when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(eq(scanDetails.get(3)), anyBoolean())).thenReturn(null); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork( false /* forceSelectNetwork */, true /* isUntrustedConnectionsAllowed */, scanDetails, false, /* isLinkDebouncing */ false, /* isConnected */ true, /* isDisconnected */ false /* isSupplicantTransient */); verifySelectedResult(chosenScanResult, candidate); //Verify two scanDetails returned in the filteredScanDetails assertEquals(2, mWifiQualifiedNetworkSelector.getFilteredScanDetails().size()); assertEquals(mWifiQualifiedNetworkSelector.getFilteredScanDetails().get(0).first.toString(), scanDetails.get(0).toString()); assertEquals(mWifiQualifiedNetworkSelector.getFilteredScanDetails().get(1).first.toString(), scanDetails.get(3).toString()); } /** * Case #35 Test Filtering of potential candidate scanDetails (Untrusted disallowed) * * In this test. we simulate following scenario * WifiStateMachine is under disconnected state * test1 is @ 2GHz with RSSI -60 * test2 is @ 5Ghz with RSSI -86, (below minimum threshold) * test3 is @ 5Ghz with RSSI -50, however it has no associated saved config * test4 is @ 2Ghz with RSSI -62, no associated config, but is Ephemeral * * Expected behavior: test1 is chosen due to 5GHz signal is too weak (5GHz bonus can not * compensate). * test1 & test4's scanDetails are returned by 'getFilteredScanDetail()' */ @Test public void testGetFilteredScanDetailsReturnsOnlyConsideredScanDetails_untrustedDisallowed() { String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\"", "\"test4\""}; String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "de:ad:ba:b1:e5:55", "c0:ff:ee:ee:e3:ee"}; int[] frequencies = {2437, 5180, 5180, 2437}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; int[] levels = {-60, -86, -50, -62}; int[] security = {SECURITY_PSK, SECURITY_PSK, SECURITY_PSK, SECURITY_PSK}; boolean[] meteredHints = {false, false, false, true}; Integer[] scores = {null, null, null, 120}; //Create all 4 scanDetails List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); //Setup NetworkScoreCache for detecting ephemeral networks ("test4") configureScoreCache(scanDetails, scores, meteredHints); WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class); unTrustedNetworkCandidate.SSID = null; unTrustedNetworkCandidate.networkId = WifiConfiguration.INVALID_NETWORK_ID; ScanResult untrustedScanResult = scanDetails.get(3).getScanResult(); when(mWifiConfigManager .wifiConfigurationFromScanResult(untrustedScanResult)) .thenReturn(unTrustedNetworkCandidate); WifiConfiguration.NetworkSelectionStatus selectionStatus = mock(WifiConfiguration.NetworkSelectionStatus.class); when(unTrustedNetworkCandidate.getNetworkSelectionStatus()).thenReturn(selectionStatus); //Set up associated configs for test1 & test2 WifiConfiguration[] savedConfigs = generateWifiConfigurations( Arrays.copyOfRange(ssids, 0, 2), Arrays.copyOfRange(security, 0, 2)); prepareConfigStore(savedConfigs); List savedScanDetails = new ArrayList(scanDetails.subList(0, 2)); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, savedScanDetails); //Force mock ConfigManager to return null (and not an empty list) for "test3" & "test4" when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(eq(scanDetails.get(2)), anyBoolean())).thenReturn(null); when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(eq(scanDetails.get(3)), anyBoolean())).thenReturn(null); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork( false /* forceSelectNetwork */, false /* isUntrustedConnectionsAllowed */, scanDetails, false, /* isLinkDebouncing */ false, /* isConnected */ true, /* isDisconnected */ false /* isSupplicantTransient */); verifySelectedResult(chosenScanResult, candidate); //Verify two scanDetails returned in the filteredScanDetails assertEquals(1, mWifiQualifiedNetworkSelector.getFilteredScanDetails().size()); assertEquals(mWifiQualifiedNetworkSelector.getFilteredScanDetails().get(0).first.toString(), scanDetails.get(0).toString()); } /** * Case #36 Ignore an ephemeral network if it was previously deleted. * * In this test. we simulate following scenario: * WifiStateMachine is not connected to any network. * selectQualifiedNetwork() is called with 2 scan results, test1 and test2. * test1 is an open network with a low score. Additionally it's a metered network. * test2 is an open network with a good score but was previously deleted. * isUntrustedConnectionsAllowed is set to true. * * expected result: return test1 with meteredHint set to True. */ @Test public void selectQualifiedNetworkDoesNotChooseDeletedEphemeral() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {5200, 5200}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]"}; int[] levels = {-70, -70}; Integer[] scores = {20, 120}; boolean[] meteredHints = {true, false}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); configureScoreCache(scanDetails, scores, meteredHints); // No saved networks. when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(any(ScanDetail.class), anyBoolean())).thenReturn(null); WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class); // Setup the config as an invalid candidate. This is done to workaround a Mockito issue. // Basically Mockito is unable to mock package-private methods in classes loaded from a // different Jar (like all of the framework code) which results in the actual saveNetwork() // method being invoked in this case. Because the config is invalid it quickly returns. unTrustedNetworkCandidate.SSID = null; unTrustedNetworkCandidate.networkId = WifiConfiguration.INVALID_NETWORK_ID; ScanResult untrustedScanResult = scanDetails.get(0).getScanResult(); when(mWifiConfigManager .wifiConfigurationFromScanResult(untrustedScanResult)) .thenReturn(unTrustedNetworkCandidate); // The second scan result is for an ephemeral network which was previously deleted when(mWifiConfigManager .wasEphemeralNetworkDeleted(ScanDetailUtil.createQuotedSSID( scanDetails.get(0).getScanResult().SSID))) .thenReturn(false); when(mWifiConfigManager .wasEphemeralNetworkDeleted(ScanDetailUtil.createQuotedSSID( scanDetails.get(1).getScanResult().SSID))) .thenReturn(true); WifiConfiguration.NetworkSelectionStatus selectionStatus = mock(WifiConfiguration.NetworkSelectionStatus.class); when(unTrustedNetworkCandidate.getNetworkSelectionStatus()).thenReturn(selectionStatus); when(selectionStatus.getCandidate()).thenReturn(untrustedScanResult); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork( false /* forceSelectNetwork */, true /* isUntrustedConnectionsAllowed */, scanDetails, false, /* isLinkDebouncing */ false, /* isConnected */ true, /* isDisconnected */ false /* isSupplicantTransient */); verify(selectionStatus).setCandidate(untrustedScanResult); assertSame(candidate, unTrustedNetworkCandidate); assertEquals(meteredHints[0], candidate.meteredHint); } /** * Case #37 Choose the saved config that doesn't qualify for external scoring. * * In this test. we simulate following scenario: * WifiStateMachine is not connected to any network. * selectQualifiedNetwork() is called with 2 scan results, test1 and test2. * test1 is a saved network. * test2 is a saved network with useExternalScores set to true and a very high score. * * expected result: return test1 because saved networks that don't request external scoring * have a higher priority. */ @Test public void selectQualifiedNetworkPrefersSavedWithoutExternalScores() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {5200, 5200}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]"}; int[] security = {SECURITY_PSK, SECURITY_PSK}; int[] levels = {-70, -70}; Integer[] scores = {null, 120}; boolean[] meteredHints = {false, true}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); configureScoreCache(scanDetails, scores, meteredHints); WifiConfiguration[] savedConfigs = generateWifiConfigurations(DEFAULT_SSIDS, security); savedConfigs[1].useExternalScores = true; // test2 is set to use external scores. prepareConfigStore(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(savedConfigs)); scanResultLinkConfiguration(savedConfigs, scanDetails); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork( false /* forceSelectNetwork */, false /* isUntrustedConnectionsAllowed */, scanDetails, false, /* isLinkDebouncing */ false, /* isConnected */ true, /* isDisconnected */ false /* isSupplicantTransient */); verifySelectedResult(scanDetails.get(0).getScanResult(), candidate); assertSame(candidate, savedConfigs[0]); } /** * Case #38 Choose the saved config that does qualify for external scoring when other saved * networks are not available. * * In this test. we simulate following scenario: * WifiStateMachine is not connected to any network. * selectQualifiedNetwork() is called with 2 scan results, test1 and test2. * test1 is a saved network with useExternalScores set to true and a very high score. * test2 is a saved network but not in range (not included in the scan results). * * expected result: return test1 because there are no better saved networks within range. */ @Test public void selectQualifiedNetworkSelectsSavedWithExternalScores() { String[] ssids = {"\"test1\""}; String[] bssids = {"6c:f3:7f:ae:8c:f3"}; int[] frequencies = {5200}; String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; int[] security = {SECURITY_PSK, SECURITY_PSK}; int[] levels = {-70}; Integer[] scores = {120}; boolean[] meteredHints = {false}; // Scan details only contains 1 ssid, test1. List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); configureScoreCache(scanDetails, scores, meteredHints); // The saved config contains 2 ssids, test1 & test2. WifiConfiguration[] savedConfigs = generateWifiConfigurations(DEFAULT_SSIDS, security); savedConfigs[0].useExternalScores = true; // test1 is set to use external scores. prepareConfigStore(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(savedConfigs)); scanResultLinkConfiguration(savedConfigs, scanDetails); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork( false /* forceSelectNetwork */, false /* isUntrustedConnectionsAllowed */, scanDetails, false, /* isLinkDebouncing */ false, /* isConnected */ true, /* isDisconnected */ false /* isSupplicantTransient */); verifySelectedResult(scanDetails.get(0).getScanResult(), candidate); assertSame(candidate, savedConfigs[0]); } /** * Case #39 Choose the saved config that does qualify for external scoring over the * untrusted network with the same score. * * In this test. we simulate following scenario: * WifiStateMachine is not connected to any network. * selectQualifiedNetwork() is called with 2 scan results, test1 and test2. * test1 is a saved network with useExternalScores set to true and the same score as test1. * test2 is NOT saved network but in range with a good external score. * * expected result: return test1 because the tie goes to the saved network. */ @Test public void selectQualifiedNetworkPrefersSavedWithExternalScoresOverUntrusted() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {5200, 5200}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]"}; int[] security = {SECURITY_PSK, SECURITY_PSK}; int[] levels = {-70, -70}; Integer[] scores = {120, 120}; boolean[] meteredHints = {false, true}; // Both networks are in the scan results. List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); configureScoreCache(scanDetails, scores, meteredHints); // Set up the associated configs only for test1 WifiConfiguration[] savedConfigs = generateWifiConfigurations( Arrays.copyOfRange(ssids, 0, 1), Arrays.copyOfRange(security, 0, 1)); savedConfigs[0].useExternalScores = true; // test1 is set to use external scores. prepareConfigStore(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(savedConfigs)); scanResultLinkConfiguration(savedConfigs, scanDetails); WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class); when(mWifiConfigManager .wifiConfigurationFromScanResult(scanDetails.get(1).getScanResult())) .thenReturn(unTrustedNetworkCandidate); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork( false /* forceSelectNetwork */, true /* isUntrustedConnectionsAllowed */, scanDetails, false, /* isLinkDebouncing */ false, /* isConnected */ true, /* isDisconnected */ false /* isSupplicantTransient */); verifySelectedResult(scanDetails.get(0).getScanResult(), candidate); assertSame(candidate, savedConfigs[0]); } /** * Case #40 Choose the ephemeral config over the saved config that does qualify for external * scoring because the untrusted network has a higher score. * * In this test. we simulate following scenario: * WifiStateMachine is not connected to any network. * selectQualifiedNetwork() is called with 2 scan results, test1 and test2. * test1 is a saved network with useExternalScores set to true and a low score. * test2 is NOT saved network but in range with a good external score. * * expected result: return test2 because it has a better score. */ @Test public void selectQualifiedNetworkPrefersUntrustedOverScoredSaved() { String[] ssids = DEFAULT_SSIDS; String[] bssids = DEFAULT_BSSIDS; int[] frequencies = {5200, 5200}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]"}; int[] security = {SECURITY_PSK, SECURITY_PSK}; int[] levels = {-70, -70}; Integer[] scores = {10, 120}; boolean[] meteredHints = {false, true}; // Both networks are in the scan results. List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); configureScoreCache(scanDetails, scores, meteredHints); // Set up the associated configs only for test1 WifiConfiguration[] savedConfigs = generateWifiConfigurations( Arrays.copyOfRange(ssids, 0, 1), Arrays.copyOfRange(security, 0, 1)); savedConfigs[0].useExternalScores = true; // test1 is set to use external scores. prepareConfigStore(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(savedConfigs)); scanResultLinkConfiguration(savedConfigs, scanDetails); WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class); unTrustedNetworkCandidate.SSID = null; unTrustedNetworkCandidate.networkId = WifiConfiguration.INVALID_NETWORK_ID; ScanResult untrustedScanResult = scanDetails.get(1).getScanResult(); when(mWifiConfigManager .wifiConfigurationFromScanResult(untrustedScanResult)) .thenReturn(unTrustedNetworkCandidate); WifiConfiguration.NetworkSelectionStatus selectionStatus = mock(WifiConfiguration.NetworkSelectionStatus.class); when(unTrustedNetworkCandidate.getNetworkSelectionStatus()).thenReturn(selectionStatus); when(selectionStatus.getCandidate()).thenReturn(untrustedScanResult); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork( false /* forceSelectNetwork */, true /* isUntrustedConnectionsAllowed */, scanDetails, false, /* isLinkDebouncing */ false, /* isConnected */ true, /* isDisconnected */ false /* isSupplicantTransient */); verify(selectionStatus).setCandidate(untrustedScanResult); assertSame(unTrustedNetworkCandidate, candidate); } /** * Case #41 Ensure the ExternalScoreEvaluator correctly selects the untrusted network. * * In this test. we simulate following scenario: * The ExternalScoreEvaluator is asked to evaluate 1 untrusted network and 1 saved network. * The untrusted network has the higher score. * * expected result: The untrusted network is determined to be the best network. */ @Test public void externalScoreEvaluator_untrustedIsBest() { WifiQualifiedNetworkSelector.ExternalScoreEvaluator evaluator = new WifiQualifiedNetworkSelector.ExternalScoreEvaluator(mLocalLog, true); ScanResult untrustedScanResult = new ScanResult(); int untrustedScore = 100; evaluator.evalUntrustedCandidate(untrustedScore, untrustedScanResult); ScanResult savedScanResult = new ScanResult(); int savedScore = 50; WifiConfiguration savedConfig = new WifiConfiguration(); evaluator.evalSavedCandidate(savedScore, savedConfig, savedScanResult); assertEquals(WifiQualifiedNetworkSelector.ExternalScoreEvaluator .BestCandidateType.UNTRUSTED_NETWORK, evaluator.getBestCandidateType()); assertEquals(untrustedScore, evaluator.getHighScore()); assertSame(untrustedScanResult, evaluator.getScanResultCandidate()); } /** * Case #42 Ensure the ExternalScoreEvaluator correctly selects the saved network. * * In this test. we simulate following scenario: * The ExternalScoreEvaluator is asked to evaluate 1 untrusted network and 1 saved network. * The saved network has the higher score. * * expected result: The saved network is determined to be the best network. */ @Test public void externalScoreEvaluator_savedIsBest() { WifiQualifiedNetworkSelector.ExternalScoreEvaluator evaluator = new WifiQualifiedNetworkSelector.ExternalScoreEvaluator(mLocalLog, true); ScanResult untrustedScanResult = new ScanResult(); int untrustedScore = 50; evaluator.evalUntrustedCandidate(untrustedScore, untrustedScanResult); ScanResult savedScanResult = new ScanResult(); int savedScore = 100; WifiConfiguration savedConfig = new WifiConfiguration(); evaluator.evalSavedCandidate(savedScore, savedConfig, savedScanResult); assertEquals(WifiQualifiedNetworkSelector.ExternalScoreEvaluator .BestCandidateType.SAVED_NETWORK, evaluator.getBestCandidateType()); assertEquals(savedScore, evaluator.getHighScore()); assertSame(savedScanResult, evaluator.getScanResultCandidate()); } /** * Case #43 Ensure the ExternalScoreEvaluator correctly selects the saved network if a * tie occurs. * * In this test. we simulate following scenario: * The ExternalScoreEvaluator is asked to evaluate 1 untrusted network and 1 saved network. * Both networks have the same score. * * expected result: The saved network is determined to be the best network. */ @Test public void externalScoreEvaluator_tieScores() { WifiQualifiedNetworkSelector.ExternalScoreEvaluator evaluator = new WifiQualifiedNetworkSelector.ExternalScoreEvaluator(mLocalLog, true); ScanResult untrustedScanResult = new ScanResult(); int untrustedScore = 100; evaluator.evalUntrustedCandidate(untrustedScore, untrustedScanResult); ScanResult savedScanResult = new ScanResult(); int savedScore = 100; WifiConfiguration savedConfig = new WifiConfiguration(); evaluator.evalSavedCandidate(savedScore, savedConfig, savedScanResult); assertEquals(WifiQualifiedNetworkSelector.ExternalScoreEvaluator .BestCandidateType.SAVED_NETWORK, evaluator.getBestCandidateType()); assertEquals(savedScore, evaluator.getHighScore()); assertSame(savedScanResult, evaluator.getScanResultCandidate()); } /** * Case #44 Ensure the ExternalScoreEvaluator correctly selects the saved network out of * multiple options. * * In this test. we simulate following scenario: * The ExternalScoreEvaluator is asked to evaluate 2 untrusted networks and 2 saved networks. * The high scores are equal and the low scores differ. * * expected result: The saved network is determined to be the best network. */ @Test public void externalScoreEvaluator_multipleScores() { WifiQualifiedNetworkSelector.ExternalScoreEvaluator evaluator = new WifiQualifiedNetworkSelector.ExternalScoreEvaluator(mLocalLog, true); ScanResult untrustedScanResult = new ScanResult(); int untrustedScore = 100; evaluator.evalUntrustedCandidate(untrustedScore, untrustedScanResult); evaluator.evalUntrustedCandidate(80, new ScanResult()); ScanResult savedScanResult = new ScanResult(); int savedScore = 100; WifiConfiguration savedConfig = new WifiConfiguration(); evaluator.evalSavedCandidate(savedScore, savedConfig, savedScanResult); evaluator.evalSavedCandidate(90, new WifiConfiguration(), new ScanResult()); assertEquals(WifiQualifiedNetworkSelector.ExternalScoreEvaluator .BestCandidateType.SAVED_NETWORK, evaluator.getBestCandidateType()); assertEquals(savedScore, evaluator.getHighScore()); assertSame(savedScanResult, evaluator.getScanResultCandidate()); } /** * Case #45 Ensure the ExternalScoreEvaluator correctly handles NULL score inputs. * * In this test we simulate following scenario: * The ExternalScoreEvaluator is asked to evaluate both types of candidates with NULL scores. * * expected result: No crashes. The best candidate type is returned as NONE. */ @Test public void externalScoreEvaluator_nullScores() { WifiQualifiedNetworkSelector.ExternalScoreEvaluator evaluator = new WifiQualifiedNetworkSelector.ExternalScoreEvaluator(mLocalLog, true); evaluator.evalUntrustedCandidate(null, new ScanResult()); assertEquals(WifiQualifiedNetworkSelector.ExternalScoreEvaluator .BestCandidateType.NONE, evaluator.getBestCandidateType()); evaluator.evalSavedCandidate(null, new WifiConfiguration(), new ScanResult()); assertEquals(WifiQualifiedNetworkSelector.ExternalScoreEvaluator .BestCandidateType.NONE, evaluator.getBestCandidateType()); } /** * Case #46 Choose 2.4GHz BSSID with stronger RSSI value over * 5GHz BSSID with weaker RSSI value * * In this test. we simulate following scenario: * Two APs are found in scan results * BSSID1 is @ 5GHz with RSSI -82 * BSSID2 is @ 2Ghz with RSSI -72 * These two BSSIDs get exactly the same QNS score * * expect BSSID2 to be chosen as it has stronger RSSI value */ @Test public void chooseStrongerRssiOver5GHz() { String[] ssids = {"\"test1\"", "\"test1\""}; String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; int[] frequencies = {5220, 2437}; String[] caps = {"[ESS]", "[ESS]"}; int[] levels = {-82, -72}; int[] security = {SECURITY_NONE, SECURITY_NONE}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #47 Choose the currently connected BSSID after a firmware initiated roaming. * * In this test. we simulate following scenario: * Two APs are found in scan results * BSSID1 is @ 2.4GHz with RSSI -78 * BSSID2 is @ 2.4Ghz with RSSI -77 * BSSID2 is chosen because of stronger RSSI. Then firmware initiates * a roaming to BSSID1. QNS now selects BSSID1 because of the bonus for currently * connected network even if BSSID 2 has slightly stronger signal strengh. * * expect BSSID2 to be chosen after firmware roaming */ @Test public void chooseCurrentlyConnectedBssid() { String[] ssids = {"\"test1\"", "\"test1\""}; String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; int[] frequencies = {2437, 2437}; String[] caps = {"[ESS]", "[ESS]"}; int[] levels = {-78, -77}; int[] security = {SECURITY_NONE, SECURITY_NONE}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); scanResultLinkConfiguration(savedConfigs, scanDetails); // Choose BSSID2 as it has stronger RSSI ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); verifySelectedResult(chosenScanResult, candidate); when(mWifiInfo.getBSSID()).thenReturn(bssids[1]); when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true); // Choose BSSID2 as it has stronger RSSI and it is the currently connected BSSID chosenScanResult = scanDetails.get(1).getScanResult(); candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(true, false, scanDetails, false, true, false, false); verifySelectedResult(chosenScanResult, candidate); // Pretend firmware roamed the device to BSSID1 when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); // Choose BSSID1 as it is the currently connected BSSID even if BSSID2 has slightly // higher RSSI value. chosenScanResult = scanDetails.get(0).getScanResult(); candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(true, false, scanDetails, false, true, false, false); verifySelectedResult(chosenScanResult, candidate); } /** * Case #48 no new QNS if current network doesn't show up in the * scan results. * * In this test. we simulate following scenario: * WifiStateMachine is under connected state and 2.4GHz test1 is connected. * The second scan results contains test2 which is 5GHz but no test1. Skip * QNS to avoid aggressive network switching. * * expected return null */ @Test public void noNewQNSCurrentNetworkNotInScanResults() { //Prepare saved network configurations. String[] ssidsConfig = DEFAULT_SSIDS; int[] security = {SECURITY_PSK, SECURITY_PSK}; WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssidsConfig, security); prepareConfigStore(savedConfigs); final List savedNetwork = Arrays.asList(savedConfigs); when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork); //Prepare the first scan results. String[] ssids = {DEFAULT_SSIDS[0]}; String[] bssids = {DEFAULT_BSSIDS[0]}; int[] frequencies = {2437}; String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; int[] levels = {-78}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); scanResultLinkConfiguration(savedConfigs, scanDetails); //Connect to test1. mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); when(mWifiInfo.getNetworkId()).thenReturn(1); when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); when(mWifiInfo.is24GHz()).thenReturn(true); mWifiQualifiedNetworkSelector.setWifiNetworkScoreCache(null); when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true); when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000); //Prepare the second scan results which doesn't contain test1. ssids[0] = DEFAULT_SSIDS[1]; bssids[0] = DEFAULT_BSSIDS[1]; frequencies[0] = 5180; caps[0] = "[WPA2-EAP-CCMP][ESS]"; levels[0] = WifiQualifiedNetworkSelector.QUALIFIED_RSSI_5G_BAND; scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); scanResultLinkConfiguration(savedConfigs, scanDetails); //Skip the second network selection since current connected network is //missing from the scan results. WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, true, false, false); assertEquals("Expect no network selection", null, candidate); } boolean compareCarrierConfigs(WifiConfiguration candidate, WifiConfiguration carrierConfig) { if (!candidate.SSID.equals(carrierConfig.SSID)) { return false; } if (!candidate.ephemeral || carrierConfig.ephemeral) { return false; } if (!candidate.isCarrierNetwork || carrierConfig.isCarrierNetwork) { return false; } if (candidate.enterpriseConfig.getEapMethod() != carrierConfig.enterpriseConfig.getEapMethod()) { return false; } return true; } /** * Case #49 Between two 2G Carrier networks, choose the one with stronger RSSI value * if other conditions are the same and the RSSI values are not staturated. */ @Test public void chooseStrongerRssi2GCarrierNetwork() { String[] ssids = {"TEST1", "TEST2"}; String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; int[] frequencies = {2470, 2437}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; int[] levels = {-65,-55}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(any(ScanDetail.class), any(Boolean.class))).thenReturn(null); when(mWifiConfigManager.saveNetworkAndSetCandidate(any(WifiConfiguration.class), any(ScanResult.class))).then(AdditionalAnswers.returnsFirstArg()); when(mWifiConfigManager.getScanResultCandidate(any(WifiConfiguration.class))) .thenReturn(chosenScanResult); when(mWifiConfigManager.getIsCarrierNetworkEnabledByUser()).thenReturn(true); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); assertTrue(compareCarrierConfigs(candidate, mCarrierConfiguredNetworks.get(1))); } /** * Case #50 Choose 5G over 2G. */ @Test public void choose5GNetworkOver2GNetwork() { String[] ssids = {"TEST1", "TEST2"}; String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; int[] frequencies = {2437, 5240}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; int[] levels = {-65,-55}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(any(ScanDetail.class), any(Boolean.class))).thenReturn(null); when(mWifiConfigManager.saveNetworkAndSetCandidate(any(WifiConfiguration.class), any(ScanResult.class))).then(AdditionalAnswers.returnsFirstArg()); when(mWifiConfigManager.getScanResultCandidate(any(WifiConfiguration.class))) .thenReturn(chosenScanResult); when(mWifiConfigManager.getIsCarrierNetworkEnabledByUser()).thenReturn(true); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); assertTrue(compareCarrierConfigs(candidate, mCarrierConfiguredNetworks.get(1))); } /** * Case #51 Stay on same BSSID & SSID. */ @Test public void chooseSameNetwork() { String[] ssids = {"TEST1", "TEST2"}; String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; int[] frequencies = {2470, 2437}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; int[] levels = {-65,-55}; int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); prepareConfigStore(savedConfigs); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(any(ScanDetail.class), any(Boolean.class))).thenReturn(null); when(mWifiConfigManager.saveNetworkAndSetCandidate(any(WifiConfiguration.class), any(ScanResult.class))).then(AdditionalAnswers.returnsFirstArg()); when(mWifiConfigManager.getScanResultCandidate(any(WifiConfiguration.class))) .thenReturn(chosenScanResult); when(mWifiInfo.getNetworkId()).thenReturn(0); when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); when(mWifiConfigManager.getIsCarrierNetworkEnabledByUser()).thenReturn(true); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, true, false, false); assertTrue(compareCarrierConfigs(candidate, mCarrierConfiguredNetworks.get(0))); } /** * Case #52 Test condition where no Carrier networks are defined. */ @Test public void testNoCarrierNetworks() { String[] ssids = {"TEST1", "TEST2"}; String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; int[] frequencies = {5200, 5240}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; // test2 has slightly stronger RSSI value than test1 int[] levels = {-65,-53}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); List nullCarrierConfiguredNetworks = new ArrayList(); mWifiQualifiedNetworkSelector.setCarrierConfiguredNetworks(nullCarrierConfiguredNetworks); when(mWifiConfigManager.getIsCarrierNetworkEnabledByUser()).thenReturn(true); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, true, scanDetails, false, false, true, false); assertEquals("Expect no network selection", null, candidate); } /** * Case #53 Test condition where no Carrier networks are defined. */ @Test public void testParseCarrierInfoSuccess() { String[] wifiArray = new String[3]; wifiArray[0] = "V2lmaSBFeHRyYQ==|2|4"; wifiArray[1] = "R29vZ2xlLUE=|2|4"; wifiArray[2] = "R29vZ2xlLUd1ZXN0|2|4"; List configList = mWifiQualifiedNetworkSelector.parseCarrierSuppliedWifiInfo(wifiArray); assertEquals("Expect right number of etnries", configList.size(), 3); assertEquals("Expect right network", configList.get(0).SSID, "\"Wifi Extra\""); assertEquals("Expect right network", configList.get(1).SSID, "\"Google-A\""); assertEquals("Expect right network", configList.get(2).SSID, "\"Google-Guest\""); assertTrue("Expect right key", configList.get(0).allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP)); assertEquals("Expect right EAP method", configList.get(0).enterpriseConfig.getEapMethod(), 4); } /** * Case #54 Test condition where string has non-numerics. */ @Test public void testParseCarrierInfoBadEntries1() { String[] wifiArray = new String[3]; wifiArray[0] = "V2lmaSBFeHRyYQ==|2|4"; wifiArray[1] = "R29vZ2xlLUE=|2|A"; //Invalid entry. Non-numeric. wifiArray[2] = "R29vZ2xlLUd1ZXN0|2|4"; List configList = mWifiQualifiedNetworkSelector.parseCarrierSuppliedWifiInfo(wifiArray); assertEquals("Expect right number of etnries", configList.size(), 2); assertEquals("Expect right network", configList.get(0).SSID, "\"Wifi Extra\""); assertEquals("Expect right network", configList.get(1).SSID, "\"Google-Guest\""); } /** * Case #55 Test condition where the config does not have the right number of entries. */ @Test public void testParseCarrierInfoBadEntries2() { String[] wifiArray = new String[3]; wifiArray[0] = "V2lmaSBFeHRyYQ==|2"; //Invalid number of entries wifiArray[1] = "R29vZ2xlLUE=|2|4"; wifiArray[2] = "R29vZ2xlLUd1ZXN0|2|4"; List configList = mWifiQualifiedNetworkSelector.parseCarrierSuppliedWifiInfo(wifiArray); assertEquals("Expect right network", configList.get(0).SSID, "\"Google-A\""); assertEquals("Expect right network", configList.get(1).SSID, "\"Google-Guest\""); } /** * Case #56 Test invalid base-64. */ @Test public void testParseCarrierInfoBadBase64() { String[] wifiArray = new String[3]; wifiArray[0] = "V2lmaSBFeHRyYQ==|2|4"; wifiArray[1] = "xyz==|2|4"; //Invalid base64 wifiArray[2] = "R29vZ2xlLUd1ZXN0|2|4"; List configList = mWifiQualifiedNetworkSelector.parseCarrierSuppliedWifiInfo(wifiArray); assertEquals("Expect right network", configList.get(0).SSID, "\"Wifi Extra\""); assertEquals("Expect right network", configList.get(1).SSID, "\"Google-Guest\""); } /** * Case #56 Test invalid eap-method */ @Test public void testParseCarrierInfoBadEapMethod() { String[] wifiArray = new String[3]; wifiArray[0] = "V2lmaSBFeHRyYQ==|2|4"; wifiArray[1] = "R29vZ2xlLUE=|2|4"; wifiArray[2] = "R29vZ2xlLUd1ZXN0|2|11"; //Invalid eap-method List configList = mWifiQualifiedNetworkSelector.parseCarrierSuppliedWifiInfo(wifiArray); assertEquals("Expect right network", configList.get(0).SSID, "\"Wifi Extra\""); assertEquals("Expect right network", configList.get(1).SSID, "\"Google-A\""); } /** * Case #56 Test invalid key */ @Test public void testParseCarrierInfoBadKey() { String[] wifiArray = new String[3]; wifiArray[0] = "V2lmaSBFeHRyYQ==|2|4"; wifiArray[1] = "R29vZ2xlLUE=|9|4"; //Invalid key wifiArray[2] = "R29vZ2xlLUd1ZXN0|2|4"; List configList = mWifiQualifiedNetworkSelector.parseCarrierSuppliedWifiInfo(wifiArray); assertEquals("Expect right network", configList.get(0).SSID, "\"Wifi Extra\""); assertEquals("Expect right network", configList.get(2).SSID, "\"Google-Guest\""); } /** * Case #57 Test condition where no Carrier networks are defined. */ @Test public void testCarrierNotEnabledByUser() { String[] ssids = {"TEST1", "TEST2"}; String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; int[] frequencies = {2437, 5240}; String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; int[] levels = {-65,-55}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(any(ScanDetail.class), any(Boolean.class))).thenReturn(null); when(mWifiConfigManager.saveNetworkAndSetCandidate(any(WifiConfiguration.class), any(ScanResult.class))).then(AdditionalAnswers.returnsFirstArg()); when(mWifiConfigManager.getScanResultCandidate(any(WifiConfiguration.class))) .thenReturn(chosenScanResult); when(mWifiConfigManager.getIsCarrierNetworkEnabledByUser()).thenReturn(false); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); assertEquals("Expect no network selection", null, candidate); } }