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