WifiConnectivityManagerTest.java revision ee0ab818341d44614ffe56ae73ecc08b974c2cbb
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.generateWifiConfig; 20 21import static org.junit.Assert.assertEquals; 22import static org.mockito.Mockito.*; 23 24import android.content.Context; 25import android.content.res.Resources; 26import android.net.wifi.ScanResult; 27import android.net.wifi.ScanResult.InformationElement; 28import android.net.wifi.SupplicantState; 29import android.net.wifi.WifiConfiguration; 30import android.net.wifi.WifiInfo; 31import android.net.wifi.WifiScanner; 32import android.net.wifi.WifiScanner.PnoScanListener; 33import android.net.wifi.WifiScanner.PnoSettings; 34import android.net.wifi.WifiScanner.ScanListener; 35import android.net.wifi.WifiScanner.ScanSettings; 36import android.net.wifi.WifiSsid; 37import android.os.SystemClock; 38import android.os.WorkSource; 39import android.test.suitebuilder.annotation.SmallTest; 40 41import com.android.internal.R; 42import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments; 43 44import org.junit.After; 45import org.junit.Before; 46import org.junit.Test; 47 48import java.nio.charset.StandardCharsets; 49import java.util.ArrayList; 50import java.util.concurrent.atomic.AtomicInteger; 51 52/** 53 * Unit tests for {@link com.android.server.wifi.WifiConnectivityManager}. 54 */ 55@SmallTest 56public class WifiConnectivityManagerTest { 57 58 /** 59 * Called before each test 60 */ 61 @Before 62 public void setUp() throws Exception { 63 mWifiInjector = mockWifiInjector(); 64 mResource = mockResource(); 65 mAlarmManager = new MockAlarmManager(); 66 mContext = mockContext(); 67 mWifiStateMachine = mockWifiStateMachine(); 68 mWifiConfigManager = mockWifiConfigManager(); 69 mWifiInfo = mockWifiInfo(); 70 mWifiScanner = mockWifiScanner(); 71 mWifiQNS = mockWifiQualifiedNetworkSelector(); 72 mWifiConnectivityManager = new WifiConnectivityManager(mContext, mWifiStateMachine, 73 mWifiScanner, mWifiConfigManager, mWifiInfo, mWifiQNS, mWifiInjector, 74 mLooper.getLooper()); 75 mWifiConnectivityManager.setWifiEnabled(true); 76 when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime()); 77 } 78 79 /** 80 * Called after each test 81 */ 82 @After 83 public void cleanup() { 84 validateMockitoUsage(); 85 } 86 87 private Resources mResource; 88 private Context mContext; 89 private MockAlarmManager mAlarmManager; 90 private MockLooper mLooper = new MockLooper(); 91 private WifiConnectivityManager mWifiConnectivityManager; 92 private WifiQualifiedNetworkSelector mWifiQNS; 93 private WifiStateMachine mWifiStateMachine; 94 private WifiScanner mWifiScanner; 95 private WifiConfigManager mWifiConfigManager; 96 private WifiInfo mWifiInfo; 97 private Clock mClock = mock(Clock.class); 98 private WifiLastResortWatchdog mWifiLastResortWatchdog; 99 private WifiMetrics mWifiMetrics; 100 private WifiInjector mWifiInjector; 101 102 private static final int CANDIDATE_NETWORK_ID = 0; 103 private static final String CANDIDATE_SSID = "\"AnSsid\""; 104 private static final String CANDIDATE_BSSID = "6c:f3:7f:ae:8c:f3"; 105 private static final String TAG = "WifiConnectivityManager Unit Test"; 106 private static final long CURRENT_SYSTEM_TIME_MS = 1000; 107 108 Resources mockResource() { 109 Resources resource = mock(Resources.class); 110 111 when(resource.getInteger(R.integer.config_wifi_framework_SECURITY_AWARD)).thenReturn(80); 112 when(resource.getInteger(R.integer.config_wifi_framework_SAME_BSSID_AWARD)).thenReturn(24); 113 114 return resource; 115 } 116 117 Context mockContext() { 118 Context context = mock(Context.class); 119 120 when(context.getResources()).thenReturn(mResource); 121 when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn( 122 mAlarmManager.getAlarmManager()); 123 124 return context; 125 } 126 127 WifiScanner mockWifiScanner() { 128 WifiScanner scanner = mock(WifiScanner.class); 129 130 // dummy scan results. QNS PeriodicScanListener bulids scanDetails from 131 // the fullScanResult and doesn't really use results 132 final WifiScanner.ScanData[] scanDatas = new WifiScanner.ScanData[1]; 133 134 // do a synchronous answer for the ScanListener callbacks 135 doAnswer(new AnswerWithArguments() { 136 public void answer(ScanSettings settings, ScanListener listener, 137 WorkSource workSource) throws Exception { 138 listener.onResults(scanDatas); 139 }}).when(scanner).startBackgroundScan(anyObject(), anyObject(), anyObject()); 140 141 doAnswer(new AnswerWithArguments() { 142 public void answer(ScanSettings settings, ScanListener listener, 143 WorkSource workSource) throws Exception { 144 listener.onResults(scanDatas); 145 }}).when(scanner).startScan(anyObject(), anyObject(), anyObject()); 146 147 // This unfortunately needs to be a somewhat valid scan result, otherwise 148 // |ScanDetailUtil.toScanDetail| raises exceptions. 149 final ScanResult[] scanResults = new ScanResult[1]; 150 scanResults[0] = new ScanResult(WifiSsid.createFromAsciiEncoded(CANDIDATE_SSID), 151 CANDIDATE_SSID, CANDIDATE_BSSID, 1245, 0, "some caps", 152 -78, 2450, 1025, 22, 33, 20, 0, 0, true); 153 scanResults[0].informationElements = new InformationElement[1]; 154 scanResults[0].informationElements[0] = new InformationElement(); 155 scanResults[0].informationElements[0].id = InformationElement.EID_SSID; 156 scanResults[0].informationElements[0].bytes = 157 CANDIDATE_SSID.getBytes(StandardCharsets.UTF_8); 158 159 doAnswer(new AnswerWithArguments() { 160 public void answer(ScanSettings settings, PnoSettings pnoSettings, 161 PnoScanListener listener) throws Exception { 162 listener.onPnoNetworkFound(scanResults); 163 }}).when(scanner).startDisconnectedPnoScan(anyObject(), anyObject(), anyObject()); 164 165 doAnswer(new AnswerWithArguments() { 166 public void answer(ScanSettings settings, PnoSettings pnoSettings, 167 PnoScanListener listener) throws Exception { 168 listener.onPnoNetworkFound(scanResults); 169 }}).when(scanner).startConnectedPnoScan(anyObject(), anyObject(), anyObject()); 170 171 return scanner; 172 } 173 174 WifiStateMachine mockWifiStateMachine() { 175 WifiStateMachine stateMachine = mock(WifiStateMachine.class); 176 177 when(stateMachine.getFrequencyBand()).thenReturn(1); 178 when(stateMachine.isLinkDebouncing()).thenReturn(false); 179 when(stateMachine.isConnected()).thenReturn(false); 180 when(stateMachine.isDisconnected()).thenReturn(true); 181 when(stateMachine.isSupplicantTransientState()).thenReturn(false); 182 183 return stateMachine; 184 } 185 186 WifiQualifiedNetworkSelector mockWifiQualifiedNetworkSelector() { 187 WifiQualifiedNetworkSelector qns = mock(WifiQualifiedNetworkSelector.class); 188 189 WifiConfiguration candidate = generateWifiConfig( 190 0, CANDIDATE_NETWORK_ID, CANDIDATE_SSID, false, true, null, null); 191 candidate.BSSID = CANDIDATE_BSSID; 192 ScanResult candidateScanResult = new ScanResult(); 193 candidateScanResult.SSID = CANDIDATE_SSID; 194 candidateScanResult.BSSID = CANDIDATE_BSSID; 195 candidate.getNetworkSelectionStatus().setCandidate(candidateScanResult); 196 197 when(qns.selectQualifiedNetwork(anyBoolean(), anyBoolean(), anyObject(), 198 anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean())).thenReturn(candidate); 199 return qns; 200 } 201 202 WifiInfo mockWifiInfo() { 203 WifiInfo wifiInfo = mock(WifiInfo.class); 204 205 when(wifiInfo.getNetworkId()).thenReturn(WifiConfiguration.INVALID_NETWORK_ID); 206 when(wifiInfo.getBSSID()).thenReturn(null); 207 when(wifiInfo.getSupplicantState()).thenReturn(SupplicantState.DISCONNECTED); 208 209 return wifiInfo; 210 } 211 212 WifiConfigManager mockWifiConfigManager() { 213 WifiConfigManager wifiConfigManager = mock(WifiConfigManager.class); 214 215 when(wifiConfigManager.getWifiConfiguration(anyInt())).thenReturn(null); 216 wifiConfigManager.mThresholdSaturatedRssi24 = new AtomicInteger( 217 WifiQualifiedNetworkSelector.RSSI_SATURATION_2G_BAND); 218 wifiConfigManager.mCurrentNetworkBoost = new AtomicInteger( 219 WifiQualifiedNetworkSelector.SAME_NETWORK_AWARD); 220 221 // Pass dummy pno network list, otherwise Pno scan requests will not be triggered. 222 PnoSettings.PnoNetwork pnoNetwork = new PnoSettings.PnoNetwork(CANDIDATE_SSID); 223 ArrayList<PnoSettings.PnoNetwork> pnoNetworkList = new ArrayList<>(); 224 pnoNetworkList.add(pnoNetwork); 225 when(wifiConfigManager.retrieveDisconnectedPnoNetworkList()).thenReturn(pnoNetworkList); 226 when(wifiConfigManager.retrieveConnectedPnoNetworkList()).thenReturn(pnoNetworkList); 227 228 return wifiConfigManager; 229 } 230 231 WifiInjector mockWifiInjector() { 232 WifiInjector wifiInjector = mock(WifiInjector.class); 233 mWifiLastResortWatchdog = mock(WifiLastResortWatchdog.class); 234 mWifiMetrics = mock(WifiMetrics.class); 235 when(wifiInjector.getWifiLastResortWatchdog()).thenReturn(mWifiLastResortWatchdog); 236 when(wifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics); 237 when(wifiInjector.getClock()).thenReturn(mClock); 238 return wifiInjector; 239 } 240 241 /** 242 * Wifi enters disconnected state while screen is on. 243 * 244 * Expected behavior: WifiConnectivityManager calls 245 * WifiStateMachine.autoConnectToNetwork() with the 246 * expected candidate network ID and BSSID. 247 */ 248 @Test 249 public void enterWifiDisconnectedStateWhenScreenOn() { 250 // Set screen to on 251 mWifiConnectivityManager.handleScreenStateChanged(true); 252 253 // Set WiFi to disconnected state 254 mWifiConnectivityManager.handleConnectionStateChanged( 255 WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 256 257 verify(mWifiStateMachine).autoConnectToNetwork( 258 CANDIDATE_NETWORK_ID, CANDIDATE_BSSID); 259 } 260 261 /** 262 * Wifi enters connected state while screen is on. 263 * 264 * Expected behavior: WifiConnectivityManager calls 265 * WifiStateMachine.autoConnectToNetwork() with the 266 * expected candidate network ID and BSSID. 267 */ 268 @Test 269 public void enterWifiConnectedStateWhenScreenOn() { 270 // Set screen to on 271 mWifiConnectivityManager.handleScreenStateChanged(true); 272 273 // Set WiFi to connected state 274 mWifiConnectivityManager.handleConnectionStateChanged( 275 WifiConnectivityManager.WIFI_STATE_CONNECTED); 276 277 verify(mWifiStateMachine).autoConnectToNetwork( 278 CANDIDATE_NETWORK_ID, CANDIDATE_BSSID); 279 } 280 281 /** 282 * Screen turned on while WiFi in disconnected state. 283 * 284 * Expected behavior: WifiConnectivityManager calls 285 * WifiStateMachine.autoConnectToNetwork() with the 286 * expected candidate network ID and BSSID. 287 */ 288 @Test 289 public void turnScreenOnWhenWifiInDisconnectedState() { 290 // Set WiFi to disconnected state 291 mWifiConnectivityManager.handleConnectionStateChanged( 292 WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 293 294 // Set screen to on 295 mWifiConnectivityManager.handleScreenStateChanged(true); 296 297 verify(mWifiStateMachine, atLeastOnce()).autoConnectToNetwork( 298 CANDIDATE_NETWORK_ID, CANDIDATE_BSSID); 299 } 300 301 /** 302 * Screen turned on while WiFi in connected state. 303 * 304 * Expected behavior: WifiConnectivityManager calls 305 * WifiStateMachine.autoConnectToNetwork() with the 306 * expected candidate network ID and BSSID. 307 */ 308 @Test 309 public void turnScreenOnWhenWifiInConnectedState() { 310 // Set WiFi to connected state 311 mWifiConnectivityManager.handleConnectionStateChanged( 312 WifiConnectivityManager.WIFI_STATE_CONNECTED); 313 314 // Set screen to on 315 mWifiConnectivityManager.handleScreenStateChanged(true); 316 317 verify(mWifiStateMachine, atLeastOnce()).autoConnectToNetwork( 318 CANDIDATE_NETWORK_ID, CANDIDATE_BSSID); 319 } 320 321 /** 322 * Multiple back to back connection attempts within the rate interval should be rate limited. 323 * 324 * Expected behavior: WifiConnectivityManager calls WifiStateMachine.autoConnectToNetwork() 325 * with the expected candidate network ID and BSSID for only the expected number of times within 326 * the given interval. 327 */ 328 @Test 329 public void connectionAttemptRateLimitedWhenScreenOff() { 330 int maxAttemptRate = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_RATE; 331 int timeInterval = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS; 332 int numAttempts = 0; 333 int connectionAttemptIntervals = timeInterval / maxAttemptRate; 334 335 mWifiConnectivityManager.handleScreenStateChanged(false); 336 337 // First attempt the max rate number of connections within the rate interval. 338 long currentTimeStamp = 0; 339 for (int attempt = 0; attempt < maxAttemptRate; attempt++) { 340 currentTimeStamp += connectionAttemptIntervals; 341 when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 342 // Set WiFi to disconnected state to trigger PNO scan 343 mWifiConnectivityManager.handleConnectionStateChanged( 344 WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 345 numAttempts++; 346 } 347 // Now trigger another connection attempt before the rate interval, this should be 348 // skipped because we've crossed rate limit. 349 when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 350 // Set WiFi to disconnected state to trigger PNO scan 351 mWifiConnectivityManager.handleConnectionStateChanged( 352 WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 353 354 // Verify that we attempt to connect upto the rate. 355 verify(mWifiStateMachine, times(numAttempts)).autoConnectToNetwork( 356 CANDIDATE_NETWORK_ID, CANDIDATE_BSSID); 357 } 358 359 /** 360 * Multiple back to back connection attempts outside the rate interval should not be rate 361 * limited. 362 * 363 * Expected behavior: WifiConnectivityManager calls WifiStateMachine.autoConnectToNetwork() 364 * with the expected candidate network ID and BSSID for only the expected number of times within 365 * the given interval. 366 */ 367 @Test 368 public void connectionAttemptNotRateLimitedWhenScreenOff() { 369 int maxAttemptRate = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_RATE; 370 int timeInterval = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS; 371 int numAttempts = 0; 372 int connectionAttemptIntervals = timeInterval / maxAttemptRate; 373 374 mWifiConnectivityManager.handleScreenStateChanged(false); 375 376 // First attempt the max rate number of connections within the rate interval. 377 long currentTimeStamp = 0; 378 for (int attempt = 0; attempt < maxAttemptRate; attempt++) { 379 currentTimeStamp += connectionAttemptIntervals; 380 when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 381 // Set WiFi to disconnected state to trigger PNO scan 382 mWifiConnectivityManager.handleConnectionStateChanged( 383 WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 384 numAttempts++; 385 } 386 // Now trigger another connection attempt after the rate interval, this should not be 387 // skipped because we should've evicted the older attempt. 388 when(mClock.elapsedRealtime()).thenReturn( 389 currentTimeStamp + connectionAttemptIntervals * 2); 390 // Set WiFi to disconnected state to trigger PNO scan 391 mWifiConnectivityManager.handleConnectionStateChanged( 392 WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 393 numAttempts++; 394 395 // Verify that all the connection attempts went through 396 verify(mWifiStateMachine, times(numAttempts)).autoConnectToNetwork( 397 CANDIDATE_NETWORK_ID, CANDIDATE_BSSID); 398 } 399 400 /** 401 * Multiple back to back connection attempts after a user selection should not be rate limited. 402 * 403 * Expected behavior: WifiConnectivityManager calls WifiStateMachine.autoConnectToNetwork() 404 * with the expected candidate network ID and BSSID for only the expected number of times within 405 * the given interval. 406 */ 407 @Test 408 public void connectionAttemptNotRateLimitedWhenScreenOffAfterUserSelection() { 409 int maxAttemptRate = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_RATE; 410 int timeInterval = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS; 411 int numAttempts = 0; 412 int connectionAttemptIntervals = timeInterval / maxAttemptRate; 413 414 mWifiConnectivityManager.handleScreenStateChanged(false); 415 416 // First attempt the max rate number of connections within the rate interval. 417 long currentTimeStamp = 0; 418 for (int attempt = 0; attempt < maxAttemptRate; attempt++) { 419 currentTimeStamp += connectionAttemptIntervals; 420 when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 421 // Set WiFi to disconnected state to trigger PNO scan 422 mWifiConnectivityManager.handleConnectionStateChanged( 423 WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 424 numAttempts++; 425 } 426 427 mWifiConnectivityManager.connectToUserSelectNetwork(CANDIDATE_NETWORK_ID, false); 428 429 for (int attempt = 0; attempt < maxAttemptRate; attempt++) { 430 currentTimeStamp += connectionAttemptIntervals; 431 when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 432 // Set WiFi to disconnected state to trigger PNO scan 433 mWifiConnectivityManager.handleConnectionStateChanged( 434 WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 435 numAttempts++; 436 } 437 438 // Verify that all the connection attempts went through 439 verify(mWifiStateMachine, times(numAttempts)).autoConnectToNetwork( 440 CANDIDATE_NETWORK_ID, CANDIDATE_BSSID); 441 } 442 443 /** 444 * PNO retry for low RSSI networks. 445 * 446 * Expected behavior: WifiConnectivityManager doubles the low RSSI 447 * network retry delay value after QNS skips the PNO scan results 448 * because of their low RSSI values. 449 */ 450 @Test 451 public void PnoRetryForLowRssiNetwork() { 452 when(mWifiQNS.selectQualifiedNetwork(anyBoolean(), anyBoolean(), anyObject(), 453 anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean())).thenReturn(null); 454 455 // Set screen to off 456 mWifiConnectivityManager.handleScreenStateChanged(false); 457 458 // Get the current retry delay value 459 int lowRssiNetworkRetryDelayStartValue = mWifiConnectivityManager 460 .getLowRssiNetworkRetryDelay(); 461 462 // Set WiFi to disconnected state to trigger PNO scan 463 mWifiConnectivityManager.handleConnectionStateChanged( 464 WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 465 466 // Get the retry delay value after QNS didn't select a 467 // network candicate from the PNO scan results. 468 int lowRssiNetworkRetryDelayAfterPnoValue = mWifiConnectivityManager 469 .getLowRssiNetworkRetryDelay(); 470 471 assertEquals(lowRssiNetworkRetryDelayStartValue * 2, 472 lowRssiNetworkRetryDelayAfterPnoValue); 473 } 474 475 /** 476 * Ensure that the watchdog bite increments the "Pno bad" metric. 477 * 478 * Expected behavior: WifiConnectivityManager detects that the PNO scan failed to find 479 * a candidate while watchdog single scan did. 480 */ 481 @Test 482 public void watchdogBitePnoBadIncrementsMetrics() { 483 // Set screen to off 484 mWifiConnectivityManager.handleScreenStateChanged(false); 485 486 // Set WiFi to disconnected state to trigger PNO scan 487 mWifiConnectivityManager.handleConnectionStateChanged( 488 WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 489 490 // Now fire the watchdog alarm and verify the metrics were incremented. 491 mAlarmManager.dispatch(WifiConnectivityManager.WATCHDOG_TIMER_TAG); 492 mLooper.dispatchAll(); 493 494 verify(mWifiMetrics).incrementNumConnectivityWatchdogPnoBad(); 495 verify(mWifiMetrics, never()).incrementNumConnectivityWatchdogPnoGood(); 496 } 497 498 /** 499 * Ensure that the watchdog bite increments the "Pno good" metric. 500 * 501 * Expected behavior: WifiConnectivityManager detects that the PNO scan failed to find 502 * a candidate which was the same with watchdog single scan. 503 */ 504 @Test 505 public void watchdogBitePnoGoodIncrementsMetrics() { 506 // Qns returns no candidate after watchdog single scan. 507 when(mWifiQNS.selectQualifiedNetwork(anyBoolean(), anyBoolean(), anyObject(), 508 anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean())).thenReturn(null); 509 510 // Set screen to off 511 mWifiConnectivityManager.handleScreenStateChanged(false); 512 513 // Set WiFi to disconnected state to trigger PNO scan 514 mWifiConnectivityManager.handleConnectionStateChanged( 515 WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 516 517 // Now fire the watchdog alarm and verify the metrics were incremented. 518 mAlarmManager.dispatch(WifiConnectivityManager.WATCHDOG_TIMER_TAG); 519 mLooper.dispatchAll(); 520 521 verify(mWifiMetrics).incrementNumConnectivityWatchdogPnoGood(); 522 verify(mWifiMetrics, never()).incrementNumConnectivityWatchdogPnoBad(); 523 } 524 525 /** 526 * Verify that scan interval for screen on and wifi disconnected scenario 527 * is in the exponential backoff fashion. 528 * 529 * Expected behavior: WifiConnectivityManager doubles periodic 530 * scan interval. 531 */ 532 @Test 533 public void checkPeriodicScanIntervalWhenDisconnected() { 534 when(mClock.elapsedRealtime()).thenReturn(CURRENT_SYSTEM_TIME_MS); 535 536 // Set screen to ON 537 mWifiConnectivityManager.handleScreenStateChanged(true); 538 539 // Set WiFi to disconnected state to trigger periodic scan 540 mWifiConnectivityManager.handleConnectionStateChanged( 541 WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 542 543 // Get the first periodic scan interval 544 long firstIntervalMs = mAlarmManager 545 .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) 546 - CURRENT_SYSTEM_TIME_MS; 547 assertEquals(firstIntervalMs, WifiConnectivityManager.PERIODIC_SCAN_INTERVAL_MS); 548 549 // Now fire the first periodic scan alarm timer 550 mAlarmManager.dispatch(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG); 551 mLooper.dispatchAll(); 552 553 // Get the second periodic scan interval 554 long secondIntervalMs = mAlarmManager 555 .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) 556 - CURRENT_SYSTEM_TIME_MS; 557 558 // Verify the intervals are exponential back off 559 assertEquals(firstIntervalMs * 2, secondIntervalMs); 560 561 // Make sure we eventually stay at the maximum scan interval. 562 long intervalMs = 0; 563 for (int i = 0; i < 5; i++) { 564 mAlarmManager.dispatch(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG); 565 mLooper.dispatchAll(); 566 intervalMs = mAlarmManager 567 .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) 568 - CURRENT_SYSTEM_TIME_MS; 569 } 570 571 assertEquals(intervalMs, WifiConnectivityManager.MAX_PERIODIC_SCAN_INTERVAL_MS); 572 } 573 574 /** 575 * Verify that scan interval for screen on and wifi connected scenario 576 * is in the exponential backoff fashion. 577 * 578 * Expected behavior: WifiConnectivityManager doubles periodic 579 * scan interval. 580 */ 581 @Test 582 public void checkPeriodicScanIntervalWhenConnected() { 583 when(mClock.elapsedRealtime()).thenReturn(CURRENT_SYSTEM_TIME_MS); 584 585 // Set screen to ON 586 mWifiConnectivityManager.handleScreenStateChanged(true); 587 588 // Set WiFi to connected state to trigger periodic scan 589 mWifiConnectivityManager.handleConnectionStateChanged( 590 WifiConnectivityManager.WIFI_STATE_CONNECTED); 591 592 // Get the first periodic scan interval 593 long firstIntervalMs = mAlarmManager 594 .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) 595 - CURRENT_SYSTEM_TIME_MS; 596 assertEquals(firstIntervalMs, WifiConnectivityManager.PERIODIC_SCAN_INTERVAL_MS); 597 598 // Now fire the first periodic scan alarm timer 599 mAlarmManager.dispatch(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG); 600 mLooper.dispatchAll(); 601 602 // Get the second periodic scan interval 603 long secondIntervalMs = mAlarmManager 604 .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) 605 - CURRENT_SYSTEM_TIME_MS; 606 607 // Verify the intervals are exponential back off 608 assertEquals(firstIntervalMs * 2, secondIntervalMs); 609 610 // Make sure we eventually stay at the maximum scan interval. 611 long intervalMs = 0; 612 for (int i = 0; i < 5; i++) { 613 mAlarmManager.dispatch(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG); 614 mLooper.dispatchAll(); 615 intervalMs = mAlarmManager 616 .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) 617 - CURRENT_SYSTEM_TIME_MS; 618 } 619 620 assertEquals(intervalMs, WifiConnectivityManager.MAX_PERIODIC_SCAN_INTERVAL_MS); 621 } 622} 623