1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wifi; 18 19import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_NONE; 20import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_PSK; 21 22import static org.junit.Assert.*; 23import static org.mockito.Mockito.*; 24 25import android.content.Context; 26import android.content.res.Resources; 27import android.net.wifi.ScanResult; 28import android.net.wifi.WifiConfiguration; 29import android.net.wifi.WifiConfiguration.NetworkSelectionStatus; 30import android.net.wifi.WifiInfo; 31import android.os.SystemClock; 32import android.test.suitebuilder.annotation.SmallTest; 33import android.util.LocalLog; 34import android.util.Pair; 35 36import com.android.internal.R; 37import com.android.server.wifi.WifiNetworkSelectorTestUtil.ScanDetailsAndWifiConfigs; 38 39import org.junit.After; 40import org.junit.Before; 41import org.junit.Test; 42import org.mockito.Mock; 43import org.mockito.MockitoAnnotations; 44 45import java.util.HashSet; 46import java.util.List; 47 48/** 49 * Unit tests for {@link com.android.server.wifi.WifiNetworkSelector}. 50 */ 51@SmallTest 52public class WifiNetworkSelectorTest { 53 54 /** Sets up test. */ 55 @Before 56 public void setUp() throws Exception { 57 MockitoAnnotations.initMocks(this); 58 setupContext(); 59 setupResources(); 60 setupWifiConfigManager(); 61 setupWifiInfo(); 62 mLocalLog = new LocalLog(512); 63 64 mWifiNetworkSelector = new WifiNetworkSelector(mContext, mWifiConfigManager, mClock, 65 mLocalLog); 66 mWifiNetworkSelector.registerNetworkEvaluator(mDummyEvaluator, 1); 67 when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()); 68 69 mThresholdMinimumRssi2G = mResource.getInteger( 70 R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz); 71 mThresholdMinimumRssi5G = mResource.getInteger( 72 R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz); 73 mThresholdQualifiedRssi2G = mResource.getInteger( 74 R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz); 75 mThresholdQualifiedRssi5G = mResource.getInteger( 76 R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz); 77 } 78 79 /** Cleans up test. */ 80 @After 81 public void cleanup() { 82 validateMockitoUsage(); 83 } 84 85 /** 86 * All this dummy network evaluator does is to pick the very first network 87 * in the scan results. 88 */ 89 public class DummyNetworkEvaluator implements WifiNetworkSelector.NetworkEvaluator { 90 private static final String NAME = "DummyNetworkEvaluator"; 91 92 @Override 93 public String getName() { 94 return NAME; 95 } 96 97 @Override 98 public void update(List<ScanDetail> scanDetails) {} 99 100 /** 101 * Always return the first network in the scan results for connection. 102 */ 103 @Override 104 public WifiConfiguration evaluateNetworks(List<ScanDetail> scanDetails, 105 WifiConfiguration currentNetwork, String currentBssid, boolean connected, 106 boolean untrustedNetworkAllowed, 107 List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks) { 108 ScanDetail scanDetail = scanDetails.get(0); 109 mWifiConfigManager.setNetworkCandidateScanResult(0, scanDetail.getScanResult(), 100); 110 111 return mWifiConfigManager.getSavedNetworkForScanDetailAndCache(scanDetail); 112 } 113 } 114 115 private WifiNetworkSelector mWifiNetworkSelector = null; 116 private DummyNetworkEvaluator mDummyEvaluator = new DummyNetworkEvaluator(); 117 @Mock private WifiConfigManager mWifiConfigManager; 118 @Mock private Context mContext; 119 @Mock private Resources mResource; 120 @Mock private WifiInfo mWifiInfo; 121 @Mock private Clock mClock; 122 private LocalLog mLocalLog; 123 private int mThresholdMinimumRssi2G; 124 private int mThresholdMinimumRssi5G; 125 private int mThresholdQualifiedRssi2G; 126 private int mThresholdQualifiedRssi5G; 127 128 private void setupContext() { 129 when(mContext.getResources()).thenReturn(mResource); 130 } 131 132 private void setupResources() { 133 when(mResource.getBoolean( 134 R.bool.config_wifi_framework_enable_associated_network_selection)).thenReturn(true); 135 when(mResource.getInteger( 136 R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz)) 137 .thenReturn(-70); 138 when(mResource.getInteger( 139 R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz)) 140 .thenReturn(-73); 141 when(mResource.getInteger( 142 R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz)) 143 .thenReturn(-82); 144 when(mResource.getInteger( 145 R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz)) 146 .thenReturn(-85); 147 } 148 149 private void setupWifiInfo() { 150 // simulate a disconnected state 151 when(mWifiInfo.is24GHz()).thenReturn(true); 152 when(mWifiInfo.is5GHz()).thenReturn(false); 153 when(mWifiInfo.getRssi()).thenReturn(-70); 154 when(mWifiInfo.getNetworkId()).thenReturn(WifiConfiguration.INVALID_NETWORK_ID); 155 when(mWifiInfo.getBSSID()).thenReturn(null); 156 } 157 158 private void setupWifiConfigManager() { 159 when(mWifiConfigManager.getLastSelectedNetwork()) 160 .thenReturn(WifiConfiguration.INVALID_NETWORK_ID); 161 } 162 163 /** 164 * No network selection if scan result is empty. 165 * 166 * WifiStateMachine is in disconnected state. 167 * scanDetails is empty. 168 * 169 * Expected behavior: no network recommended by Network Selector 170 */ 171 @Test 172 public void emptyScanResults() { 173 String[] ssids = new String[0]; 174 String[] bssids = new String[0]; 175 int[] freqs = new int[0]; 176 String[] caps = new String[0]; 177 int[] levels = new int[0]; 178 int[] securities = new int[0]; 179 180 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 181 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 182 freqs, caps, levels, securities, mWifiConfigManager, mClock); 183 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 184 HashSet<String> blacklist = new HashSet<String>(); 185 WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 186 blacklist, mWifiInfo, false, true, false); 187 assertEquals("Expect null configuration", null, candidate); 188 } 189 190 191 /** 192 * No network selection if the RSSI values in scan result are too low. 193 * 194 * WifiStateMachine is in disconnected state. 195 * scanDetails contains a 2.4GHz and a 5GHz network, but both with RSSI lower than 196 * the threshold 197 * 198 * Expected behavior: no network recommended by Network Selector 199 */ 200 @Test 201 public void verifyMinimumRssiThreshold() { 202 String[] ssids = {"\"test1\"", "\"test2\""}; 203 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; 204 int[] freqs = {2437, 5180}; 205 String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; 206 int[] levels = {mThresholdMinimumRssi2G - 1, mThresholdMinimumRssi5G - 1}; 207 int[] securities = {SECURITY_PSK, SECURITY_PSK}; 208 209 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 210 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 211 freqs, caps, levels, securities, mWifiConfigManager, mClock); 212 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 213 HashSet<String> blacklist = new HashSet<String>(); 214 WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 215 blacklist, mWifiInfo, false, true, false); 216 assertEquals("Expect null configuration", null, candidate); 217 } 218 219 /** 220 * No network selection if WiFi is connected and it is too short from last 221 * network selection. 222 * 223 * WifiStateMachine is in connected state. 224 * scanDetails contains two valid networks. 225 * Perform a network seletion right after the first one. 226 * 227 * Expected behavior: no network recommended by Network Selector 228 */ 229 @Test 230 public void verifyMinimumTimeGapWhenConnected() { 231 String[] ssids = {"\"test1\"", "\"test2\""}; 232 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; 233 int[] freqs = {2437, 5180}; 234 String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; 235 int[] levels = {mThresholdMinimumRssi2G + 1, mThresholdMinimumRssi5G + 1}; 236 int[] securities = {SECURITY_PSK, SECURITY_PSK}; 237 238 // Make a network selection. 239 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 240 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 241 freqs, caps, levels, securities, mWifiConfigManager, mClock); 242 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 243 HashSet<String> blacklist = new HashSet<String>(); 244 WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 245 blacklist, mWifiInfo, false, true, false); 246 247 when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() 248 + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS - 2000); 249 250 // Do another network selection with WSM in CONNECTED state. 251 candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 252 blacklist, mWifiInfo, true, false, false); 253 254 assertEquals("Expect null configuration", null, candidate); 255 } 256 257 /** 258 * Perform network selection if WiFi is disconnected even if it is too short from last 259 * network selection. 260 * 261 * WifiStateMachine is in disconnected state. 262 * scanDetails contains two valid networks. 263 * Perform a network seletion right after the first one. 264 * 265 * Expected behavior: the first network is recommended by Network Selector 266 */ 267 @Test 268 public void verifyNoMinimumTimeGapWhenDisconnected() { 269 String[] ssids = {"\"test1\"", "\"test2\""}; 270 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; 271 int[] freqs = {2437, 5180}; 272 String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; 273 int[] levels = {mThresholdMinimumRssi2G + 1, mThresholdMinimumRssi5G + 1}; 274 int[] securities = {SECURITY_PSK, SECURITY_PSK}; 275 276 // Make a network selection. 277 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 278 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 279 freqs, caps, levels, securities, mWifiConfigManager, mClock); 280 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 281 WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); 282 HashSet<String> blacklist = new HashSet<String>(); 283 WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 284 blacklist, mWifiInfo, false, true, false); 285 WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate); 286 287 when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() 288 + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS - 2000); 289 290 // Do another network selection with WSM in DISCONNECTED state. 291 candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 292 blacklist, mWifiInfo, false, true, false); 293 294 ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); 295 WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate); 296 WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, 297 chosenScanResult, candidate); 298 } 299 300 /** 301 * No network selection if the currently connected on is already sufficient. 302 * 303 * WifiStateMachine is connected to a qualified (5G, secure, good RSSI) network. 304 * scanDetails contains a valid network. 305 * Perform a network seletion after the first one. 306 * 307 * Expected behavior: no network recommended by Network Selector 308 */ 309 @Test 310 public void noNetworkSelectionWhenCurrentOneIsSufficient() { 311 String[] ssids = {"\"test1\""}; 312 String[] bssids = {"6c:f3:7f:ae:8c:f3"}; 313 int[] freqs = {5180}; 314 String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; 315 int[] levels = {mThresholdQualifiedRssi5G + 8}; 316 int[] securities = {SECURITY_PSK}; 317 318 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 319 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 320 freqs, caps, levels, securities, mWifiConfigManager, mClock); 321 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 322 HashSet<String> blacklist = new HashSet<String>(); 323 324 // connect to test1 325 mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false); 326 when(mWifiInfo.getNetworkId()).thenReturn(0); 327 when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); 328 when(mWifiInfo.is24GHz()).thenReturn(false); 329 330 when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() 331 + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000); 332 333 levels[0] = mThresholdQualifiedRssi5G + 20; 334 scanDetailsAndConfigs = 335 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 336 freqs, caps, levels, securities, mWifiConfigManager, mClock); 337 scanDetails = scanDetailsAndConfigs.getScanDetails(); 338 339 WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 340 blacklist, mWifiInfo, true, false, false); 341 assertEquals("Expect null configuration", null, candidate); 342 } 343 344 /** 345 * New network selection is performed if the currently connected network 346 * band is 2G. 347 * 348 * WifiStateMachine is connected to a 2G network. 349 * scanDetails contains a valid networks. 350 * Perform a network seletion after the first one. 351 * 352 * Expected behavior: the first network is recommended by Network Selector 353 */ 354 @Test 355 public void band2GNetworkIsNotSufficient() { 356 String[] ssids = {"\"test1\""}; 357 String[] bssids = {"6c:f3:7f:ae:8c:f3"}; 358 int[] freqs = {2470}; 359 String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; 360 int[] levels = {mThresholdQualifiedRssi2G + 8}; 361 int[] securities = {SECURITY_PSK}; 362 363 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 364 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 365 freqs, caps, levels, securities, mWifiConfigManager, mClock); 366 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 367 HashSet<String> blacklist = new HashSet<String>(); 368 WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); 369 370 // connect to test1 371 mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false); 372 when(mWifiInfo.getNetworkId()).thenReturn(0); 373 when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); 374 when(mWifiInfo.is24GHz()).thenReturn(true); 375 376 when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() 377 + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000); 378 379 // Do another network selection. 380 WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 381 blacklist, mWifiInfo, true, false, false); 382 383 ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); 384 WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate); 385 WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, 386 chosenScanResult, candidate); 387 } 388 389 390 /** 391 * New network selection is performed if the currently connected network 392 * is a open one. 393 * 394 * WifiStateMachine is connected to a open network. 395 * scanDetails contains a valid networks. 396 * Perform a network seletion after the first one. 397 * 398 * Expected behavior: the first network is recommended by Network Selector 399 */ 400 @Test 401 public void openNetworkIsNotSufficient() { 402 String[] ssids = {"\"test1\""}; 403 String[] bssids = {"6c:f3:7f:ae:8c:f3"}; 404 int[] freqs = {5180}; 405 String[] caps = {"[ESS]"}; 406 int[] levels = {mThresholdQualifiedRssi5G + 8}; 407 int[] securities = {SECURITY_NONE}; 408 409 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 410 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 411 freqs, caps, levels, securities, mWifiConfigManager, mClock); 412 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 413 HashSet<String> blacklist = new HashSet<String>(); 414 WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); 415 416 // connect to test1 417 mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false); 418 when(mWifiInfo.getNetworkId()).thenReturn(0); 419 when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); 420 when(mWifiInfo.is24GHz()).thenReturn(false); 421 when(mWifiInfo.is5GHz()).thenReturn(true); 422 423 when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() 424 + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000); 425 426 // Do another network selection. 427 WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 428 blacklist, mWifiInfo, true, false, false); 429 430 ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); 431 WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate); 432 WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, 433 chosenScanResult, candidate); 434 } 435 436 /** 437 * New network selection is performed if the currently connected network 438 * has low RSSI value. 439 * 440 * WifiStateMachine is connected to a low RSSI 5GHz network. 441 * scanDetails contains a valid networks. 442 * Perform a network seletion after the first one. 443 * 444 * Expected behavior: the first network is recommended by Network Selector 445 */ 446 @Test 447 public void lowRssi5GNetworkIsNotSufficient() { 448 String[] ssids = {"\"test1\""}; 449 String[] bssids = {"6c:f3:7f:ae:8c:f3"}; 450 int[] freqs = {5180}; 451 String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; 452 int[] levels = {mThresholdQualifiedRssi5G - 2}; 453 int[] securities = {SECURITY_PSK}; 454 455 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 456 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 457 freqs, caps, levels, securities, mWifiConfigManager, mClock); 458 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 459 HashSet<String> blacklist = new HashSet<String>(); 460 WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); 461 462 // connect to test1 463 mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false); 464 when(mWifiInfo.getNetworkId()).thenReturn(0); 465 when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); 466 when(mWifiInfo.is24GHz()).thenReturn(false); 467 when(mWifiInfo.is5GHz()).thenReturn(true); 468 when(mWifiInfo.getRssi()).thenReturn(levels[0]); 469 470 when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() 471 + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000); 472 473 // Do another network selection. 474 WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 475 blacklist, mWifiInfo, true, false, false); 476 477 ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); 478 WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate); 479 WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, 480 chosenScanResult, candidate); 481 } 482 483 /** 484 * Blacklisted BSSID is filtered out for network selection. 485 * 486 * WifiStateMachine is disconnected. 487 * scanDetails contains a network which is blacklisted. 488 * 489 * Expected behavior: no network recommended by Network Selector 490 */ 491 @Test 492 public void filterOutBlacklistedBssid() { 493 String[] ssids = {"\"test1\""}; 494 String[] bssids = {"6c:f3:7f:ae:8c:f3"}; 495 int[] freqs = {5180}; 496 String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; 497 int[] levels = {mThresholdQualifiedRssi5G + 8}; 498 int[] securities = {SECURITY_PSK}; 499 500 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 501 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 502 freqs, caps, levels, securities, mWifiConfigManager, mClock); 503 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 504 HashSet<String> blacklist = new HashSet<String>(); 505 blacklist.add(bssids[0]); 506 507 WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 508 blacklist, mWifiInfo, false, true, false); 509 assertEquals("Expect null configuration", null, candidate); 510 } 511 512 /** 513 * Wifi network selector doesn't recommend any network if the currently connected one 514 * doesn't show up in the scan results. 515 * 516 * WifiStateMachine is under connected state and 2.4GHz test1 is connected. 517 * The second scan results contains only test2 which now has a stronger RSSI than test1. 518 * Test1 is not in the second scan results. 519 * 520 * Expected behavior: no network recommended by Network Selector 521 */ 522 @Test 523 public void noSelectionWhenCurrentNetworkNotInScanResults() { 524 String[] ssids = {"\"test1\"", "\"test2\""}; 525 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; 526 int[] freqs = {2437, 2457}; 527 String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; 528 int[] levels = {mThresholdMinimumRssi2G + 20, mThresholdMinimumRssi2G + 1}; 529 int[] securities = {SECURITY_PSK, SECURITY_PSK}; 530 531 // Make a network selection to connect to test1. 532 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 533 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 534 freqs, caps, levels, securities, mWifiConfigManager, mClock); 535 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 536 HashSet<String> blacklist = new HashSet<String>(); 537 WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 538 blacklist, mWifiInfo, false, true, false); 539 540 when(mWifiInfo.getNetworkId()).thenReturn(0); 541 when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); 542 when(mWifiInfo.is24GHz()).thenReturn(true); 543 when(mWifiInfo.is5GHz()).thenReturn(false); 544 when(mWifiInfo.getRssi()).thenReturn(levels[0]); 545 when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() 546 + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000); 547 548 // Prepare the second scan results which have no test1. 549 String[] ssidsNew = {"\"test2\""}; 550 String[] bssidsNew = {"6c:f3:7f:ae:8c:f4"}; 551 int[] freqsNew = {2457}; 552 String[] capsNew = {"[WPA2-EAP-CCMP][ESS]"}; 553 int[] levelsNew = {mThresholdMinimumRssi2G + 40}; 554 scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(ssidsNew, bssidsNew, 555 freqsNew, capsNew, levelsNew, mClock); 556 candidate = mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, 557 true, false, false); 558 559 // The second network selection is skipped since current connected network is 560 // missing from the scan results. 561 assertEquals("Expect null configuration", null, candidate); 562 } 563 564 /** 565 * Ensures that settings the user connect choice updates the 566 * NetworkSelectionStatus#mConnectChoice for all other WifiConfigurations in range in the last 567 * round of network selection. 568 * 569 * Expected behavior: WifiConfiguration.NetworkSelectionStatus#mConnectChoice is set to 570 * test1's configkey for test2. test3's WifiConfiguration is unchanged. 571 */ 572 @Test 573 public void setUserConnectChoice() { 574 String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\""}; 575 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "6c:f3:7f:ae:8c:f5"}; 576 int[] freqs = {2437, 5180, 5181}; 577 String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; 578 int[] levels = {mThresholdMinimumRssi2G + 1, mThresholdMinimumRssi5G + 1, 579 mThresholdMinimumRssi5G + 1}; 580 int[] securities = {SECURITY_PSK, SECURITY_PSK, SECURITY_PSK}; 581 582 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 583 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 584 freqs, caps, levels, securities, mWifiConfigManager, mClock); 585 586 WifiConfiguration selectedWifiConfig = scanDetailsAndConfigs.getWifiConfigs()[0]; 587 selectedWifiConfig.getNetworkSelectionStatus() 588 .setCandidate(scanDetailsAndConfigs.getScanDetails().get(0).getScanResult()); 589 selectedWifiConfig.getNetworkSelectionStatus().setNetworkSelectionStatus( 590 NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED); 591 selectedWifiConfig.getNetworkSelectionStatus().setConnectChoice("bogusKey"); 592 593 WifiConfiguration configInLastNetworkSelection = scanDetailsAndConfigs.getWifiConfigs()[1]; 594 configInLastNetworkSelection.getNetworkSelectionStatus() 595 .setSeenInLastQualifiedNetworkSelection(true); 596 597 WifiConfiguration configNotInLastNetworkSelection = 598 scanDetailsAndConfigs.getWifiConfigs()[2]; 599 600 assertTrue(mWifiNetworkSelector.setUserConnectChoice(selectedWifiConfig.networkId)); 601 602 verify(mWifiConfigManager).updateNetworkSelectionStatus(selectedWifiConfig.networkId, 603 NetworkSelectionStatus.NETWORK_SELECTION_ENABLE); 604 verify(mWifiConfigManager).clearNetworkConnectChoice(selectedWifiConfig.networkId); 605 verify(mWifiConfigManager).setNetworkConnectChoice(configInLastNetworkSelection.networkId, 606 selectedWifiConfig.configKey(), mClock.getWallClockMillis()); 607 verify(mWifiConfigManager, never()).setNetworkConnectChoice( 608 configNotInLastNetworkSelection.networkId, selectedWifiConfig.configKey(), 609 mClock.getWallClockMillis()); 610 } 611 612 /** 613 * If two qualified networks, test1 and test2, are in range when the user selects test2 over 614 * test1, WifiNetworkSelector will override the NetworkSelector's choice to connect to test1 615 * with test2. 616 * 617 * Expected behavior: test2 is the recommended network 618 */ 619 @Test 620 public void userConnectChoiceOverridesNetworkEvaluators() { 621 String[] ssids = {"\"test1\"", "\"test2\""}; 622 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; 623 int[] freqs = {2437, 5180}; 624 String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; 625 int[] levels = {mThresholdMinimumRssi2G + 1, mThresholdMinimumRssi5G + 1}; 626 int[] securities = {SECURITY_PSK, SECURITY_PSK}; 627 628 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 629 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 630 freqs, caps, levels, securities, mWifiConfigManager, mClock); 631 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 632 HashSet<String> blacklist = new HashSet<String>(); 633 634 // DummyEvaluator always selects the first network in the list. 635 WifiConfiguration networkSelectorChoice = scanDetailsAndConfigs.getWifiConfigs()[0]; 636 networkSelectorChoice.getNetworkSelectionStatus() 637 .setSeenInLastQualifiedNetworkSelection(true); 638 639 WifiConfiguration userChoice = scanDetailsAndConfigs.getWifiConfigs()[1]; 640 userChoice.getNetworkSelectionStatus() 641 .setCandidate(scanDetailsAndConfigs.getScanDetails().get(1).getScanResult()); 642 643 // With no user choice set, networkSelectorChoice should be chosen. 644 WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 645 blacklist, mWifiInfo, false, true, false); 646 647 WifiConfigurationTestUtil.assertConfigurationEqual(networkSelectorChoice, candidate); 648 649 when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() 650 + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000); 651 652 assertTrue(mWifiNetworkSelector.setUserConnectChoice(userChoice.networkId)); 653 654 // After user connect choice is set, userChoice should override networkSelectorChoice. 655 candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 656 blacklist, mWifiInfo, false, true, false); 657 658 WifiConfigurationTestUtil.assertConfigurationEqual(userChoice, candidate); 659 } 660} 661