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 17 package com.android.server.wifi; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertTrue; 21 import static org.mockito.Mockito.*; 22 import static org.mockito.MockitoAnnotations.*; 23 24 import android.net.wifi.WifiConfiguration; 25 import android.net.wifi.WifiSsid; 26 import android.os.test.TestLooper; 27 import android.support.test.filters.SmallTest; 28 import android.util.Pair; 29 30 import org.junit.Before; 31 import org.junit.Test; 32 import org.mockito.Mock; 33 34 import java.util.ArrayList; 35 import java.util.Arrays; 36 import java.util.List; 37 38 /** 39 * Unit tests for {@link com.android.server.wifi.WifiLastResortWatchdog}. 40 */ 41 @SmallTest 42 public class WifiLastResortWatchdogTest { 43 WifiLastResortWatchdog mLastResortWatchdog; 44 @Mock WifiMetrics mWifiMetrics; 45 @Mock SelfRecovery mSelfRecovery; 46 @Mock WifiStateMachine mWifiStateMachine; 47 @Mock Clock mClock; 48 49 private String[] mSsids = {"\"test1\"", "\"test2\"", "\"test3\"", "\"test4\""}; 50 private String[] mBssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "de:ad:ba:b1:e5:55", 51 "c0:ff:ee:ee:e3:ee"}; 52 private int[] mFrequencies = {2437, 5180, 5180, 2437}; 53 private String[] mCaps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", 54 "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; 55 private int[] mLevels = {-60, -86, -50, -62}; 56 private boolean[] mIsEphemeral = {false, false, false, false}; 57 private boolean[] mHasEverConnected = {false, false, false, false}; 58 private TestLooper mLooper; 59 60 @Before 61 public void setUp() throws Exception { 62 initMocks(this); 63 mLooper = new TestLooper(); 64 mLastResortWatchdog = new WifiLastResortWatchdog(mSelfRecovery, mClock, mWifiMetrics, 65 mWifiStateMachine, mLooper.getLooper()); 66 mLastResortWatchdog.setBugReportProbability(1); 67 } 68 69 private List<Pair<ScanDetail, WifiConfiguration>> createFilteredQnsCandidates(String[] ssids, 70 String[] bssids, int[] frequencies, String[] caps, int[] levels, 71 boolean[] isEphemeral) { 72 List<Pair<ScanDetail, WifiConfiguration>> candidates = new ArrayList<>(); 73 long timeStamp = System.currentTimeMillis(); 74 for (int index = 0; index < ssids.length; index++) { 75 String ssid = ssids[index].replaceAll("^\"+", "").replaceAll("\"+$", ""); 76 ScanDetail scanDetail = new ScanDetail(WifiSsid.createFromAsciiEncoded(ssid), 77 bssids[index], caps[index], levels[index], frequencies[index], timeStamp, 78 0); 79 WifiConfiguration config = null; 80 if (!isEphemeral[index]) { 81 config = mock(WifiConfiguration.class); 82 WifiConfiguration.NetworkSelectionStatus networkSelectionStatus = 83 mock(WifiConfiguration.NetworkSelectionStatus.class); 84 when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStatus); 85 when(networkSelectionStatus.getHasEverConnected()).thenReturn(true); 86 } 87 candidates.add(Pair.create(scanDetail, config)); 88 } 89 return candidates; 90 } 91 92 private List<Pair<ScanDetail, WifiConfiguration>> createFilteredQnsCandidates(String[] ssids, 93 String[] bssids, int[] frequencies, String[] caps, int[] levels, 94 boolean[] isEphemeral, boolean[] hasEverConnected) { 95 List<Pair<ScanDetail, WifiConfiguration>> candidates = 96 new ArrayList<Pair<ScanDetail, WifiConfiguration>>(); 97 long timeStamp = System.currentTimeMillis(); 98 for (int index = 0; index < ssids.length; index++) { 99 String ssid = ssids[index].replaceAll("^\"+", "").replaceAll("\"+$", ""); 100 ScanDetail scanDetail = new ScanDetail(WifiSsid.createFromAsciiEncoded(ssid), 101 bssids[index], caps[index], levels[index], frequencies[index], timeStamp, 102 0); 103 WifiConfiguration config = null; 104 if (!isEphemeral[index]) { 105 config = mock(WifiConfiguration.class); 106 WifiConfiguration.NetworkSelectionStatus networkSelectionStatus = 107 mock(WifiConfiguration.NetworkSelectionStatus.class); 108 when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStatus); 109 when(networkSelectionStatus.getHasEverConnected()) 110 .thenReturn(hasEverConnected[index]); 111 } 112 candidates.add(Pair.create(scanDetail, config)); 113 } 114 return candidates; 115 } 116 117 private void assertFailureCountEquals( 118 String bssid, int associationRejections, int authenticationFailures, int dhcpFailures) { 119 assertEquals(associationRejections, mLastResortWatchdog.getFailureCount(bssid, 120 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION)); 121 assertEquals(authenticationFailures, mLastResortWatchdog.getFailureCount(bssid, 122 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION)); 123 assertEquals(dhcpFailures, mLastResortWatchdog.getFailureCount(bssid, 124 WifiLastResortWatchdog.FAILURE_CODE_DHCP)); 125 } 126 127 /** 128 * Case #1: Test aging works in available network buffering 129 * This test simulates 4 networks appearing in a scan result, and then only the first 2 130 * appearing in successive scans results. 131 * Expected Behavior: 132 * 4 networks appear in recentAvailalbeNetworks, after N=MAX_BSSID_AGE scans, only 2 remain 133 */ 134 @Test 135 public void testAvailableNetworkBuffering_ageCullingWorks() throws Exception { 136 // Buffer potential candidates 1,2,3 & 4 137 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 138 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral); 139 mLastResortWatchdog.updateAvailableNetworks(candidates); 140 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 4); 141 142 // Repeatedly buffer candidates 1 & 2, MAX_BSSID_AGE - 1 times 143 candidates = createFilteredQnsCandidates(Arrays.copyOfRange(mSsids, 0, 2), 144 Arrays.copyOfRange(mBssids, 0, 2), 145 Arrays.copyOfRange(mFrequencies, 0, 2), 146 Arrays.copyOfRange(mCaps, 0, 2), 147 Arrays.copyOfRange(mLevels, 0, 2), 148 Arrays.copyOfRange(mIsEphemeral, 0, 2)); 149 for (int i = 0; i < WifiLastResortWatchdog.MAX_BSSID_AGE - 1; i++) { 150 mLastResortWatchdog.updateAvailableNetworks(candidates); 151 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[0]).age, 0); 152 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[1]).age, 0); 153 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[2]).age, 154 i + 1); 155 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[3]).age, 156 i + 1); 157 } 158 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 4); 159 160 // One more buffering should age and cull candidates 2 & 3 161 mLastResortWatchdog.updateAvailableNetworks(candidates); 162 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 2); 163 }; 164 165 /** 166 * Case #2: Culling of old networks 167 * Part 1: 168 * This test starts with 4 networks seen, it then buffers N=MAX_BSSID_AGE empty scans 169 * Expected behaviour: All networks are culled from recentAvailableNetworks 170 * 171 * Part 2: 172 * Buffer some more empty scans just to make sure nothing breaks 173 */ 174 @Test 175 public void testAvailableNetworkBuffering_emptyBufferWithEmptyScanResults() throws Exception { 176 // Buffer potential candidates 1,2,3 & 4 177 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 178 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral); 179 mLastResortWatchdog.updateAvailableNetworks(candidates); 180 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 4); 181 182 // Repeatedly buffer with no candidates 183 candidates = createFilteredQnsCandidates(Arrays.copyOfRange(mSsids, 0, 0), 184 Arrays.copyOfRange(mBssids, 0, 0), 185 Arrays.copyOfRange(mFrequencies, 0, 0), 186 Arrays.copyOfRange(mCaps, 0, 0), 187 Arrays.copyOfRange(mLevels, 0, 0), 188 Arrays.copyOfRange(mIsEphemeral, 0, 0)); 189 for (int i = 0; i < WifiLastResortWatchdog.MAX_BSSID_AGE; i++) { 190 mLastResortWatchdog.updateAvailableNetworks(candidates); 191 } 192 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 0); 193 for (int i = 0; i < WifiLastResortWatchdog.MAX_BSSID_AGE; i++) { 194 mLastResortWatchdog.updateAvailableNetworks(candidates); 195 } 196 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 0); 197 }; 198 199 /** 200 * Case 3: Adding more networks over time 201 * In this test, each successive (4 total) scan result buffers one more network. 202 * Expected behavior: recentAvailableNetworks grows with number of scan results 203 */ 204 @Test 205 public void testAvailableNetworkBuffering_addNewNetworksOverTime() throws Exception { 206 List<Pair<ScanDetail, WifiConfiguration>> candidates; 207 // Buffer (i) scan results with each successive scan result 208 for (int i = 1; i <= mSsids.length; i++) { 209 candidates = createFilteredQnsCandidates(Arrays.copyOfRange(mSsids, 0, i), 210 Arrays.copyOfRange(mBssids, 0, i), 211 Arrays.copyOfRange(mFrequencies, 0, i), 212 Arrays.copyOfRange(mCaps, 0, i), 213 Arrays.copyOfRange(mLevels, 0, i), 214 Arrays.copyOfRange(mIsEphemeral, 0, i)); 215 mLastResortWatchdog.updateAvailableNetworks(candidates); 216 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), i); 217 for (int j = 0; j < i; j++) { 218 assertEquals( 219 mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[j]).age, 0); 220 } 221 } 222 }; 223 224 /** 225 * Case 4: Test buffering with ephemeral networks & toString() 226 * This test is the same as Case 1, but it also includes ephemeral networks. toString is also 227 * smoke tested at various places in this test 228 * Expected behaviour: 4 networks added initially (2 ephemeral). After MAX_BSSID_AGE more 229 * bufferings, 2 are culled (leaving 1 ephemeral, one normal). toString method should execute 230 * without breaking anything. 231 */ 232 @Test 233 public void testAvailableNetworkBuffering_multipleNetworksSomeEphemeral() throws Exception { 234 boolean[] isEphemeral = {true, false, true, false}; 235 236 // Buffer potential candidates 1,2,3 & 4 237 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 238 mBssids, mFrequencies, mCaps, mLevels, isEphemeral); 239 mLastResortWatchdog.updateAvailableNetworks(candidates); 240 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 4); 241 242 // Repeatedly buffer candidates 1 & 2, MAX_BSSID_AGE - 1 times 243 candidates = createFilteredQnsCandidates(Arrays.copyOfRange(mSsids, 0, 2), 244 Arrays.copyOfRange(mBssids, 0, 2), 245 Arrays.copyOfRange(mFrequencies, 0, 2), 246 Arrays.copyOfRange(mCaps, 0, 2), 247 Arrays.copyOfRange(mLevels, 0, 2), 248 Arrays.copyOfRange(isEphemeral, 0, 2)); 249 for (int i = 0; i < WifiLastResortWatchdog.MAX_BSSID_AGE - 1; i++) { 250 mLastResortWatchdog.updateAvailableNetworks(candidates); 251 mLastResortWatchdog.toString(); 252 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[0]).age, 0); 253 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[1]).age, 0); 254 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[2]).age, 255 i + 1); 256 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[3]).age, 257 i + 1); 258 } 259 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 4); 260 261 // One more buffering should age and cull candidates 2 & 3 262 mLastResortWatchdog.updateAvailableNetworks(candidates); 263 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 2); 264 mLastResortWatchdog.toString(); 265 }; 266 267 /** 268 * Case 5: Test failure counting, incrementing a specific BSSID 269 * Test has 4 networks buffered, increment each different failure type on one of them 270 * Expected behaviour: See failure counts for the specific failures rise to the appropriate 271 * level for the specific network 272 */ 273 @Test 274 public void testFailureCounting_countFailuresForSingleBssid() throws Exception { 275 int associationRejections = 5; 276 int authenticationFailures = 9; 277 int dhcpFailures = 11; 278 // Buffer potential candidates 1,2,3 & 4 279 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 280 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); 281 mLastResortWatchdog.updateAvailableNetworks(candidates); 282 283 // Ensure new networks have zero'ed failure counts 284 for (int i = 0; i < mSsids.length; i++) { 285 assertFailureCountEquals(mBssids[i], 0, 0, 0); 286 } 287 288 //Increment failure count for each network and failure type 289 int net = 0; 290 for (int i = 0; i < associationRejections; i++) { 291 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 292 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 293 assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() 294 .get(mBssids[net]).associationRejection); 295 } 296 net = 1; 297 for (int i = 0; i < authenticationFailures; i++) { 298 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 299 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 300 assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() 301 .get(mBssids[net]).authenticationFailure); 302 } 303 net = 2; 304 for (int i = 0; i < dhcpFailures; i++) { 305 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 306 WifiLastResortWatchdog.FAILURE_CODE_DHCP); 307 assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() 308 .get(mBssids[net]).dhcpFailure); 309 } 310 assertFailureCountEquals(mBssids[0], associationRejections, 0, 0); 311 assertFailureCountEquals(mBssids[1], 0, authenticationFailures, 0); 312 assertFailureCountEquals(mBssids[2], 0, 0, dhcpFailures); 313 assertFailureCountEquals(mBssids[3], 0, 0, 0); 314 } 315 316 /** 317 * Case 6: Test failure counting, incrementing a specific BSSID, with some ephemeral networks 318 * Almost identical to test case 5. 319 * Test has 4 networks buffered (two are ephemeral), increment each different failure type on 320 * one of them. 321 * Expected behavior: See failure counts for the specific failures rise to the appropriate 322 * level for the specific network 323 */ 324 @Test 325 public void testFailureCounting_countFailuresForSingleBssidWithEphemeral() throws Exception { 326 int associationRejections = 5; 327 int authenticationFailures = 9; 328 int dhcpFailures = 11; 329 boolean[] mIsEphemeral = {false, true, false, true}; 330 // Buffer potential candidates 1,2,3 & 4 331 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 332 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); 333 mLastResortWatchdog.updateAvailableNetworks(candidates); 334 335 // Ensure new networks have zero'ed failure counts 336 for (int i = 0; i < mSsids.length; i++) { 337 assertFailureCountEquals(mBssids[i], 0, 0, 0); 338 } 339 340 //Increment failure count for each network and failure type 341 int net = 0; 342 for (int i = 0; i < associationRejections; i++) { 343 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 344 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 345 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks() 346 .get(mBssids[net]).associationRejection, i + 1); 347 } 348 net = 1; 349 for (int i = 0; i < authenticationFailures; i++) { 350 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 351 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 352 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks() 353 .get(mBssids[net]).authenticationFailure, i + 1); 354 } 355 net = 2; 356 for (int i = 0; i < dhcpFailures; i++) { 357 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 358 WifiLastResortWatchdog.FAILURE_CODE_DHCP); 359 assertEquals(mLastResortWatchdog.getRecentAvailableNetworks() 360 .get(mBssids[net]).dhcpFailure, i + 1); 361 } 362 assertFailureCountEquals(mBssids[0], associationRejections, 0, 0); 363 assertFailureCountEquals(mBssids[1], 0, authenticationFailures, 0); 364 assertFailureCountEquals(mBssids[2], 0, 0, dhcpFailures); 365 assertFailureCountEquals(mBssids[3], 0, 0, 0); 366 } 367 368 /** 369 * Case 7: Test failure counting, incrementing a specific BSSID but with the wrong SSID given 370 * Test has 4 networks buffered, increment each different failure type on one of them but using 371 * the wrong ssid. 372 * Expected behavior: Failure counts will remain at zero for all networks 373 */ 374 @Test 375 public void testFailureCounting_countFailuresForSingleBssidWrongSsid() throws Exception { 376 String badSsid = "ItHertzWhenIP"; 377 int associationRejections = 5; 378 int authenticationFailures = 9; 379 int dhcpFailures = 11; 380 // Buffer potential candidates 1,2,3 & 4 381 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 382 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); 383 mLastResortWatchdog.updateAvailableNetworks(candidates); 384 385 // Ensure new networks have zero'ed failure counts 386 for (int i = 0; i < mSsids.length; i++) { 387 assertFailureCountEquals(mBssids[i], 0, 0, 0); 388 } 389 390 //Increment failure count for each network and failure type 391 int net = 0; 392 for (int i = 0; i < associationRejections; i++) { 393 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(badSsid, mBssids[net], 394 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 395 } 396 net = 1; 397 for (int i = 0; i < authenticationFailures; i++) { 398 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(badSsid, mBssids[net], 399 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 400 } 401 net = 2; 402 for (int i = 0; i < dhcpFailures; i++) { 403 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(badSsid, mBssids[net], 404 WifiLastResortWatchdog.FAILURE_CODE_DHCP); 405 } 406 407 // Ensure all networks still have zero failure count 408 for (int i = 0; i < mSsids.length; i++) { 409 assertFailureCountEquals(mBssids[i], 0, 0, 0); 410 } 411 } 412 413 /** 414 * Case 8: Test failure counting, increment a bssid that does not exist 415 * Test has 4 networks buffered, increment each failure type, but using the wrong bssid 416 * Expected behavior: Failure counts will remain at zero for all networks 417 */ 418 @Test 419 public void testFailureCounting_countFailuresForNonexistentBssid() throws Exception { 420 String badBssid = "de:ad:be:ee:e3:ef"; 421 int associationRejections = 5; 422 int authenticationFailures = 9; 423 int dhcpFailures = 11; 424 // Buffer potential candidates 1,2,3 & 4 425 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 426 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); 427 mLastResortWatchdog.updateAvailableNetworks(candidates); 428 429 // Ensure new networks have zero'ed failure counts 430 for (int i = 0; i < mSsids.length; i++) { 431 assertFailureCountEquals(mBssids[i], 0, 0, 0); 432 } 433 434 //Increment failure count for each network and failure type 435 int net = 0; 436 for (int i = 0; i < associationRejections; i++) { 437 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], badBssid, 438 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 439 } 440 net = 1; 441 for (int i = 0; i < authenticationFailures; i++) { 442 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], badBssid, 443 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 444 } 445 net = 2; 446 for (int i = 0; i < dhcpFailures; i++) { 447 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], badBssid, 448 WifiLastResortWatchdog.FAILURE_CODE_DHCP); 449 } 450 451 // Ensure all networks still have zero failure count 452 for (int i = 0; i < mSsids.length; i++) { 453 assertFailureCountEquals(mBssids[i], 0, 0, 0); 454 } 455 } 456 457 /** 458 * Case 9: Test Failure Counting, using the "Any" BSSID 459 * Test has 4 buffered networks, two of which share the same SSID (different mBssids) 460 * Each failure type is incremented for the shared SSID, but with BSSID "any" 461 * Expected Behavior: Both networks increment their counts in tandem 462 */ 463 @Test 464 public void testFailureCounting_countFailuresForAnyBssid() throws Exception { 465 String[] ssids = {"\"test1\"", "\"test2\"", "\"test1\"", "\"test4\""}; 466 int associationRejections = 5; 467 int authenticationFailures = 9; 468 int dhcpFailures = 11; 469 // Buffer potential candidates 1,2,3 & 4 470 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(ssids, 471 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); 472 mLastResortWatchdog.updateAvailableNetworks(candidates); 473 474 // Ensure new networks have zero'ed failure counts 475 for (int i = 0; i < ssids.length; i++) { 476 assertFailureCountEquals(mBssids[i], 0, 0, 0); 477 } 478 479 //Increment failure count for each network and failure type 480 int net = 0; 481 for (int i = 0; i < associationRejections; i++) { 482 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 483 ssids[0], WifiLastResortWatchdog.BSSID_ANY, 484 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 485 } 486 net = 1; 487 for (int i = 0; i < authenticationFailures; i++) { 488 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 489 ssids[0], WifiLastResortWatchdog.BSSID_ANY, 490 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 491 } 492 net = 2; 493 for (int i = 0; i < dhcpFailures; i++) { 494 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 495 ssids[0], WifiLastResortWatchdog.BSSID_ANY, 496 WifiLastResortWatchdog.FAILURE_CODE_DHCP); 497 } 498 assertFailureCountEquals(mBssids[0], associationRejections, authenticationFailures, 499 dhcpFailures); 500 assertFailureCountEquals(mBssids[1], 0, 0, 0); 501 assertFailureCountEquals(mBssids[2], associationRejections, authenticationFailures, 502 dhcpFailures); 503 assertFailureCountEquals(mBssids[3], 0, 0, 0); 504 } 505 506 /** 507 * Case 10: Test Failure Counting, using the "Any" BSSID for nonexistent SSID 508 * Test has 4 buffered networks, two of which share the same SSID (different mBssids) 509 * Each failure type is incremented for a bad SSID (doesn't exist), but with BSSID "any" 510 * Expected Behavior: No Failures counted 511 */ 512 @Test 513 public void testFailureCounting_countFailuresForAnyBssidNonexistentSsid() throws Exception { 514 int associationRejections = 5; 515 int authenticationFailures = 9; 516 int dhcpFailures = 11; 517 String badSsid = "DropItLikeIt'sHotSpot"; 518 // Buffer potential candidates 1,2,3 & 4 519 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 520 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); 521 mLastResortWatchdog.updateAvailableNetworks(candidates); 522 523 // Ensure new networks have zero'ed failure counts 524 for (int i = 0; i < mSsids.length; i++) { 525 assertFailureCountEquals(mBssids[i], 0, 0, 0); 526 } 527 528 //Increment failure count for each network and failure type 529 int net = 0; 530 for (int i = 0; i < associationRejections; i++) { 531 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 532 badSsid, WifiLastResortWatchdog.BSSID_ANY, 533 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 534 } 535 net = 1; 536 for (int i = 0; i < authenticationFailures; i++) { 537 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 538 badSsid, WifiLastResortWatchdog.BSSID_ANY, 539 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 540 } 541 net = 2; 542 for (int i = 0; i < dhcpFailures; i++) { 543 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 544 badSsid, WifiLastResortWatchdog.BSSID_ANY, 545 WifiLastResortWatchdog.FAILURE_CODE_DHCP); 546 } 547 // Check that all network failure counts are still zero 548 for (int i = 0; i < mSsids.length; i++) { 549 assertFailureCountEquals(mBssids[i], 0, 0, 0); 550 } 551 } 552 553 /** 554 * Case 11: Test Failure Counting, over failure Threshold check 555 * Test has 4 buffered networks, cause FAILURE_THRESHOLD failures for each failure type to one 556 * of each network (leaving one unfailed). 557 * Expected Behavior: 3 of the Available Networks report OverFailureThreshold 558 */ 559 @Test 560 public void testFailureCounting_failureOverThresholdCheck() throws Exception { 561 int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD; 562 int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD; 563 int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD; 564 // Buffer potential candidates 1,2,3 & 4 565 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 566 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); 567 mLastResortWatchdog.updateAvailableNetworks(candidates); 568 569 // Ensure new networks have zero'ed failure counts 570 for (int i = 0; i < mSsids.length; i++) { 571 assertFailureCountEquals(mBssids[i], 0, 0, 0); 572 } 573 574 //Increment failure count for each network and failure type 575 int net = 0; 576 for (int i = 0; i < associationRejections; i++) { 577 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 578 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 579 } 580 net = 1; 581 for (int i = 0; i < authenticationFailures; i++) { 582 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 583 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 584 } 585 net = 2; 586 for (int i = 0; i < dhcpFailures; i++) { 587 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 588 WifiLastResortWatchdog.FAILURE_CODE_DHCP); 589 } 590 assertEquals(true, mLastResortWatchdog.isOverFailureThreshold(mBssids[0])); 591 assertEquals(true, mLastResortWatchdog.isOverFailureThreshold(mBssids[1])); 592 assertEquals(true, mLastResortWatchdog.isOverFailureThreshold(mBssids[2])); 593 assertEquals(false, mLastResortWatchdog.isOverFailureThreshold(mBssids[3])); 594 } 595 596 /** 597 * Case 12: Test Failure Counting, under failure Threshold check 598 * Test has 4 buffered networks, cause FAILURE_THRESHOLD - 1 failures for each failure type to 599 * one of each network (leaving one unfailed). 600 * Expected Behavior: 0 of the Available Networks report OverFailureThreshold 601 */ 602 @Test 603 public void testFailureCounting_failureUnderThresholdCheck() throws Exception { 604 int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD - 1; 605 int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD - 1; 606 int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD - 1; 607 // Buffer potential candidates 1,2,3 & 4 608 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 609 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); 610 mLastResortWatchdog.updateAvailableNetworks(candidates); 611 612 // Ensure new networks have zero'ed failure counts 613 for (int i = 0; i < mSsids.length; i++) { 614 assertFailureCountEquals(mBssids[i], 0, 0, 0); 615 } 616 617 //Increment failure count for each network and failure type 618 int net = 0; 619 for (int i = 0; i < associationRejections; i++) { 620 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 621 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 622 } 623 net = 1; 624 for (int i = 0; i < authenticationFailures; i++) { 625 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 626 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 627 } 628 net = 2; 629 for (int i = 0; i < dhcpFailures; i++) { 630 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 631 WifiLastResortWatchdog.FAILURE_CODE_DHCP); 632 } 633 assertEquals(false, mLastResortWatchdog.isOverFailureThreshold(mBssids[0])); 634 assertEquals(false, mLastResortWatchdog.isOverFailureThreshold(mBssids[1])); 635 assertEquals(false, mLastResortWatchdog.isOverFailureThreshold(mBssids[2])); 636 assertEquals(false, mLastResortWatchdog.isOverFailureThreshold(mBssids[3])); 637 } 638 639 /** 640 * Case 13: Test Failure Counting, available network buffering does not affect counts 641 * In this test: 642 * 4 networks are buffered 643 * Some number of failures are counted 644 * networks are buffered again 645 * Expected Behavior: Failure counts are not modified by buffering 646 */ 647 @Test 648 public void testAvailableNetworkBuffering_doesNotAffectFailureCounts() throws Exception { 649 int associationRejections = 5; 650 int authenticationFailures = 9; 651 int dhcpFailures = 11; 652 // Buffer potential candidates 1,2,3 & 4 653 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 654 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); 655 mLastResortWatchdog.updateAvailableNetworks(candidates); 656 657 // Ensure new networks have zero'ed failure counts 658 for (int i = 0; i < mSsids.length; i++) { 659 assertFailureCountEquals(mBssids[i], 0, 0, 0); 660 } 661 662 //Increment failure count for each network and failure type 663 int net = 0; 664 for (int i = 0; i < associationRejections; i++) { 665 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 666 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 667 assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() 668 .get(mBssids[net]).associationRejection); 669 } 670 net = 1; 671 for (int i = 0; i < authenticationFailures; i++) { 672 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 673 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 674 assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() 675 .get(mBssids[net]).authenticationFailure); 676 } 677 net = 2; 678 for (int i = 0; i < dhcpFailures; i++) { 679 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 680 WifiLastResortWatchdog.FAILURE_CODE_DHCP); 681 assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() 682 .get(mBssids[net]).dhcpFailure); 683 } 684 // Check Each Network has appropriate failure count 685 assertFailureCountEquals(mBssids[0], associationRejections, 0, 0); 686 assertFailureCountEquals(mBssids[1], 0, authenticationFailures, 0); 687 assertFailureCountEquals(mBssids[2], 0, 0, dhcpFailures); 688 assertFailureCountEquals(mBssids[3], 0, 0, 0); 689 690 // Re-buffer all networks 691 for (int i = 0; i < WifiLastResortWatchdog.MAX_BSSID_AGE; i++) { 692 mLastResortWatchdog.updateAvailableNetworks(candidates); 693 } 694 695 // Check Each Network still has appropriate failure count 696 assertFailureCountEquals(mBssids[0], associationRejections, 0, 0); 697 assertFailureCountEquals(mBssids[1], 0, authenticationFailures, 0); 698 assertFailureCountEquals(mBssids[2], 0, 0, dhcpFailures); 699 assertFailureCountEquals(mBssids[3], 0, 0, 0); 700 } 701 702 /** 703 * Case 14: Test Failure Counting, culling of an old network will remove its failure counts 704 * In this test: 705 * 4 networks are buffered 706 * Some number of failures are counted for all networks 707 * 3 of the networks are buffered until the 4th dies of old age 708 * The 4th network is re-buffered 709 * Expected Behavior: Failure counts for the 4th network are cleared after re-buffering 710 */ 711 @Test 712 public void testAvailableNetworkBuffering_rebufferWipesCounts() throws Exception { 713 int associationRejections = 5; 714 int authenticationFailures = 9; 715 int dhcpFailures = 11; 716 // Buffer potential candidates 1,2,3 & 4 717 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 718 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); 719 mLastResortWatchdog.updateAvailableNetworks(candidates); 720 721 // Ensure new networks have zero'ed failure counts 722 for (int i = 0; i < mSsids.length; i++) { 723 assertFailureCountEquals(mBssids[i], 0, 0, 0); 724 } 725 726 //Increment failure count for each network and failure type 727 int net = 0; 728 for (int i = 0; i < associationRejections; i++) { 729 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 730 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 731 assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() 732 .get(mBssids[net]).associationRejection); 733 } 734 net = 1; 735 for (int i = 0; i < authenticationFailures; i++) { 736 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 737 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 738 assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() 739 .get(mBssids[net]).authenticationFailure); 740 } 741 net = 2; 742 for (int i = 0; i < dhcpFailures; i++) { 743 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 744 WifiLastResortWatchdog.FAILURE_CODE_DHCP); 745 assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() 746 .get(mBssids[net]).dhcpFailure); 747 } 748 // Check Each Network has appropriate failure count 749 assertFailureCountEquals(mBssids[0], associationRejections, 0, 0); 750 assertFailureCountEquals(mBssids[1], 0, authenticationFailures, 0); 751 assertFailureCountEquals(mBssids[2], 0, 0, dhcpFailures); 752 assertFailureCountEquals(mBssids[3], 0, 0, 0); 753 754 // Re-buffer all networks except 'test1' until it dies of old age 755 candidates = createFilteredQnsCandidates(Arrays.copyOfRange(mSsids, 1, 4), 756 Arrays.copyOfRange(mBssids, 1, 4), 757 Arrays.copyOfRange(mFrequencies, 1, 4), 758 Arrays.copyOfRange(mCaps, 1, 4), 759 Arrays.copyOfRange(mLevels, 1, 4), 760 Arrays.copyOfRange(mIsEphemeral, 1, 4)); 761 for (int i = 0; i < WifiLastResortWatchdog.MAX_BSSID_AGE; i++) { 762 mLastResortWatchdog.updateAvailableNetworks(candidates); 763 } 764 assertEquals(3, mLastResortWatchdog.getRecentAvailableNetworks().size()); 765 // Re-buffer All networks, with 'test1' again 766 candidates = createFilteredQnsCandidates(mSsids, 767 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); 768 mLastResortWatchdog.updateAvailableNetworks(candidates); 769 770 // Check Each Network has appropriate failure count (network 1 should be zero'd) 771 assertFailureCountEquals(mBssids[0], 0, 0, 0); 772 assertFailureCountEquals(mBssids[1], 0, authenticationFailures, 0); 773 assertFailureCountEquals(mBssids[2], 0, 0, dhcpFailures); 774 assertFailureCountEquals(mBssids[3], 0, 0, 0); 775 } 776 777 /** 778 * Case 26: Test Failure Counting, null failure incrementation 779 * In this test: 780 * 4 networks are buffered 781 * Attempt to increment failures with null BSSID & SSID 782 * Expected behavior: Nothing breaks, no counts incremented 783 */ 784 @Test 785 public void testFailureCounting_nullInputsNoBreaky() { 786 int associationRejections = 5; 787 int authenticationFailures = 9; 788 int dhcpFailures = 11; 789 // Buffer potential candidates 1,2,3 & 4 790 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 791 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); 792 mLastResortWatchdog.updateAvailableNetworks(candidates); 793 794 // Ensure new networks have zero'ed failure counts 795 for (int i = 0; i < mSsids.length; i++) { 796 assertFailureCountEquals(mBssids[i], 0, 0, 0); 797 } 798 799 //Increment failure count for each network and failure type 800 int net = 0; 801 for (int i = 0; i < associationRejections; i++) { 802 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(null, mBssids[net], 803 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 804 } 805 net = 1; 806 for (int i = 0; i < authenticationFailures; i++) { 807 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], null, 808 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 809 } 810 net = 2; 811 for (int i = 0; i < dhcpFailures; i++) { 812 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(null, null, 813 WifiLastResortWatchdog.FAILURE_CODE_DHCP); 814 } 815 816 // Ensure new networks have zero'ed failure counts 817 for (int i = 0; i < mSsids.length; i++) { 818 assertFailureCountEquals(mBssids[i], 0, 0, 0); 819 } 820 } 821 822 /** 823 * Case 27: Test Failure Counting, test all failures are counted across SSID 824 * In this test there are 8 networks, 825 * the first 4 networks have unique SSIDs amongst themselves, 826 * the last 4 networks share these SSIDs respectively, so there are 2 networks per SSID 827 * In this test we increment failure counts for the 'test1' ssid for a specific BSSID, and for 828 * the 'test2' ssid for BSSID_ANY. 829 * Expected behaviour: Failure counts for both networks on the same SSID are mirrored via both 830 * incrementation methods 831 */ 832 @Test 833 public void testFailureCounting_countFailuresAcrossSsids() throws Exception { 834 String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\"", "\"test4\"", 835 "\"test1\"", "\"test2\"", "\"test3\"", "\"test4\""}; 836 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "de:ad:ba:b1:e5:55", 837 "c0:ff:ee:ee:e3:ee", "6c:f3:7f:ae:3c:f3", "6c:f3:7f:ae:3c:f4", "d3:ad:ba:b1:35:55", 838 "c0:ff:ee:ee:33:ee"}; 839 int[] frequencies = {2437, 5180, 5180, 2437, 2437, 5180, 5180, 2437}; 840 String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", 841 "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", 842 "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; 843 int[] levels = {-60, -86, -50, -62, -60, -86, -50, -62}; 844 boolean[] isEphemeral = {false, false, false, false, false, false, false, false}; 845 boolean[] hasEverConnected = {false, false, false, false, false, false, false, 846 false}; 847 int firstNetFails = 13; 848 int secondNetFails = 8; 849 // Buffer potential candidates 1,2,3 & 4 850 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(ssids, 851 bssids, frequencies, caps, levels, isEphemeral, hasEverConnected); 852 mLastResortWatchdog.updateAvailableNetworks(candidates); 853 854 // Ensure new networks have zero'ed failure counts 855 for (int i = 0; i < ssids.length; i++) { 856 assertFailureCountEquals(bssids[i], 0, 0, 0); 857 } 858 859 //Increment failure count for the first test network ssid & bssid 860 for (int i = 0; i < firstNetFails; i++) { 861 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 862 ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 863 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 864 ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 865 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 866 ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_DHCP); 867 } 868 //Increment failure count for the first test network ssid & BSSID_ANY 869 for (int i = 0; i < secondNetFails; i++) { 870 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 871 ssids[1], WifiLastResortWatchdog.BSSID_ANY, 872 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 873 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 874 ssids[1], WifiLastResortWatchdog.BSSID_ANY, 875 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 876 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 877 ssids[1], WifiLastResortWatchdog.BSSID_ANY, 878 WifiLastResortWatchdog.FAILURE_CODE_DHCP); 879 } 880 assertFailureCountEquals(bssids[0], firstNetFails, firstNetFails, firstNetFails); 881 assertFailureCountEquals(bssids[1], secondNetFails, secondNetFails, secondNetFails); 882 assertFailureCountEquals(bssids[2], 0, 0, 0); 883 assertFailureCountEquals(bssids[3], 0, 0, 0); 884 assertFailureCountEquals(bssids[4], firstNetFails, firstNetFails, firstNetFails); 885 assertFailureCountEquals(bssids[5], secondNetFails, secondNetFails, secondNetFails); 886 assertFailureCountEquals(bssids[6], 0, 0, 0); 887 assertFailureCountEquals(bssids[7], 0, 0, 0); 888 } 889 890 /** 891 * Case 15: Test failure counting, ensure failures still counted while connected 892 * Although failures should not occur while wifi is connected, race conditions are a thing, and 893 * I'd like the count to be incremented even while connected (Later test verifies that this 894 * can't cause a trigger though) 895 * Expected behavior: Failure counts increment like normal 896 */ 897 @Test 898 public void testFailureCounting_wifiIsConnectedDoesNotAffectCounting() throws Exception { 899 int associationRejections = 5; 900 int authenticationFailures = 9; 901 int dhcpFailures = 11; 902 903 // Set Watchdogs internal wifi state tracking to 'connected' 904 mLastResortWatchdog.connectedStateTransition(true); 905 906 // Buffer potential candidates 1,2,3 & 4 907 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 908 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); 909 mLastResortWatchdog.updateAvailableNetworks(candidates); 910 911 // Ensure new networks have zero'ed failure counts 912 for (int i = 0; i < mSsids.length; i++) { 913 assertFailureCountEquals(mBssids[i], 0, 0, 0); 914 } 915 916 //Increment failure count for each network and failure type 917 int net = 0; 918 for (int i = 0; i < associationRejections; i++) { 919 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 920 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 921 assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() 922 .get(mBssids[net]).associationRejection); 923 } 924 net = 1; 925 for (int i = 0; i < authenticationFailures; i++) { 926 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 927 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 928 assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() 929 .get(mBssids[net]).authenticationFailure); 930 } 931 net = 2; 932 for (int i = 0; i < dhcpFailures; i++) { 933 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 934 WifiLastResortWatchdog.FAILURE_CODE_DHCP); 935 assertEquals(i + 1, mLastResortWatchdog.getRecentAvailableNetworks() 936 .get(mBssids[net]).dhcpFailure); 937 } 938 assertFailureCountEquals(mBssids[0], associationRejections, 0, 0); 939 assertFailureCountEquals(mBssids[1], 0, authenticationFailures, 0); 940 assertFailureCountEquals(mBssids[2], 0, 0, dhcpFailures); 941 assertFailureCountEquals(mBssids[3], 0, 0, 0); 942 } 943 944 /** 945 * Case 16: Test Failure Counting, entering ConnectedState clears all failure counts 946 * 4 Networks are buffered, cause various failures to 3 of them. Transition to ConnectedState 947 * Expected behavior: After transitioning, failure counts are reset to 0 948 */ 949 @Test 950 public void testFailureCounting_enteringWifiConnectedStateClearsCounts() throws Exception { 951 int associationRejections = 5; 952 int authenticationFailures = 9; 953 int dhcpFailures = 11; 954 955 // Buffer potential candidates 1,2,3 & 4 956 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 957 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); 958 mLastResortWatchdog.updateAvailableNetworks(candidates); 959 960 //Increment failure count for each network and failure type 961 int net = 0; 962 for (int i = 0; i < associationRejections; i++) { 963 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 964 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 965 } 966 net = 1; 967 for (int i = 0; i < authenticationFailures; i++) { 968 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 969 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 970 } 971 net = 2; 972 for (int i = 0; i < dhcpFailures; i++) { 973 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(mSsids[net], mBssids[net], 974 WifiLastResortWatchdog.FAILURE_CODE_DHCP); 975 } 976 977 // Check that we have Failures 978 assertFailureCountEquals(mBssids[0], associationRejections, 0, 0); 979 assertFailureCountEquals(mBssids[1], 0, authenticationFailures, 0); 980 assertFailureCountEquals(mBssids[2], 0, 0, dhcpFailures); 981 982 // Transition to 'ConnectedState' 983 mLastResortWatchdog.connectedStateTransition(true); 984 985 // Check that we have no failures 986 for (int i = 0; i < mSsids.length; i++) { 987 assertFailureCountEquals(mBssids[i], 0, 0, 0); 988 } 989 } 990 991 /** 992 * Case 17: Test Trigger Condition, only some networks over threshold 993 * We have 4 buffered networks, increment failure counts on 3 of them, until all 3 are over 994 * threshold. 995 * Expected Behavior: Watchdog does not trigger 996 */ 997 @Test 998 public void testTriggerCondition_someNetworksOverFailureThreshold_allHaveEverConnected() 999 throws Exception { 1000 int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD; 1001 int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 2; 1002 int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 3; 1003 boolean[] hasEverConnected = {true, true, true, true}; 1004 1005 // Buffer potential candidates 1,2,3 & 4 1006 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 1007 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, hasEverConnected); 1008 mLastResortWatchdog.updateAvailableNetworks(candidates); 1009 1010 // Increment failure count for 3 networks and failure types, asserting each time that it 1011 // does not trigger, with only 3 over threshold 1012 boolean watchdogTriggered = false; 1013 int net = 0; 1014 for (int i = 0; i < associationRejections; i++) { 1015 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1016 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1017 assertEquals(false, watchdogTriggered); 1018 } 1019 net = 1; 1020 for (int i = 0; i < authenticationFailures; i++) { 1021 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1022 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 1023 assertEquals(false, watchdogTriggered); 1024 } 1025 net = 2; 1026 for (int i = 0; i < dhcpFailures; i++) { 1027 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1028 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_DHCP); 1029 assertEquals(false, watchdogTriggered); 1030 } 1031 1032 // Check that we have Failures 1033 assertFailureCountEquals(mBssids[0], associationRejections, 0, 0); 1034 assertFailureCountEquals(mBssids[1], 0, authenticationFailures, 0); 1035 assertFailureCountEquals(mBssids[2], 0, 0, dhcpFailures); 1036 1037 // Add one more failure to one of the already over threshold networks, assert that it 1038 // does not trigger 1039 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1040 mSsids[0], mBssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1041 assertEquals(false, watchdogTriggered); 1042 } 1043 1044 /** 1045 * Case 18: Test Trigger Condition, watchdog fires once, then deactivates 1046 * In this test we have 4 networks, which we have connected to in the past. Failures are 1047 * incremented until all networks but one are over failure threshold, and then a few more times. 1048 * 1049 * Expected behavior: The watchdog triggers once as soon as all failures are over threshold, 1050 * but stops triggering for subsequent failures 1051 */ 1052 @Test 1053 public void testTriggerCondition_allNetworksOverFailureThreshold_allHaveEverConnected() 1054 throws Exception { 1055 int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD; 1056 int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 2; 1057 int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 3; 1058 boolean[] hasEverConnected = {true, true, true, true}; 1059 1060 // Buffer potential candidates 1,2,3 & 4 1061 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 1062 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, hasEverConnected); 1063 mLastResortWatchdog.updateAvailableNetworks(candidates); 1064 1065 // Bring 3 of the 4 networks over failure Threshold without triggering watchdog 1066 boolean watchdogTriggered = false; 1067 int net = 0; 1068 for (int i = 0; i < associationRejections; i++) { 1069 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1070 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1071 assertEquals(false, watchdogTriggered); 1072 } 1073 net = 1; 1074 for (int i = 0; i < authenticationFailures; i++) { 1075 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1076 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 1077 assertEquals(false, watchdogTriggered); 1078 } 1079 net = 2; 1080 for (int i = 0; i < dhcpFailures; i++) { 1081 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1082 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_DHCP); 1083 assertEquals(false, watchdogTriggered); 1084 } 1085 1086 // Bring the remaining unfailed network upto 1 less than the failure threshold 1087 net = 3; 1088 for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD - 1; i++) { 1089 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1090 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1091 assertEquals(false, watchdogTriggered); 1092 } 1093 // Increment failure count once more, check that watchdog triggered this time 1094 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1095 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1096 mLastResortWatchdog.updateAvailableNetworks(candidates); 1097 assertEquals(true, watchdogTriggered); 1098 1099 // Increment failure count 5 more times, watchdog should not trigger 1100 for (int i = 0; i < 5; i++) { 1101 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1102 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1103 assertEquals(false, watchdogTriggered); 1104 } 1105 } 1106 1107 /** 1108 * Case 19: Test Trigger Condition, all networks over failure threshold, one has ever connected 1109 * In this test we have 4 networks, only one has connected in the past. Failures are 1110 * incremented until all networks but one are over failure threshold, and then a few more times. 1111 * 1112 * Expected behavior: The watchdog triggers once as soon as all failures are over threshold, 1113 * but stops triggering for subsequent failures 1114 */ 1115 @Test 1116 public void testTriggerCondition_allNetworksOverFailureThreshold_oneHaveEverConnected() 1117 throws Exception { 1118 int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD; 1119 int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 2; 1120 int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 3; 1121 boolean[] hasEverConnected = {false, true, false, false}; 1122 1123 // Buffer potential candidates 1,2,3 & 4 1124 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 1125 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, hasEverConnected); 1126 mLastResortWatchdog.updateAvailableNetworks(candidates); 1127 1128 // Bring 3 of the 4 networks over failure Threshold without triggering watchdog 1129 boolean watchdogTriggered = false; 1130 int net = 0; 1131 for (int i = 0; i < associationRejections; i++) { 1132 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1133 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1134 assertEquals(false, watchdogTriggered); 1135 } 1136 net = 1; 1137 for (int i = 0; i < authenticationFailures; i++) { 1138 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1139 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 1140 assertEquals(false, watchdogTriggered); 1141 } 1142 net = 2; 1143 for (int i = 0; i < dhcpFailures; i++) { 1144 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1145 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_DHCP); 1146 assertEquals(false, watchdogTriggered); 1147 } 1148 1149 // Bring the remaining unfailed network upto 1 less than the failure threshold 1150 net = 3; 1151 for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD - 1; i++) { 1152 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1153 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1154 assertEquals(false, watchdogTriggered); 1155 } 1156 // Increment failure count once more, check that watchdog triggered this time 1157 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1158 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1159 mLastResortWatchdog.updateAvailableNetworks(candidates); 1160 assertEquals(true, watchdogTriggered); 1161 1162 // Increment failure count 5 more times, watchdog should not trigger 1163 for (int i = 0; i < 5; i++) { 1164 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1165 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1166 assertEquals(false, watchdogTriggered); 1167 } 1168 } 1169 1170 /** 1171 * Case 20: Test Trigger Condition, all networks over failure threshold, 0 have ever connected 1172 * In this test we have 4 networks, none have ever connected. Failures are 1173 * incremented until all networks but one are over failure threshold, and then a few more times. 1174 * 1175 * Expected behavior: The watchdog does not trigger 1176 */ 1177 @Test 1178 public void testTriggerCondition_allNetworksOverFailureThreshold_zeroHaveEverConnected() 1179 throws Exception { 1180 int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD + 1; 1181 int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 2; 1182 int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 3; 1183 1184 // Buffer potential candidates 1,2,3 & 4 1185 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 1186 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); 1187 mLastResortWatchdog.updateAvailableNetworks(candidates); 1188 1189 // Count failures on all 4 networks until all of them are over the failure threshold 1190 boolean watchdogTriggered = false; 1191 int net = 0; 1192 for (int i = 0; i < associationRejections; i++) { 1193 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1194 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1195 assertEquals(false, watchdogTriggered); 1196 } 1197 net = 1; 1198 for (int i = 0; i < authenticationFailures; i++) { 1199 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1200 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 1201 assertEquals(false, watchdogTriggered); 1202 } 1203 net = 2; 1204 for (int i = 0; i < dhcpFailures; i++) { 1205 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1206 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_DHCP); 1207 assertEquals(false, watchdogTriggered); 1208 } 1209 net = 3; 1210 for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD + 1; i++) { 1211 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1212 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1213 assertEquals(false, watchdogTriggered); 1214 } 1215 } 1216 1217 /** 1218 * Case 21: Test Trigger Condition, Conditions right to trigger, but wifi is connected 1219 * In this test we have 4 networks, all have connected in the past 1220 * incremented until all networks but one are over failure threshold, and then a few more times. 1221 * 1222 * Expected behavior: The watchdog does not trigger 1223 */ 1224 @Test 1225 public void testTriggerCondition_allNetworksOverFailureThreshold_isConnected() 1226 throws Exception { 1227 int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD + 1; 1228 int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 2; 1229 int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 3; 1230 1231 // Buffer potential candidates 1,2,3 & 4 1232 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 1233 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, mHasEverConnected); 1234 mLastResortWatchdog.updateAvailableNetworks(candidates); 1235 1236 // Set Watchdogs internal wifi state tracking to 'connected' 1237 mLastResortWatchdog.connectedStateTransition(true); 1238 1239 // Count failures on all 4 networks until all of them are over the failure threshold 1240 boolean watchdogTriggered = false; 1241 int net = 0; 1242 for (int i = 0; i < associationRejections; i++) { 1243 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1244 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1245 assertEquals(false, watchdogTriggered); 1246 } 1247 net = 1; 1248 for (int i = 0; i < authenticationFailures; i++) { 1249 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1250 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 1251 assertEquals(false, watchdogTriggered); 1252 } 1253 net = 2; 1254 for (int i = 0; i < dhcpFailures; i++) { 1255 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1256 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_DHCP); 1257 assertEquals(false, watchdogTriggered); 1258 } 1259 net = 3; 1260 for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD + 1; i++) { 1261 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1262 mSsids[net], mBssids[net], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1263 assertEquals(false, watchdogTriggered); 1264 } 1265 } 1266 1267 private void incrementFailuresUntilTrigger(String[] ssids, String[] bssids) { 1268 // Bring 3 of the 4 networks over failure Threshold without triggering watchdog 1269 boolean watchdogTriggered = false; 1270 for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { 1271 for (int j = 0; j < ssids.length - 1; j++) { 1272 watchdogTriggered = mLastResortWatchdog 1273 .noteConnectionFailureAndTriggerIfNeeded(ssids[j], bssids[j], 1274 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1275 assertEquals(false, watchdogTriggered); 1276 } 1277 } 1278 for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD - 1; i++) { 1279 watchdogTriggered = mLastResortWatchdog 1280 .noteConnectionFailureAndTriggerIfNeeded(ssids[ssids.length - 1], 1281 bssids[ssids.length - 1], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1282 assertEquals(false, watchdogTriggered); 1283 } 1284 1285 // Increment failure count once more, check that watchdog triggered this time 1286 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1287 ssids[ssids.length - 1], bssids[ssids.length - 1], 1288 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1289 assertEquals(true, watchdogTriggered); 1290 verify(mSelfRecovery).trigger(eq(SelfRecovery.REASON_LAST_RESORT_WATCHDOG)); 1291 reset(mSelfRecovery); 1292 } 1293 1294 /** 1295 * Case 22: Test enabling/disabling of Watchdog Trigger, disabled after triggering 1296 * In this test, we have 4 networks. Increment failures until Watchdog triggers. Increment some 1297 * more failures. 1298 * Expected behavior: Watchdog trigger gets deactivated after triggering, and stops triggering 1299 */ 1300 @Test 1301 public void testTriggerEnabling_disabledAfterTriggering() throws Exception { 1302 int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD; 1303 int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 2; 1304 int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 3; 1305 boolean[] hasEverConnected = {false, true, false, false}; 1306 1307 // Buffer potential candidates 1,2,3 & 4 1308 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 1309 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, hasEverConnected); 1310 mLastResortWatchdog.updateAvailableNetworks(candidates); 1311 1312 incrementFailuresUntilTrigger(mSsids, mBssids); 1313 1314 // Increment failure count 5 more times, watchdog should not trigger 1315 for (int i = 0; i < 5; i++) { 1316 boolean watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1317 mSsids[3], mBssids[3], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1318 assertEquals(false, watchdogTriggered); 1319 } 1320 } 1321 1322 /** 1323 * Case 23: Test enabling/disabling of Watchdog Trigger, trigger re-enabled after connecting 1324 * In this test, we have 4 networks. Increment failures until Watchdog triggers and deactivates, 1325 * transition wifi to connected state, then increment failures until all networks over threshold 1326 * Expected behavior: Watchdog able to trigger again after transitioning to and from connected 1327 * state 1328 */ 1329 @Test 1330 public void testTriggerEnabling_enabledAfterConnecting() throws Exception { 1331 int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD; 1332 int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 2; 1333 int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 3; 1334 boolean[] hasEverConnected = {false, true, false, false}; 1335 boolean watchdogTriggered; 1336 // Buffer potential candidates 1,2,3 & 4 1337 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(mSsids, 1338 mBssids, mFrequencies, mCaps, mLevels, mIsEphemeral, hasEverConnected); 1339 mLastResortWatchdog.updateAvailableNetworks(candidates); 1340 1341 incrementFailuresUntilTrigger(mSsids, mBssids); 1342 1343 // Increment failure count 5 more times, ensure trigger is deactivated 1344 for (int i = 0; i < 5; i++) { 1345 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1346 mSsids[3], mBssids[3], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1347 mLastResortWatchdog.updateAvailableNetworks(candidates); 1348 assertEquals(false, watchdogTriggered); 1349 } 1350 1351 // transition Watchdog wifi state tracking to 'connected' then back to 'disconnected' 1352 mLastResortWatchdog.connectedStateTransition(true); 1353 mLastResortWatchdog.connectedStateTransition(false); 1354 1355 // Fail 3/4 networks until they're over threshold 1356 for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD + 1; i++) { 1357 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1358 mSsids[0], mBssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1359 assertEquals(false, watchdogTriggered); 1360 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1361 mSsids[1], mBssids[1], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 1362 assertEquals(false, watchdogTriggered); 1363 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1364 mSsids[2], mBssids[2], WifiLastResortWatchdog.FAILURE_CODE_DHCP); 1365 assertEquals(false, watchdogTriggered); 1366 } 1367 1368 // Bring the remaining unfailed network upto 1 less than the failure threshold 1369 for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD - 1; i++) { 1370 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1371 mSsids[3], mBssids[3], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1372 assertEquals(false, watchdogTriggered); 1373 } 1374 // Increment failure count once more, check that watchdog triggered this time 1375 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1376 mSsids[3], mBssids[3], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1377 assertEquals(true, watchdogTriggered); 1378 } 1379 1380 /** 1381 * Case 24: Test enabling/disabling of Watchdog Trigger, trigger re-enabled after new network 1382 * In this test, we have 3 networks. Increment failures until Watchdog triggers and deactivates, 1383 * we then buffer a new network (network 4), then increment failures until all networks over 1384 * threshold Expected behavior: Watchdog able to trigger again after discovering a new network 1385 */ 1386 @Test 1387 public void testTriggerEnabling_enabledAfterNewNetwork() { 1388 int associationRejections = WifiLastResortWatchdog.FAILURE_THRESHOLD; 1389 int authenticationFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 2; 1390 int dhcpFailures = WifiLastResortWatchdog.FAILURE_THRESHOLD + 3; 1391 boolean[] hasEverConnected = {false, true, false, false}; 1392 boolean watchdogTriggered; 1393 1394 // Buffer potential candidates 1,2,3 1395 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates( 1396 Arrays.copyOfRange(mSsids, 0, 3), 1397 Arrays.copyOfRange(mBssids, 0, 3), 1398 Arrays.copyOfRange(mFrequencies, 0, 3), 1399 Arrays.copyOfRange(mCaps, 0, 3), 1400 Arrays.copyOfRange(mLevels, 0, 3), 1401 Arrays.copyOfRange(mIsEphemeral, 0, 3), 1402 Arrays.copyOfRange(hasEverConnected, 0, 3)); 1403 mLastResortWatchdog.updateAvailableNetworks(candidates); 1404 1405 incrementFailuresUntilTrigger(Arrays.copyOfRange(mSsids, 0, 3), 1406 Arrays.copyOfRange(mBssids, 0, 3)); 1407 1408 // Increment failure count 5 more times, ensure trigger is deactivated 1409 for (int i = 0; i < 5; i++) { 1410 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1411 mSsids[2], mBssids[2], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1412 mLastResortWatchdog.updateAvailableNetworks(candidates); 1413 assertEquals(false, watchdogTriggered); 1414 } 1415 1416 candidates = createFilteredQnsCandidates(mSsids, mBssids, mFrequencies, mCaps, mLevels, 1417 mIsEphemeral, hasEverConnected); 1418 mLastResortWatchdog.updateAvailableNetworks(candidates); 1419 1420 incrementFailuresUntilTrigger(mSsids, mBssids); 1421 1422 } 1423 1424 /** 1425 * Case 28: Test Metrics collection 1426 * Setup 5 networks (unique SSIDs). Fail them until watchdog triggers, with 1 network failing 1427 * association, 1 failing authentication, 2 failing dhcp and one failing both authentication and 1428 * dhcp, (over threshold for all these failures) 1429 * Expected behavior: Metrics are updated as follows 1430 * Triggers++ 1431 * # of Networks += 5 1432 * Triggers with Bad association++ 1433 * Triggers with Bad authentication++ 1434 * Triggers with Bad dhcp++ 1435 * Number of networks with bad association += 1 1436 * Number of networks with bad authentication += 2 1437 * Number of networks with bad dhcp += 3 1438 */ 1439 @Test 1440 public void testMetricsCollection() { 1441 String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\"", "\"test4\"", "\"test5\""}; 1442 String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "de:ad:ba:b1:e5:55", 1443 "c0:ff:ee:ee:e3:ee", "6c:f3:7f:ae:3c:f3"}; 1444 int[] frequencies = {2437, 5180, 5180, 2437, 2437}; 1445 String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", 1446 "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; 1447 int[] levels = {-60, -86, -50, -62, -60}; 1448 boolean[] isEphemeral = {false, false, false, false, false}; 1449 boolean[] hasEverConnected = {true, false, false, false, false}; 1450 // Buffer potential candidates 1,2,3,4 & 5 1451 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(ssids, 1452 bssids, frequencies, caps, levels, isEphemeral, hasEverConnected); 1453 mLastResortWatchdog.updateAvailableNetworks(candidates); 1454 1455 // Ensure new networks have zero'ed failure counts 1456 for (int i = 0; i < ssids.length; i++) { 1457 assertFailureCountEquals(bssids[i], 0, 0, 0); 1458 } 1459 1460 final long timeAtFailure = 100; 1461 final long timeAtReconnect = 5000; 1462 final long expectedDuration = timeAtReconnect - timeAtFailure; 1463 when(mClock.getElapsedSinceBootMillis()).thenReturn(timeAtFailure, timeAtReconnect); 1464 1465 //Increment failure counts 1466 for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { 1467 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1468 ssids[1], bssids[1], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 1469 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1470 ssids[2], bssids[2], WifiLastResortWatchdog.FAILURE_CODE_DHCP); 1471 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1472 ssids[3], bssids[3], WifiLastResortWatchdog.FAILURE_CODE_DHCP); 1473 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1474 ssids[4], bssids[4], WifiLastResortWatchdog.FAILURE_CODE_DHCP); 1475 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1476 ssids[4], bssids[4], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 1477 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1478 ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1479 } 1480 1481 // Verify relevant WifiMetrics calls were made once with appropriate arguments 1482 verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggers(); 1483 verify(mWifiMetrics, times(1)).addCountToNumLastResortWatchdogAvailableNetworksTotal(5); 1484 verify(mWifiMetrics, times(1)) 1485 .addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal(2); 1486 verify(mWifiMetrics, times(1)) 1487 .incrementNumLastResortWatchdogTriggersWithBadAuthentication(); 1488 verify(mWifiMetrics, times(1)) 1489 .addCountToNumLastResortWatchdogBadAssociationNetworksTotal(1); 1490 verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggersWithBadAssociation(); 1491 verify(mWifiMetrics, times(1)).addCountToNumLastResortWatchdogBadDhcpNetworksTotal(3); 1492 verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggersWithBadDhcp(); 1493 1494 // Simulate wifi connecting after triggering 1495 mLastResortWatchdog.connectedStateTransition(true); 1496 1497 // Verify that WifiMetrics counted this as a Watchdog success 1498 verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogSuccesses(); 1499 verify(mWifiMetrics, times(1)).setWatchdogSuccessTimeDurationMs(eq(expectedDuration)); 1500 1501 // Verify takeBugReport is called 1502 mLooper.dispatchAll(); 1503 verify(mWifiStateMachine, times(1)).takeBugReport(anyString(), anyString()); 1504 1505 // Simulate wifi disconnecting 1506 mLastResortWatchdog.connectedStateTransition(false); 1507 1508 // Verify that WifiMetrics has still only counted one success 1509 verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogSuccesses(); 1510 verify(mWifiMetrics, times(1)).setWatchdogSuccessTimeDurationMs(eq(expectedDuration)); 1511 // Verify takeBugReport not called again 1512 mLooper.dispatchAll(); 1513 verify(mWifiStateMachine, times(1)).takeBugReport(anyString(), anyString()); 1514 1515 // Remove the fifth network from candidates 1516 candidates = createFilteredQnsCandidates(Arrays.copyOfRange(mSsids, 0, 4), 1517 Arrays.copyOfRange(mBssids, 0, 4), 1518 Arrays.copyOfRange(mFrequencies, 0, 4), 1519 Arrays.copyOfRange(mCaps, 0, 4), 1520 Arrays.copyOfRange(mLevels, 0, 4), 1521 Arrays.copyOfRange(mIsEphemeral, 0, 4)); 1522 1523 // Age out the fifth network 1524 for (int i = 0; i < WifiLastResortWatchdog.MAX_BSSID_AGE; i++) { 1525 mLastResortWatchdog.updateAvailableNetworks(candidates); 1526 } 1527 1528 //Increment failure counts 1529 for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { 1530 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1531 ssids[1], bssids[1], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 1532 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1533 ssids[2], bssids[2], WifiLastResortWatchdog.FAILURE_CODE_DHCP); 1534 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1535 ssids[3], bssids[3], WifiLastResortWatchdog.FAILURE_CODE_DHCP); 1536 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1537 ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1538 } 1539 1540 // Add network #5 back into the candidates 1541 candidates = createFilteredQnsCandidates(ssids, 1542 bssids, frequencies, caps, levels, isEphemeral, hasEverConnected); 1543 1544 // LastResortWatchdog should reactivate because there is a new network (#5) available, 1545 // Not because it was successful 1546 mLastResortWatchdog.updateAvailableNetworks(candidates); 1547 1548 // Simulate wifi connecting 1549 mLastResortWatchdog.connectedStateTransition(true); 1550 1551 // Verify that WifiMetrics did not count another success, as the connection could be due 1552 // to the newly available network #5 1553 verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogSuccesses(); 1554 verify(mWifiMetrics, times(1)).setWatchdogSuccessTimeDurationMs(eq(expectedDuration)); 1555 } 1556 1557 /** 1558 * Case 21: Test config updates where new config is null. 1559 * Create a scan result with an associated config and update the available networks list. 1560 * Repeat this with a second scan result where the config is null. 1561 * Expected behavior: The stored config should not be lost overwritten. 1562 */ 1563 @Test 1564 public void testUpdateNetworkWithNullConfig() { 1565 List<Pair<ScanDetail, WifiConfiguration>> candidates = 1566 new ArrayList<Pair<ScanDetail, WifiConfiguration>>(); 1567 String ssid = mSsids[0].replaceAll("^\"+", "").replaceAll("\"+$", ""); 1568 ScanDetail scanDetail = new ScanDetail(WifiSsid.createFromAsciiEncoded(ssid), 1569 mBssids[0], mCaps[0], mLevels[0], mFrequencies[0], System.currentTimeMillis(), 0); 1570 WifiConfiguration config = mock(WifiConfiguration.class); 1571 WifiConfiguration.NetworkSelectionStatus networkSelectionStatus = 1572 mock(WifiConfiguration.NetworkSelectionStatus.class); 1573 when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStatus); 1574 when(networkSelectionStatus.getHasEverConnected()) 1575 .thenReturn(true); 1576 candidates.add(Pair.create(scanDetail, config)); 1577 mLastResortWatchdog.updateAvailableNetworks(candidates); 1578 1579 candidates.clear(); 1580 1581 candidates.add(Pair.create(scanDetail, null)); 1582 mLastResortWatchdog.updateAvailableNetworks(candidates); 1583 1584 boolean watchdogTriggered = false; 1585 for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { 1586 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1587 mSsids[0], mBssids[0], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 1588 } 1589 assertEquals(true, watchdogTriggered); 1590 } 1591 1592 /** 1593 * Case 22: Test config updates where hasEverConnected goes from false to true. 1594 * Create a scan result with an associated config and update the available networks list. 1595 * Repeat this with a second scan result where the config value for hasEverConnected 1596 * is true. 1597 * Expected behavior: The stored config should not be lost overwritten. 1598 */ 1599 @Test 1600 public void testUpdateNetworkWithHasEverConnectedTrue() { 1601 List<Pair<ScanDetail, WifiConfiguration>> candidates = 1602 new ArrayList<Pair<ScanDetail, WifiConfiguration>>(); 1603 String ssid = mSsids[0].replaceAll("^\"+", "").replaceAll("\"+$", ""); 1604 ScanDetail scanDetail = new ScanDetail(WifiSsid.createFromAsciiEncoded(ssid), 1605 mBssids[0], mCaps[0], mLevels[0], mFrequencies[0], System.currentTimeMillis(), 0); 1606 WifiConfiguration configHasEverConnectedFalse = mock(WifiConfiguration.class); 1607 WifiConfiguration.NetworkSelectionStatus networkSelectionStatusFalse = 1608 mock(WifiConfiguration.NetworkSelectionStatus.class); 1609 when(configHasEverConnectedFalse.getNetworkSelectionStatus()) 1610 .thenReturn(networkSelectionStatusFalse); 1611 when(networkSelectionStatusFalse.getHasEverConnected()) 1612 .thenReturn(false); 1613 candidates.add(Pair.create(scanDetail, configHasEverConnectedFalse)); 1614 mLastResortWatchdog.updateAvailableNetworks(candidates); 1615 1616 boolean watchdogTriggered = false; 1617 for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { 1618 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1619 mSsids[0], mBssids[0], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 1620 } 1621 assertEquals(false, watchdogTriggered); 1622 1623 candidates.clear(); 1624 1625 WifiConfiguration configHasEverConnectedTrue = mock(WifiConfiguration.class); 1626 WifiConfiguration.NetworkSelectionStatus networkSelectionStatusTrue = 1627 mock(WifiConfiguration.NetworkSelectionStatus.class); 1628 when(configHasEverConnectedTrue.getNetworkSelectionStatus()) 1629 .thenReturn(networkSelectionStatusTrue); 1630 when(networkSelectionStatusTrue.getHasEverConnected()) 1631 .thenReturn(true); 1632 candidates.add(Pair.create(scanDetail, configHasEverConnectedTrue)); 1633 mLastResortWatchdog.updateAvailableNetworks(candidates); 1634 1635 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1636 mSsids[0], mBssids[0], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 1637 assertEquals(true, watchdogTriggered); 1638 } 1639 1640 /** 1641 * Case 23: Test config updates where hasEverConnected goes from true to false. 1642 * Create a scan result with an associated config and update the available networks list. 1643 * Repeat this with a second scan result where hasEverConnected is false. 1644 * Expected behavior: The stored config should not be lost overwritten. 1645 */ 1646 @Test 1647 public void testUpdateNetworkWithHasEverConnectedFalse() { 1648 List<Pair<ScanDetail, WifiConfiguration>> candidates = 1649 new ArrayList<Pair<ScanDetail, WifiConfiguration>>(); 1650 String ssid = mSsids[0].replaceAll("^\"+", "").replaceAll("\"+$", ""); 1651 ScanDetail scanDetail = new ScanDetail(WifiSsid.createFromAsciiEncoded(ssid), 1652 mBssids[0], mCaps[0], mLevels[0], mFrequencies[0], System.currentTimeMillis(), 0); 1653 1654 WifiConfiguration configHasEverConnectedTrue = mock(WifiConfiguration.class); 1655 WifiConfiguration.NetworkSelectionStatus networkSelectionStatusTrue = 1656 mock(WifiConfiguration.NetworkSelectionStatus.class); 1657 when(configHasEverConnectedTrue.getNetworkSelectionStatus()) 1658 .thenReturn(networkSelectionStatusTrue); 1659 when(networkSelectionStatusTrue.getHasEverConnected()) 1660 .thenReturn(true); 1661 candidates.add(Pair.create(scanDetail, configHasEverConnectedTrue)); 1662 mLastResortWatchdog.updateAvailableNetworks(candidates); 1663 1664 boolean watchdogTriggered = false; 1665 for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { 1666 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1667 mSsids[0], mBssids[0], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 1668 } 1669 assertEquals(true, watchdogTriggered); 1670 1671 candidates.clear(); 1672 1673 WifiConfiguration configHasEverConnectedFalse = mock(WifiConfiguration.class); 1674 WifiConfiguration.NetworkSelectionStatus networkSelectionStatusFalse = 1675 mock(WifiConfiguration.NetworkSelectionStatus.class); 1676 when(configHasEverConnectedFalse.getNetworkSelectionStatus()) 1677 .thenReturn(networkSelectionStatusFalse); 1678 when(networkSelectionStatusFalse.getHasEverConnected()) 1679 .thenReturn(false); 1680 candidates.add(Pair.create(scanDetail, configHasEverConnectedFalse)); 1681 mLastResortWatchdog.updateAvailableNetworks(candidates); 1682 1683 for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { 1684 watchdogTriggered = mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1685 mSsids[0], mBssids[0], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 1686 } 1687 assertEquals(false, watchdogTriggered); 1688 } 1689 1690 /** 1691 * Case 24: Check toString method for accurate hasEverConnected value in 1692 * AvailableNetworkFailureCount objects. 1693 * Create an AvailableNetworkFailureCount instance and check output of toString method. 1694 * Expected behavior: String contains HasEverConnected setting or null_config if there is not 1695 * an associated config. 1696 */ 1697 @Test 1698 public void testHasEverConnectedValueInAvailableNetworkFailureCountToString() { 1699 // Check with HasEverConnected true 1700 WifiConfiguration configHasEverConnectedTrue = mock(WifiConfiguration.class); 1701 WifiConfiguration.NetworkSelectionStatus networkSelectionStatusTrue = 1702 mock(WifiConfiguration.NetworkSelectionStatus.class); 1703 when(configHasEverConnectedTrue.getNetworkSelectionStatus()) 1704 .thenReturn(networkSelectionStatusTrue); 1705 when(networkSelectionStatusTrue.getHasEverConnected()).thenReturn(true); 1706 WifiLastResortWatchdog.AvailableNetworkFailureCount withConfigHECTrue = 1707 new WifiLastResortWatchdog.AvailableNetworkFailureCount(configHasEverConnectedTrue); 1708 String output = withConfigHECTrue.toString(); 1709 assertTrue(output.contains("HasEverConnected: true")); 1710 1711 // check with HasEverConnected false 1712 WifiConfiguration configHasEverConnectedFalse = mock(WifiConfiguration.class); 1713 WifiConfiguration.NetworkSelectionStatus networkSelectionStatusFalse = 1714 mock(WifiConfiguration.NetworkSelectionStatus.class); 1715 when(configHasEverConnectedFalse.getNetworkSelectionStatus()) 1716 .thenReturn(networkSelectionStatusFalse); 1717 when(networkSelectionStatusFalse.getHasEverConnected()).thenReturn(false); 1718 WifiLastResortWatchdog.AvailableNetworkFailureCount withConfigHECFalse = 1719 new WifiLastResortWatchdog.AvailableNetworkFailureCount( 1720 configHasEverConnectedFalse); 1721 output = withConfigHECFalse.toString(); 1722 assertTrue(output.contains("HasEverConnected: false")); 1723 1724 // Check with a null config 1725 WifiLastResortWatchdog.AvailableNetworkFailureCount withNullConfig = 1726 new WifiLastResortWatchdog.AvailableNetworkFailureCount(null); 1727 output = withNullConfig.toString(); 1728 assertTrue(output.contains("HasEverConnected: null_config")); 1729 } 1730 1731 /** 1732 * Test metrics incrementing connection failure count after watchdog has already been triggered 1733 */ 1734 @Test 1735 public void testIncrementingWatchdogConnectionFailuresAfterTrigger() { 1736 String[] ssids = {"\"test1\""}; 1737 String[] bssids = {"6c:f3:7f:ae:8c:f3"}; 1738 int[] frequencies = {2437}; 1739 String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; 1740 int[] levels = {-60}; 1741 boolean[] isEphemeral = {false}; 1742 boolean[] hasEverConnected = {true}; 1743 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(ssids, 1744 bssids, frequencies, caps, levels, isEphemeral, hasEverConnected); 1745 mLastResortWatchdog.updateAvailableNetworks(candidates); 1746 1747 // Ensure new networks have zero'ed failure counts 1748 for (int i = 0; i < ssids.length; i++) { 1749 assertFailureCountEquals(bssids[i], 0, 0, 0); 1750 } 1751 1752 //Increment failure counts 1753 for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { 1754 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1755 ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1756 } 1757 1758 // Verify relevant WifiMetrics calls were made once with appropriate arguments 1759 verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggers(); 1760 1761 // Verify that failure count after trigger is not incremented yet 1762 verify(mWifiMetrics, never()).incrementWatchdogTotalConnectionFailureCountAfterTrigger(); 1763 1764 // Fail 1 more time and verify this time it's counted 1765 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1766 ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1767 verify(mWifiMetrics, times(1)).incrementWatchdogTotalConnectionFailureCountAfterTrigger(); 1768 } 1769 1770 /** 1771 * Test that LRWD success is only declared when the first connection after restarting wifi 1772 * is successful. 1773 * 1774 * First tests the failure case: check success metric is not incremented when the first 1775 * connection is a failure. 1776 * Then test state transition and the success case: check success metric is incremented 1777 * when the first connection is a success. 1778 */ 1779 @Test 1780 public void testWatchdogAssumesSuccessOnlyIfFirstConnectionAfterRestartSucceeds() { 1781 String[] ssids = {"\"test1\""}; 1782 String[] bssids = {"6c:f3:7f:ae:8c:f3"}; 1783 int[] frequencies = {2437}; 1784 String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; 1785 int[] levels = {-60}; 1786 boolean[] isEphemeral = {false}; 1787 boolean[] hasEverConnected = {true}; 1788 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(ssids, 1789 bssids, frequencies, caps, levels, isEphemeral, hasEverConnected); 1790 mLastResortWatchdog.updateAvailableNetworks(candidates); 1791 1792 // Ensure new networks have zero'ed failure counts 1793 for (int i = 0; i < ssids.length; i++) { 1794 assertFailureCountEquals(bssids[i], 0, 0, 0); 1795 } 1796 1797 //Increment failure counts 1798 for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { 1799 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1800 ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1801 } 1802 1803 // Verify watchdog has triggered a restart 1804 verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggers(); 1805 1806 // Fail 1 more time and verify this time it's counted 1807 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1808 ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1809 1810 // Simulate wifi connecting after triggering 1811 mLastResortWatchdog.connectedStateTransition(true); 1812 // Verify takeBugReport is not called again 1813 mLooper.dispatchAll(); 1814 verify(mWifiStateMachine, never()).takeBugReport(anyString(), anyString()); 1815 verify(mWifiMetrics, never()).incrementNumLastResortWatchdogSuccesses(); 1816 1817 // Simulate wifi disconnecting 1818 mLastResortWatchdog.connectedStateTransition(false); 1819 1820 // Test another round, and this time successfully connect after restart trigger 1821 for (int i = 0; i < ssids.length; i++) { 1822 assertFailureCountEquals(bssids[i], 0, 0, 0); 1823 } 1824 for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { 1825 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1826 ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1827 } 1828 1829 // Verify watchdog has triggered a restart 1830 verify(mWifiMetrics, times(2)).incrementNumLastResortWatchdogTriggers(); 1831 // Simulate wifi connecting after triggering 1832 mLastResortWatchdog.connectedStateTransition(true); 1833 // Verify takeBugReport is not called again 1834 mLooper.dispatchAll(); 1835 verify(mWifiStateMachine, times(1)).takeBugReport(anyString(), anyString()); 1836 verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogSuccesses(); 1837 } 1838 1839 /** 1840 * If the user changes the configuration and then we have a successful connection, don't 1841 * trigger bugreport. 1842 * Tests this specific path: 1843 * 1. watchdog triggers restart 1844 * 2. wifi configuration changes 1845 * 3. wifi successfully connects immedietly after 1846 * Expected result: bugreport should not trigger 1847 */ 1848 @Test 1849 public void testWatchdogVerifiesAtLeastOneNetworkIsConnectedBeforeTriggeringBugreport() { 1850 String[] ssids = {"\"test1\""}; 1851 String[] bssids = {"6c:f3:7f:ae:8c:f3"}; 1852 int[] frequencies = {2437}; 1853 String[] caps = {"[WPA2-EAP-CCMP][ESS]"}; 1854 int[] levels = {-60}; 1855 boolean[] isEphemeral = {false}; 1856 boolean[] hasEverConnected = {true}; 1857 List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(ssids, 1858 bssids, frequencies, caps, levels, isEphemeral, hasEverConnected); 1859 mLastResortWatchdog.updateAvailableNetworks(candidates); 1860 1861 // Ensure new networks have zero'ed failure counts 1862 for (int i = 0; i < ssids.length; i++) { 1863 assertFailureCountEquals(bssids[i], 0, 0, 0); 1864 } 1865 1866 //Increment failure counts 1867 for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) { 1868 mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded( 1869 ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 1870 } 1871 1872 // Verify watchdog has triggered a restart 1873 verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggers(); 1874 1875 // Simulate user changing the configuration 1876 when(candidates.get(0).second.getNetworkSelectionStatus().getHasEverConnected()) 1877 .thenReturn(false); 1878 1879 mLastResortWatchdog.connectedStateTransition(true); 1880 // Verify takeBugReport is not called again 1881 mLooper.dispatchAll(); 1882 verify(mWifiStateMachine, never()).takeBugReport(anyString(), anyString()); 1883 verify(mWifiMetrics, never()).incrementNumLastResortWatchdogSuccesses(); 1884 } 1885 } 1886