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