WifiNetworkSelectorTest.java revision 42f602b9ace875b5bf25640fc4f8c708bb8a9c0e
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.NetworkScoreManager; 28import android.net.wifi.ScanResult; 29import android.net.wifi.WifiConfiguration; 30import android.net.wifi.WifiInfo; 31import android.os.SystemClock; 32import android.test.suitebuilder.annotation.SmallTest; 33import android.util.Pair; 34 35import com.android.internal.R; 36import com.android.server.wifi.WifiNetworkSelectorTestUtil.ScanDetailsAndWifiConfigs; 37 38import org.junit.After; 39import org.junit.Before; 40import org.junit.Test; 41 42import java.util.List; 43 44/** 45 * Unit tests for {@link com.android.server.wifi.WifiNetworkSelector}. 46 */ 47@SmallTest 48public class WifiNetworkSelectorTest { 49 50 /** Sets up test. */ 51 @Before 52 public void setUp() throws Exception { 53 mResource = getResource(); 54 mContext = getContext(); 55 mWifiConfigManager = getWifiConfigManager(); 56 mWifiInfo = getWifiInfo(); 57 58 mWifiNetworkSelector = new WifiNetworkSelector(mContext, mWifiConfigManager, 59 mWifiInfo, mClock); 60 mWifiNetworkSelector.registerNetworkEvaluator(mDummyEvaluator, 1); 61 when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()); 62 63 mThresholdMinimumRssi2G = mResource.getInteger( 64 R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz); 65 mThresholdMinimumRssi5G = mResource.getInteger( 66 R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz); 67 mThresholdQualifiedRssi2G = mResource.getInteger( 68 R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz); 69 mThresholdQualifiedRssi5G = mResource.getInteger( 70 R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz); 71 } 72 73 /** Cleans up test. */ 74 @After 75 public void cleanup() { 76 validateMockitoUsage(); 77 } 78 79 /** 80 * All this dummy network evaluator does is to pick the very first network 81 * in the scan results. 82 */ 83 public class DummyNetworkEvaluator implements WifiNetworkSelector.NetworkEvaluator { 84 private static final String NAME = "DummyNetworkEvaluator"; 85 private WifiConfigManager mConfigManager; 86 87 /** 88 * Get the evaluator name. 89 */ 90 public String getName() { 91 return NAME; 92 } 93 94 /** 95 * Update thee evaluator. 96 */ 97 public void update(List<ScanDetail> scanDetails) { 98 } 99 100 /** 101 * Always return the first network in the scan results for connection. 102 */ 103 public WifiConfiguration evaluateNetworks(List<ScanDetail> scanDetails, 104 WifiConfiguration currentNetwork, String currentBssid, boolean connected, 105 boolean untrustedNetworkAllowed, 106 List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks) { 107 ScanDetail scanDetail = scanDetails.get(0); 108 mWifiConfigManager.setNetworkCandidateScanResult(0, scanDetail.getScanResult(), 100); 109 110 return mWifiConfigManager.getSavedNetworkForScanDetailAndCache(scanDetail); 111 } 112 } 113 114 private WifiNetworkSelector mWifiNetworkSelector = null; 115 private DummyNetworkEvaluator mDummyEvaluator = new DummyNetworkEvaluator(); 116 private WifiConfigManager mWifiConfigManager = null; 117 private Context mContext; 118 private Resources mResource; 119 private WifiInfo mWifiInfo; 120 private Clock mClock = mock(Clock.class); 121 private int mThresholdMinimumRssi2G; 122 private int mThresholdMinimumRssi5G; 123 private int mThresholdQualifiedRssi2G; 124 private int mThresholdQualifiedRssi5G; 125 126 Context getContext() { 127 Context context = mock(Context.class); 128 Resources resource = mock(Resources.class); 129 130 when(context.getResources()).thenReturn(mResource); 131 return context; 132 } 133 134 Resources getResource() { 135 Resources resource = mock(Resources.class); 136 137 when(resource.getBoolean( 138 R.bool.config_wifi_framework_enable_associated_network_selection)).thenReturn(true); 139 when(resource.getInteger( 140 R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz)) 141 .thenReturn(-70); 142 when(resource.getInteger( 143 R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz)) 144 .thenReturn(-73); 145 when(resource.getInteger( 146 R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz)) 147 .thenReturn(-82); 148 when(resource.getInteger( 149 R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz)) 150 .thenReturn(-85); 151 return resource; 152 } 153 154 NetworkScoreManager getNetworkScoreManager() { 155 NetworkScoreManager networkScoreManager = mock(NetworkScoreManager.class); 156 157 return networkScoreManager; 158 } 159 160 WifiInfo getWifiInfo() { 161 WifiInfo wifiInfo = mock(WifiInfo.class); 162 163 // simulate a disconnected state 164 when(wifiInfo.is24GHz()).thenReturn(true); 165 when(wifiInfo.is5GHz()).thenReturn(false); 166 when(wifiInfo.getRssi()).thenReturn(-70); 167 when(wifiInfo.getNetworkId()).thenReturn(WifiConfiguration.INVALID_NETWORK_ID); 168 when(wifiInfo.getBSSID()).thenReturn(null); 169 return wifiInfo; 170 } 171 172 WifiConfigManager getWifiConfigManager() { 173 WifiConfigManager wifiConfigManager = mock(WifiConfigManager.class); 174 when(wifiConfigManager.getLastSelectedNetwork()) 175 .thenReturn(WifiConfiguration.INVALID_NETWORK_ID); 176 return wifiConfigManager; 177 } 178 179 180 /** 181 * No network selection if scan result is empty. 182 * 183 * WifiStateMachine is in disconnected state. 184 * scanDetails is empty. 185 * 186 * Expected behavior: no network recommended by Network Selector 187 */ 188 @Test 189 public void emptyScanResults() { 190 String[] ssids = new String[0]; 191 String[] bssids = new String[0]; 192 int[] freqs = new int[0]; 193 String[] caps = new String[0]; 194 int[] levels = new int[0]; 195 int[] securities = new int[0]; 196 197 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 198 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 199 freqs, caps, levels, securities, mWifiConfigManager, mClock); 200 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 201 WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 202 false, true, false); 203 assertEquals("Expect null configuration", null, candidate); 204 } 205 206 207 /** 208 * No network selection if the RSSI values in scan result are too low. 209 * 210 * WifiStateMachine is in disconnected state. 211 * scanDetails contains a 2.4GHz and a 5GHz network, but both with RSSI lower than 212 * the threshold 213 * 214 * Expected behavior: no network recommended by Network Selector 215 */ 216 @Test 217 public void verifyMinimumRssiThreshold() { 218 String[] ssids = {"\"test1\"", "\"test2\""}; 219 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; 220 int[] freqs = {2437, 5180}; 221 String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; 222 int[] levels = {mThresholdMinimumRssi2G - 1, mThresholdMinimumRssi5G - 1}; 223 int[] securities = {SECURITY_PSK, SECURITY_PSK}; 224 225 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 226 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 227 freqs, caps, levels, securities, mWifiConfigManager, mClock); 228 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 229 WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 230 false, true, false); 231 assertEquals("Expect null configuration", null, candidate); 232 } 233 234 /** 235 * No network selection if WiFi is connected and it is too short from last 236 * network selection. 237 * 238 * WifiStateMachine is in connected state. 239 * scanDetails contains two valid networks. 240 * Perform a network seletion right after the first one. 241 * 242 * Expected behavior: no network recommended by Network Selector 243 */ 244 @Test 245 public void verifyMinimumTimeGapWhenConnected() { 246 String[] ssids = {"\"test1\"", "\"test2\""}; 247 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; 248 int[] freqs = {2437, 5180}; 249 String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; 250 int[] levels = {mThresholdMinimumRssi2G + 1, mThresholdMinimumRssi5G + 1}; 251 int[] securities = {SECURITY_PSK, SECURITY_PSK}; 252 253 // Make a network selection. 254 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 255 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 256 freqs, caps, levels, securities, mWifiConfigManager, mClock); 257 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 258 WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 259 false, true, false); 260 261 when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() 262 + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS - 2000); 263 264 // Do another network selection with WSM in CONNECTED state. 265 candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 266 true, false, false); 267 268 assertEquals("Expect null configuration", null, candidate); 269 } 270 271 /** 272 * Perform network selection if WiFi is disconnected even if it is too short from last 273 * network selection. 274 * 275 * WifiStateMachine is in disconnected state. 276 * scanDetails contains two valid networks. 277 * Perform a network seletion right after the first one. 278 * 279 * Expected behavior: the first network is recommended by Network Selector 280 */ 281 @Test 282 public void verifyNoMinimumTimeGapWhenDisconnected() { 283 String[] ssids = {"\"test1\"", "\"test2\""}; 284 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; 285 int[] freqs = {2437, 5180}; 286 String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; 287 int[] levels = {mThresholdMinimumRssi2G + 1, mThresholdMinimumRssi5G + 1}; 288 int[] securities = {SECURITY_PSK, SECURITY_PSK}; 289 290 // Make a network selection. 291 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 292 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 293 freqs, caps, levels, securities, mWifiConfigManager, mClock); 294 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 295 WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); 296 WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 297 false, true, false); 298 299 when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() 300 + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS - 2000); 301 302 // Do another network selection with WSM in DISCONNECTED state. 303 candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 304 false, true, false); 305 306 ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); 307 WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate); 308 WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, 309 chosenScanResult, candidate); 310 } 311 312 /** 313 * No network selection if the currently connected on is already sufficient. 314 * 315 * WifiStateMachine is connected to a qualified (5G, secure, good RSSI) network. 316 * scanDetails contains a valid network. 317 * Perform a network seletion after the first one. 318 * 319 * Expected behavior: no network recommended by Network Selector 320 */ 321 @Test 322 public void noNetworkSelectionWhenCurrentOneIsSufficient() { 323 String[] ssids = {"\"test1\""}; 324 String[] bssids = {"6c:f3:7f:ae:8c:f3"}; 325 int[] freqs = {5180}; 326 String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; 327 int[] levels = {mThresholdQualifiedRssi5G + 8}; 328 int[] securities = {SECURITY_PSK}; 329 330 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 331 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 332 freqs, caps, levels, securities, mWifiConfigManager, mClock); 333 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 334 335 // connect to test1 336 mWifiNetworkSelector.selectNetwork(scanDetails, false, true, false); 337 when(mWifiInfo.getNetworkId()).thenReturn(0); 338 when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); 339 when(mWifiInfo.is24GHz()).thenReturn(false); 340 341 when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() 342 + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000); 343 344 levels[0] = mThresholdQualifiedRssi5G + 20; 345 scanDetailsAndConfigs = 346 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 347 freqs, caps, levels, securities, mWifiConfigManager, mClock); 348 scanDetails = scanDetailsAndConfigs.getScanDetails(); 349 350 WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 351 true, false, false); 352 assertEquals("Expect null configuration", null, candidate); 353 } 354 355 356 /** 357 * New network selection is performed if the currently connected network 358 * band is 2G. 359 * 360 * WifiStateMachine is connected to a 2G network. 361 * scanDetails contains a valid networks. 362 * Perform a network seletion after the first one. 363 * 364 * Expected behavior: the first network is recommended by Network Selector 365 */ 366 @Test 367 public void band2GNetworkIsNotSufficient() { 368 String[] ssids = {"\"test1\""}; 369 String[] bssids = {"6c:f3:7f:ae:8c:f3"}; 370 int[] freqs = {2470}; 371 String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; 372 int[] levels = {mThresholdQualifiedRssi2G + 8}; 373 int[] securities = {SECURITY_PSK}; 374 375 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 376 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 377 freqs, caps, levels, securities, mWifiConfigManager, mClock); 378 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 379 WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); 380 381 // connect to test1 382 mWifiNetworkSelector.selectNetwork(scanDetails, false, true, false); 383 when(mWifiInfo.getNetworkId()).thenReturn(0); 384 when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); 385 when(mWifiInfo.is24GHz()).thenReturn(true); 386 387 when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() 388 + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000); 389 390 // Do another network selection. 391 WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 392 true, false, false); 393 394 ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); 395 WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate); 396 WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, 397 chosenScanResult, candidate); 398 } 399 400 401 /** 402 * New network selection is performed if the currently connected network 403 * is a open one. 404 * 405 * WifiStateMachine is connected to a open network. 406 * scanDetails contains a valid networks. 407 * Perform a network seletion after the first one. 408 * 409 * Expected behavior: the first network is recommended by Network Selector 410 */ 411 @Test 412 public void openNetworkIsNotSufficient() { 413 String[] ssids = {"\"test1\""}; 414 String[] bssids = {"6c:f3:7f:ae:8c:f3"}; 415 int[] freqs = {5180}; 416 String[] caps = {"[ESS]"}; 417 int[] levels = {mThresholdQualifiedRssi5G + 8}; 418 int[] securities = {SECURITY_NONE}; 419 420 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 421 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 422 freqs, caps, levels, securities, mWifiConfigManager, mClock); 423 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 424 WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); 425 426 // connect to test1 427 mWifiNetworkSelector.selectNetwork(scanDetails, false, true, false); 428 when(mWifiInfo.getNetworkId()).thenReturn(0); 429 when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); 430 when(mWifiInfo.is24GHz()).thenReturn(false); 431 when(mWifiInfo.is5GHz()).thenReturn(true); 432 433 when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() 434 + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000); 435 436 // Do another network selection. 437 WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 438 true, false, false); 439 440 ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); 441 WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate); 442 WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, 443 chosenScanResult, candidate); 444 } 445 446 /** 447 * New network selection is performed if the currently connected network 448 * has low RSSI value. 449 * 450 * WifiStateMachine is connected to a low RSSI 5GHz network. 451 * scanDetails contains a valid networks. 452 * Perform a network seletion after the first one. 453 * 454 * Expected behavior: the first network is recommended by Network Selector 455 */ 456 @Test 457 public void lowRssi5GNetworkIsNotSufficient() { 458 String[] ssids = {"\"test1\""}; 459 String[] bssids = {"6c:f3:7f:ae:8c:f3"}; 460 int[] freqs = {5180}; 461 String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; 462 int[] levels = {mThresholdQualifiedRssi5G - 2}; 463 int[] securities = {SECURITY_PSK}; 464 465 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 466 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 467 freqs, caps, levels, securities, mWifiConfigManager, mClock); 468 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 469 WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); 470 471 // connect to test1 472 mWifiNetworkSelector.selectNetwork(scanDetails, false, true, false); 473 when(mWifiInfo.getNetworkId()).thenReturn(0); 474 when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); 475 when(mWifiInfo.is24GHz()).thenReturn(false); 476 when(mWifiInfo.is5GHz()).thenReturn(true); 477 when(mWifiInfo.getRssi()).thenReturn(levels[0]); 478 479 when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() 480 + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000); 481 482 // Do another network selection. 483 WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, 484 true, false, false); 485 486 ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); 487 WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate); 488 WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, 489 chosenScanResult, candidate); 490 } 491} 492