SavedNetworkEvaluatorTest.java revision 17c2a7b30e5680b11fc0073ce322ee7bc14ef2c5
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.ContentResolver; 26import android.content.Context; 27import android.content.res.Resources; 28import android.database.ContentObserver; 29import android.net.Uri; 30import android.net.wifi.ScanResult; 31import android.net.wifi.WifiConfiguration; 32import android.os.Looper; 33import android.os.SystemClock; 34import android.provider.Settings; 35import android.test.suitebuilder.annotation.SmallTest; 36import android.util.LocalLog; 37 38import com.android.internal.R; 39import com.android.server.wifi.WifiNetworkSelectorTestUtil.ScanDetailsAndWifiConfigs; 40 41import org.junit.After; 42import org.junit.Before; 43import org.junit.Test; 44import org.mockito.ArgumentCaptor; 45import org.mockito.Mock; 46import org.mockito.MockitoAnnotations; 47 48import java.util.List; 49 50/** 51 * Unit tests for {@link com.android.server.wifi.SavedNetworkEvaluator}. 52 */ 53@SmallTest 54public class SavedNetworkEvaluatorTest { 55 56 /** Sets up test. */ 57 @Before 58 public void setUp() throws Exception { 59 MockitoAnnotations.initMocks(this); 60 setupContext(); 61 setupResource(); 62 setupWifiConfigManager(); 63 mLocalLog = new LocalLog(512); 64 65 when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()); 66 when(mFrameworkFacade.getIntegerSetting(mContext, 67 Settings.Global.CURATE_SAVED_OPEN_NETWORKS, 0)).thenReturn(0); 68 when(mFrameworkFacade.getIntegerSetting(mContext, 69 Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0)).thenReturn(0); 70 71 mThresholdMinimumRssi2G = mResource.getInteger( 72 R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz); 73 mThresholdMinimumRssi5G = mResource.getInteger( 74 R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz); 75 mThresholdQualifiedRssi2G = mResource.getInteger( 76 R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz); 77 mThresholdQualifiedRssi5G = mResource.getInteger( 78 R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz); 79 mThresholdSaturatedRssi2G = mResource.getInteger( 80 R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz); 81 mThresholdSaturatedRssi5G = mResource.getInteger( 82 R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz); 83 84 ArgumentCaptor<ContentObserver> observerCaptor = 85 ArgumentCaptor.forClass(ContentObserver.class); 86 87 mSavedNetworkEvaluator = new SavedNetworkEvaluator(mContext, mWifiConfigManager, 88 mClock, mLocalLog, Looper.getMainLooper(), mFrameworkFacade); 89 verify(mFrameworkFacade, times(2)).registerContentObserver(eq(mContext), any(Uri.class), 90 eq(false), observerCaptor.capture()); 91 // SavedNetworkEvaluator uses a single ContentObserver for two registrations, we only need 92 // to get this object once. 93 mContentObserver = observerCaptor.getValue(); 94 } 95 96 /** Cleans up test. */ 97 @After 98 public void cleanup() { 99 validateMockitoUsage(); 100 } 101 102 private SavedNetworkEvaluator mSavedNetworkEvaluator; 103 @Mock private WifiConfigManager mWifiConfigManager; 104 @Mock private Context mContext; 105 @Mock private ContentResolver mContentResolver; 106 @Mock private FrameworkFacade mFrameworkFacade; 107 @Mock private Resources mResource; 108 @Mock private Clock mClock; 109 private LocalLog mLocalLog; 110 private int mThresholdMinimumRssi2G; 111 private int mThresholdMinimumRssi5G; 112 private int mThresholdQualifiedRssi2G; 113 private int mThresholdQualifiedRssi5G; 114 private int mThresholdSaturatedRssi2G; 115 private int mThresholdSaturatedRssi5G; 116 private ContentObserver mContentObserver; 117 private static final String TAG = "Saved Network Evaluator Unit Test"; 118 119 private void setupContext() { 120 when(mContext.getResources()).thenReturn(mResource); 121 when(mContext.getContentResolver()).thenReturn(mContentResolver); 122 } 123 124 private void setupResource() { 125 when(mResource.getInteger( 126 R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz)) 127 .thenReturn(-70); 128 when(mResource.getInteger( 129 R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz)) 130 .thenReturn(-73); 131 when(mResource.getInteger( 132 R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz)) 133 .thenReturn(-70); 134 when(mResource.getInteger( 135 R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz)) 136 .thenReturn(-73); 137 when(mResource.getInteger( 138 R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz)) 139 .thenReturn(-82); 140 when(mResource.getInteger( 141 R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz)) 142 .thenReturn(-85); 143 when(mResource.getInteger( 144 R.integer.config_wifi_framework_RSSI_SCORE_SLOPE)) 145 .thenReturn(4); 146 when(mResource.getInteger( 147 R.integer.config_wifi_framework_RSSI_SCORE_OFFSET)) 148 .thenReturn(85); 149 when(mResource.getInteger( 150 R.integer.config_wifi_framework_SAME_BSSID_AWARD)) 151 .thenReturn(24); 152 when(mResource.getInteger( 153 R.integer.config_wifi_framework_SECURITY_AWARD)) 154 .thenReturn(80); 155 when(mResource.getInteger( 156 R.integer.config_wifi_framework_5GHz_preference_boost_factor)) 157 .thenReturn(16); 158 when(mResource.getInteger( 159 R.integer.config_wifi_framework_current_network_boost)) 160 .thenReturn(16); 161 } 162 163 private void setupWifiConfigManager() { 164 when(mWifiConfigManager.getLastSelectedNetwork()) 165 .thenReturn(WifiConfiguration.INVALID_NETWORK_ID); 166 } 167 168 /** 169 * Do not evaluate networks that {@link WifiConfiguration#useExternalScores}. 170 */ 171 @Test 172 public void ignoreNetworksIfUseExternalScores() { 173 String[] ssids = {"\"test1\"", "\"test2\""}; 174 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; 175 int[] freqs = {2470, 2437}; 176 String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; 177 int[] levels = {mThresholdQualifiedRssi2G + 8, mThresholdQualifiedRssi2G + 10}; 178 int[] securities = {SECURITY_PSK, SECURITY_PSK}; 179 180 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 181 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 182 freqs, caps, levels, securities, mWifiConfigManager, mClock); 183 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 184 WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); 185 for (WifiConfiguration wifiConfiguration : savedConfigs) { 186 wifiConfiguration.useExternalScores = true; 187 } 188 189 WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails, 190 null, null, true, false, null); 191 192 assertNull(candidate); 193 } 194 195 /** 196 * Do not evaluate open networks when {@link Settings.Global.CURATE_SAVED_OPEN_NETWORKS} and 197 * {@link Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED} are enabled. 198 */ 199 @Test 200 public void ignoreOpensNetworksIfCurateSavedNetworksEnabled() { 201 String[] ssids = {"\"test1\"", "\"test2\""}; 202 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; 203 int[] freqs = {5200, 5240}; 204 String[] caps = {"[ESS]", "[ESS]"}; 205 int[] levels = {mThresholdQualifiedRssi5G, mThresholdQualifiedRssi5G}; 206 int[] securities = {SECURITY_NONE, SECURITY_NONE}; 207 208 when(mFrameworkFacade.getIntegerSetting(mContext, 209 Settings.Global.CURATE_SAVED_OPEN_NETWORKS, 0)).thenReturn(1); 210 when(mFrameworkFacade.getIntegerSetting(mContext, 211 Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0)).thenReturn(1); 212 mContentObserver.onChange(false); 213 214 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 215 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 216 freqs, caps, levels, securities, mWifiConfigManager, mClock); 217 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 218 219 WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails, 220 null, null, true, false, null); 221 222 assertNull(candidate); 223 } 224 225 /** 226 * Set the candidate {@link ScanResult} for all {@link WifiConfiguration}s even if they have 227 * useExternalScores set or are open networks with 228 * {@link Settings.Global.CURATE_SAVED_OPEN_NETWORKS} and 229 * {@link Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED} enabled. 230 */ 231 @Test 232 public void setCandidateScanResultsForAllSavedNetworks() { 233 String[] ssids = {"\"test1\"", "\"test2\""}; 234 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; 235 int[] freqs = {5200, 5240}; 236 String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]"}; 237 int[] levels = {mThresholdQualifiedRssi5G, mThresholdQualifiedRssi5G}; 238 int[] securities = {SECURITY_PSK, SECURITY_NONE}; 239 240 when(mFrameworkFacade.getIntegerSetting(mContext, 241 Settings.Global.CURATE_SAVED_OPEN_NETWORKS, 0)).thenReturn(1); 242 when(mFrameworkFacade.getIntegerSetting(mContext, 243 Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0)).thenReturn(1); 244 mContentObserver.onChange(false); 245 246 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 247 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 248 freqs, caps, levels, securities, mWifiConfigManager, mClock); 249 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 250 WifiConfiguration useExternalScoresConfig = scanDetailsAndConfigs.getWifiConfigs()[0]; 251 useExternalScoresConfig.useExternalScores = true; 252 WifiConfiguration openNetworkConfig = scanDetailsAndConfigs.getWifiConfigs()[1]; 253 254 WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails, 255 null, null, true, false, null); 256 257 assertNull(candidate); 258 259 verify(mWifiConfigManager).setNetworkCandidateScanResult( 260 eq(useExternalScoresConfig.networkId), 261 eq(scanDetails.get(0).getScanResult()), 262 anyInt()); 263 verify(mWifiConfigManager).setNetworkCandidateScanResult( 264 eq(openNetworkConfig.networkId), 265 eq(scanDetails.get(1).getScanResult()), 266 anyInt()); 267 } 268 269 /** 270 * Between two 2G networks, choose the one with stronger RSSI value if other conditions 271 * are the same and the RSSI values are not satuarted. 272 */ 273 @Test 274 public void chooseStrongerRssi2GNetwork() { 275 String[] ssids = {"\"test1\"", "\"test2\""}; 276 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; 277 int[] freqs = {2470, 2437}; 278 String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; 279 int[] levels = {mThresholdQualifiedRssi2G + 8, mThresholdQualifiedRssi2G + 10}; 280 int[] securities = {SECURITY_PSK, SECURITY_PSK}; 281 282 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 283 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 284 freqs, caps, levels, securities, mWifiConfigManager, mClock); 285 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 286 WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); 287 288 WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails, 289 null, null, true, false, null); 290 291 ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); 292 WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[1], candidate); 293 WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, 294 chosenScanResult, candidate); 295 } 296 297 /** 298 * Between two 5G networks, choose the one with stronger RSSI value if other conditions 299 * are the same and the RSSI values are not saturated. 300 * {@link Settings.Global.CURATE_SAVED_OPEN_NETWORKS} and 301 * {@link Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED} will no affect on the outcome 302 * because both networks are secure. 303 */ 304 @Test 305 public void chooseStrongerRssi5GNetwork() { 306 String[] ssids = {"\"test1\"", "\"test2\""}; 307 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; 308 int[] freqs = {5200, 5240}; 309 String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; 310 int[] levels = {mThresholdQualifiedRssi5G + 8, mThresholdQualifiedRssi5G + 10}; 311 int[] securities = {SECURITY_PSK, SECURITY_PSK}; 312 313 when(mFrameworkFacade.getIntegerSetting(mContext, 314 Settings.Global.CURATE_SAVED_OPEN_NETWORKS, 0)).thenReturn(1); 315 when(mFrameworkFacade.getIntegerSetting(mContext, 316 Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0)).thenReturn(1); 317 mContentObserver.onChange(false); 318 319 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 320 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 321 freqs, caps, levels, securities, mWifiConfigManager, mClock); 322 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 323 WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); 324 325 WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails, 326 null, null, true, false, null); 327 328 ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); 329 WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[1], candidate); 330 WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, 331 chosenScanResult, candidate); 332 } 333 334 /** 335 * Choose secure network over open network if other conditions are the same. 336 */ 337 @Test 338 public void chooseSecureNetworkOverOpenNetwork() { 339 String[] ssids = {"\"test1\"", "\"test2\""}; 340 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; 341 int[] freqs = {5200, 5240}; 342 String[] caps = {"[ESS]", "[WPA2-EAP-CCMP][ESS]"}; 343 int[] levels = {mThresholdQualifiedRssi5G, mThresholdQualifiedRssi5G}; 344 int[] securities = {SECURITY_NONE, SECURITY_PSK}; 345 346 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 347 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 348 freqs, caps, levels, securities, mWifiConfigManager, mClock); 349 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 350 WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); 351 352 WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails, 353 null, null, true, false, null); 354 355 ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); 356 WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[1], candidate); 357 WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, 358 chosenScanResult, candidate); 359 } 360 361 /** 362 * Choose 5G network over 2G network if other conditions are the same. 363 */ 364 @Test 365 public void choose5GNetworkOver2GNetwork() { 366 String[] ssids = {"\"test1\"", "\"test2\""}; 367 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; 368 int[] freqs = {2437, 5240}; 369 String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; 370 int[] levels = {mThresholdQualifiedRssi2G, mThresholdQualifiedRssi5G}; 371 int[] securities = {SECURITY_PSK, SECURITY_PSK}; 372 373 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 374 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 375 freqs, caps, levels, securities, mWifiConfigManager, mClock); 376 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 377 WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); 378 379 WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails, 380 null, null, true, false, null); 381 382 ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); 383 WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[1], candidate); 384 WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, 385 chosenScanResult, candidate); 386 } 387 388 /** 389 * Verify that we stick to the currently connected network if the other one is 390 * just slightly better scored. 391 */ 392 @Test 393 public void stickToCurrentNetwork() { 394 String[] ssids = {"\"test1\"", "\"test2\""}; 395 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; 396 int[] freqs = {5200, 5240}; 397 String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; 398 // test2 has slightly stronger RSSI value than test1 399 int[] levels = {mThresholdMinimumRssi5G + 2, mThresholdMinimumRssi5G + 4}; 400 int[] securities = {SECURITY_PSK, SECURITY_PSK}; 401 402 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 403 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 404 freqs, caps, levels, securities, mWifiConfigManager, mClock); 405 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 406 WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); 407 408 // Simuluate we are connected to SSID test1 already. 409 WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails, 410 savedConfigs[0], null, true, false, null); 411 412 // Even though test2 has higher RSSI value, test1 is chosen because of the 413 // currently connected network bonus. 414 ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); 415 WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate); 416 WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, 417 chosenScanResult, candidate); 418 } 419 420 /** 421 * Verify that we stick to the currently connected BSSID if the other one is 422 * just slightly better scored. 423 */ 424 @Test 425 public void stickToCurrentBSSID() { 426 // Same SSID 427 String[] ssids = {"\"test1\"", "\"test1\""}; 428 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; 429 int[] freqs = {5200, 5240}; 430 String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; 431 // test2 has slightly stronger RSSI value than test1 432 int[] levels = {mThresholdMinimumRssi5G + 2, mThresholdMinimumRssi5G + 6}; 433 int[] securities = {SECURITY_PSK, SECURITY_PSK}; 434 435 ScanDetailsAndWifiConfigs scanDetailsAndConfigs = 436 WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, 437 freqs, caps, levels, securities, mWifiConfigManager, mClock); 438 List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); 439 WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); 440 441 // Simuluate we are connected to BSSID "6c:f3:7f:ae:8c:f3" already 442 WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails, 443 null, bssids[0], true, false, null); 444 445 // Even though test2 has higher RSSI value, test1 is chosen because of the 446 // currently connected BSSID bonus. 447 ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); 448 WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate); 449 } 450} 451