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