1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wifi; 18 19 import static com.android.server.wifi.DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT; 20 import static com.android.server.wifi.WifiHealthMonitor.REASON_ASSOC_REJECTION; 21 import static com.android.server.wifi.WifiHealthMonitor.REASON_ASSOC_TIMEOUT; 22 import static com.android.server.wifi.WifiHealthMonitor.REASON_AUTH_FAILURE; 23 import static com.android.server.wifi.WifiHealthMonitor.REASON_CONNECTION_FAILURE; 24 import static com.android.server.wifi.WifiHealthMonitor.REASON_DISCONNECTION_NONLOCAL; 25 import static com.android.server.wifi.WifiHealthMonitor.REASON_SHORT_CONNECTION_NONLOCAL; 26 import static com.android.server.wifi.WifiScoreCard.BANDWIDTH_STATS_COUNT_THR; 27 import static com.android.server.wifi.WifiScoreCard.CNT_ASSOCIATION_REJECTION; 28 import static com.android.server.wifi.WifiScoreCard.CNT_ASSOCIATION_TIMEOUT; 29 import static com.android.server.wifi.WifiScoreCard.CNT_AUTHENTICATION_FAILURE; 30 import static com.android.server.wifi.WifiScoreCard.CNT_CONNECTION_ATTEMPT; 31 import static com.android.server.wifi.WifiScoreCard.CNT_CONNECTION_DURATION_SEC; 32 import static com.android.server.wifi.WifiScoreCard.CNT_CONNECTION_FAILURE; 33 import static com.android.server.wifi.WifiScoreCard.CNT_CONSECUTIVE_CONNECTION_FAILURE; 34 import static com.android.server.wifi.WifiScoreCard.CNT_CONSECUTIVE_WRONG_PASSWORD_FAILURE; 35 import static com.android.server.wifi.WifiScoreCard.CNT_DISCONNECTION_NONLOCAL; 36 import static com.android.server.wifi.WifiScoreCard.CNT_DISCONNECTION_NONLOCAL_CONNECTING; 37 import static com.android.server.wifi.WifiScoreCard.CNT_SHORT_CONNECTION_NONLOCAL; 38 import static com.android.server.wifi.WifiScoreCard.LINK_BANDWIDTH_INIT_KBPS; 39 import static com.android.server.wifi.WifiScoreCard.LINK_RX; 40 import static com.android.server.wifi.WifiScoreCard.LINK_TX; 41 import static com.android.server.wifi.util.NativeUtil.hexStringFromByteArray; 42 43 import static org.junit.Assert.*; 44 import static org.mockito.Mockito.*; 45 46 import android.content.Context; 47 import android.content.res.Resources; 48 import android.net.MacAddress; 49 import android.net.wifi.SupplicantState; 50 import android.net.wifi.WifiInfo; 51 import android.net.wifi.WifiSsid; 52 import android.util.Base64; 53 import android.util.Pair; 54 55 import androidx.test.filters.SmallTest; 56 57 import com.android.server.wifi.WifiHealthMonitor.FailureStats; 58 import com.android.server.wifi.WifiScoreCard.NetworkConnectionStats; 59 import com.android.server.wifi.WifiScoreCard.PerNetwork; 60 import com.android.server.wifi.proto.WifiScoreCardProto.AccessPoint; 61 import com.android.server.wifi.proto.WifiScoreCardProto.BandwidthStatsAll; 62 import com.android.server.wifi.proto.WifiScoreCardProto.ConnectionStats; 63 import com.android.server.wifi.proto.WifiScoreCardProto.Event; 64 import com.android.server.wifi.proto.WifiScoreCardProto.Network; 65 import com.android.server.wifi.proto.WifiScoreCardProto.NetworkList; 66 import com.android.server.wifi.proto.WifiScoreCardProto.NetworkStats; 67 import com.android.server.wifi.proto.WifiScoreCardProto.Signal; 68 import com.android.server.wifi.proto.nano.WifiMetricsProto.BandwidthEstimatorStats; 69 import com.android.server.wifi.util.IntHistogram; 70 import com.android.server.wifi.util.RssiUtil; 71 import com.android.wifi.resources.R; 72 73 import org.junit.Before; 74 import org.junit.Test; 75 import org.mockito.Mock; 76 import org.mockito.MockitoAnnotations; 77 78 import java.util.ArrayList; 79 import java.util.Arrays; 80 import java.util.List; 81 82 /** 83 * Unit tests for {@link com.android.server.wifi.WifiScoreCard}. 84 */ 85 @SmallTest 86 public class WifiScoreCardTest extends WifiBaseTest { 87 88 static final WifiSsid TEST_SSID_1 = WifiSsid.fromUtf8Text("Joe's Place"); 89 static final WifiSsid TEST_SSID_2 = WifiSsid.fromUtf8Text("Poe's Ravn"); 90 91 static final MacAddress TEST_BSSID_1 = MacAddress.fromString("aa:bb:cc:dd:ee:ff"); 92 static final MacAddress TEST_BSSID_2 = MacAddress.fromString("1:2:3:4:5:6"); 93 94 static final int TEST_NETWORK_AGENT_ID = 123; 95 static final int TEST_NETWORK_CONFIG_ID = 1492; 96 97 static final double TOL = 1e-6; // for assertEquals(double, double, tolerance) 98 99 static final int TEST_BSSID_FAILURE_REASON = 100 WifiBlocklistMonitor.REASON_ASSOCIATION_REJECTION; 101 102 private static final String WIFI_IFACE_NAME = "wlanTest"; 103 104 WifiScoreCard mWifiScoreCard; 105 106 @Mock Clock mClock; 107 @Mock WifiScoreCard.MemoryStore mMemoryStore; 108 @Mock DeviceConfigFacade mDeviceConfigFacade; 109 @Mock Context mContext; 110 @Mock Resources mResources; 111 @Mock WifiGlobals mWifiGlobals; 112 113 private WifiLinkLayerStats mOldLlStats; 114 private WifiLinkLayerStats mNewLlStats; 115 private long mTotalTxBytes; 116 private long mTotalRxBytes; 117 118 final ArrayList<String> mKeys = new ArrayList<>(); 119 final ArrayList<WifiScoreCard.BlobListener> mBlobListeners = new ArrayList<>(); 120 final ArrayList<byte[]> mBlobs = new ArrayList<>(); 121 122 long mMilliSecondsSinceBoot; 123 ExtendedWifiInfo mWifiInfo; 124 millisecondsPass(long ms)125 void millisecondsPass(long ms) { 126 mMilliSecondsSinceBoot += ms; 127 when(mClock.getElapsedSinceBootMillis()).thenReturn(mMilliSecondsSinceBoot); 128 } 129 secondsPass(long s)130 void secondsPass(long s) { 131 millisecondsPass(s * 1000); 132 } 133 134 /** 135 * Sets up for unit test 136 */ 137 @Before setUp()138 public void setUp() throws Exception { 139 MockitoAnnotations.initMocks(this); 140 mKeys.clear(); 141 mBlobListeners.clear(); 142 mBlobs.clear(); 143 mMilliSecondsSinceBoot = 0; 144 mWifiInfo = new ExtendedWifiInfo(mock(WifiGlobals.class), WIFI_IFACE_NAME); 145 mWifiInfo.setSSID(TEST_SSID_1); 146 mWifiInfo.setBSSID(TEST_BSSID_1.toString()); 147 mWifiInfo.setNetworkId(TEST_NETWORK_CONFIG_ID); 148 mWifiInfo.setTxLinkSpeedMbps(866); 149 mWifiInfo.setRxLinkSpeedMbps(866); 150 mWifiInfo.setMaxSupportedTxLinkSpeedMbps(866); 151 mWifiInfo.setMaxSupportedRxLinkSpeedMbps(866); 152 millisecondsPass(0); 153 mWifiScoreCard = new WifiScoreCard(mClock, "some seed", mDeviceConfigFacade, 154 mContext, mWifiGlobals); 155 mWifiScoreCard.mPersistentHistograms = true; // TODO - remove when ready 156 when(mDeviceConfigFacade.getConnectionFailureHighThrPercent()).thenReturn( 157 DeviceConfigFacade.DEFAULT_CONNECTION_FAILURE_HIGH_THR_PERCENT); 158 when(mDeviceConfigFacade.getConnectionFailureCountMin()).thenReturn( 159 DeviceConfigFacade.DEFAULT_CONNECTION_FAILURE_COUNT_MIN); 160 when(mDeviceConfigFacade.getConnectionFailureDisconnectionHighThrPercent()).thenReturn( 161 DeviceConfigFacade.DEFAULT_CONNECTION_FAILURE_DISCONNECTION_HIGH_THR_PERCENT); 162 when(mDeviceConfigFacade.getConnectionFailureDisconnectionCountMin()).thenReturn( 163 DeviceConfigFacade.DEFAULT_CONNECTION_FAILURE_DISCONNECTION_COUNT_MIN); 164 when(mDeviceConfigFacade.getAssocRejectionHighThrPercent()).thenReturn( 165 DeviceConfigFacade.DEFAULT_ASSOC_REJECTION_HIGH_THR_PERCENT); 166 when(mDeviceConfigFacade.getAssocRejectionCountMin()).thenReturn( 167 DeviceConfigFacade.DEFAULT_ASSOC_REJECTION_COUNT_MIN); 168 when(mDeviceConfigFacade.getAssocTimeoutHighThrPercent()).thenReturn( 169 DeviceConfigFacade.DEFAULT_ASSOC_TIMEOUT_HIGH_THR_PERCENT); 170 when(mDeviceConfigFacade.getAssocTimeoutCountMin()).thenReturn( 171 DeviceConfigFacade.DEFAULT_ASSOC_TIMEOUT_COUNT_MIN); 172 when(mDeviceConfigFacade.getAuthFailureHighThrPercent()).thenReturn( 173 DeviceConfigFacade.DEFAULT_AUTH_FAILURE_HIGH_THR_PERCENT); 174 when(mDeviceConfigFacade.getAuthFailureCountMin()).thenReturn( 175 DeviceConfigFacade.DEFAULT_AUTH_FAILURE_COUNT_MIN); 176 when(mDeviceConfigFacade.getShortConnectionNonlocalHighThrPercent()).thenReturn( 177 DeviceConfigFacade.DEFAULT_SHORT_CONNECTION_NONLOCAL_HIGH_THR_PERCENT); 178 when(mDeviceConfigFacade.getShortConnectionNonlocalCountMin()).thenReturn( 179 DeviceConfigFacade.DEFAULT_SHORT_CONNECTION_NONLOCAL_COUNT_MIN); 180 when(mDeviceConfigFacade.getDisconnectionNonlocalHighThrPercent()).thenReturn( 181 DeviceConfigFacade.DEFAULT_DISCONNECTION_NONLOCAL_HIGH_THR_PERCENT); 182 when(mDeviceConfigFacade.getDisconnectionNonlocalCountMin()).thenReturn( 183 DeviceConfigFacade.DEFAULT_DISCONNECTION_NONLOCAL_COUNT_MIN); 184 when(mDeviceConfigFacade.getHealthMonitorMinRssiThrDbm()).thenReturn( 185 DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_MIN_RSSI_THR_DBM); 186 when(mDeviceConfigFacade.getHealthMonitorRatioThrNumerator()).thenReturn( 187 DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_RATIO_THR_NUMERATOR); 188 when(mDeviceConfigFacade.getHealthMonitorMinNumConnectionAttempt()).thenReturn( 189 DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT); 190 when(mDeviceConfigFacade.getHealthMonitorShortConnectionDurationThrMs()).thenReturn( 191 DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_SHORT_CONNECTION_DURATION_THR_MS); 192 when(mDeviceConfigFacade.getAbnormalDisconnectionReasonCodeMask()).thenReturn( 193 DeviceConfigFacade.DEFAULT_ABNORMAL_DISCONNECTION_REASON_CODE_MASK); 194 when(mDeviceConfigFacade.getHealthMonitorRssiPollValidTimeMs()).thenReturn(3000); 195 // Disable FW alert time check by default 196 when(mDeviceConfigFacade.getHealthMonitorFwAlertValidTimeMs()).thenReturn(-1); 197 when(mDeviceConfigFacade.getBugReportThresholdExtraRatio()).thenReturn(1); 198 when(mDeviceConfigFacade.getBandwidthEstimatorLargeTimeConstantSec()).thenReturn(6); 199 when(mDeviceConfigFacade.getTrafficStatsThresholdMaxKbyte()).thenReturn(4000); 200 mWifiScoreCard.enableVerboseLogging(true); 201 when(mContext.getResources()).thenReturn(mResources); 202 when(mResources.getIntArray(R.array.config_wifiRssiLevelThresholds)) 203 .thenReturn(new int[]{-88, -77, -66, -55}); 204 when(mWifiGlobals.getPollRssiIntervalMillis()).thenReturn(3000); 205 mOldLlStats = new WifiLinkLayerStats(); 206 mNewLlStats = new WifiLinkLayerStats(); 207 mTotalTxBytes = 0; 208 mTotalRxBytes = 0; 209 } 210 211 /** 212 * Test generic update 213 */ 214 @Test testUpdate()215 public void testUpdate() throws Exception { 216 mWifiInfo.setSSID(TEST_SSID_1); 217 mWifiInfo.setBSSID(TEST_BSSID_1.toString()); 218 219 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 220 221 WifiScoreCard.PerBssid perBssid = mWifiScoreCard.fetchByBssid(TEST_BSSID_1); 222 assertTrue(perBssid.id > 0); 223 assertNotNull(perBssid.getL2Key()); 224 assertTrue("L2Key length should be more than 16.", perBssid.getL2Key().length() > 16); 225 226 mWifiInfo.setBSSID(TEST_BSSID_2.toString()); 227 228 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 229 230 assertEquals(perBssid, mWifiScoreCard.fetchByBssid(TEST_BSSID_1)); 231 assertNotEquals(perBssid.id, mWifiScoreCard.fetchByBssid(TEST_BSSID_2).id); 232 assertNotEquals(perBssid.getL2Key(), mWifiScoreCard.fetchByBssid(TEST_BSSID_2).getL2Key()); 233 } 234 235 /** 236 * Test the get, increment, and removal of Bssid blocklist streak counts. 237 */ 238 @Test testBssidBlocklistStreakOperations()239 public void testBssidBlocklistStreakOperations() { 240 mWifiInfo.setSSID(TEST_SSID_1); 241 mWifiInfo.setBSSID(TEST_BSSID_1.toString()); 242 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 243 244 String ssid = mWifiInfo.getSSID(); 245 String bssid = mWifiInfo.getBSSID(); 246 assertEquals(0, mWifiScoreCard.getBssidBlocklistStreak( 247 ssid, bssid, TEST_BSSID_FAILURE_REASON)); 248 for (int i = 1; i < 3; i++) { 249 assertEquals(i, mWifiScoreCard.incrementBssidBlocklistStreak( 250 ssid, bssid, TEST_BSSID_FAILURE_REASON)); 251 assertEquals(i, mWifiScoreCard.getBssidBlocklistStreak( 252 ssid, bssid, TEST_BSSID_FAILURE_REASON)); 253 } 254 mWifiScoreCard.resetBssidBlocklistStreak(ssid, bssid, TEST_BSSID_FAILURE_REASON); 255 assertEquals(0, mWifiScoreCard.getBssidBlocklistStreak( 256 ssid, bssid, TEST_BSSID_FAILURE_REASON)); 257 } 258 259 /** 260 * Test clearing the blocklist streak for all APs belonging to a SSID. 261 */ 262 @Test testClearBssidBlocklistStreakForSsid()263 public void testClearBssidBlocklistStreakForSsid() { 264 // Increment and verify the blocklist streak for SSID_1, BSSID_1 265 mWifiInfo.setSSID(TEST_SSID_1); 266 mWifiInfo.setBSSID(TEST_BSSID_1.toString()); 267 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 268 for (int i = 1; i < 3; i++) { 269 assertEquals(i, mWifiScoreCard.incrementBssidBlocklistStreak( 270 mWifiInfo.getSSID(), mWifiInfo.getBSSID(), TEST_BSSID_FAILURE_REASON)); 271 assertEquals(i, mWifiScoreCard.getBssidBlocklistStreak( 272 mWifiInfo.getSSID(), mWifiInfo.getBSSID(), TEST_BSSID_FAILURE_REASON)); 273 } 274 275 // Increment and verify the blocklist streak for SSID_2, BSSID_2 276 mWifiInfo.setSSID(TEST_SSID_2); 277 mWifiInfo.setBSSID(TEST_BSSID_2.toString()); 278 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 279 for (int i = 1; i < 3; i++) { 280 assertEquals(i, mWifiScoreCard.incrementBssidBlocklistStreak( 281 mWifiInfo.getSSID(), mWifiInfo.getBSSID(), TEST_BSSID_FAILURE_REASON)); 282 assertEquals(i, mWifiScoreCard.getBssidBlocklistStreak( 283 mWifiInfo.getSSID(), mWifiInfo.getBSSID(), TEST_BSSID_FAILURE_REASON)); 284 } 285 286 // Clear the blocklist streak for SSID_2 287 mWifiScoreCard.resetBssidBlocklistStreakForSsid(mWifiInfo.getSSID()); 288 // Verify that the blocklist streak for SSID_2 is cleared. 289 assertEquals(0, mWifiScoreCard.getBssidBlocklistStreak( 290 mWifiInfo.getSSID(), mWifiInfo.getBSSID(), TEST_BSSID_FAILURE_REASON)); 291 292 // verify that the blocklist streak for SSID_1 is not cleared. 293 mWifiInfo.setSSID(TEST_SSID_1); 294 mWifiInfo.setBSSID(TEST_BSSID_1.toString()); 295 assertEquals(2, mWifiScoreCard.getBssidBlocklistStreak( 296 mWifiInfo.getSSID(), mWifiInfo.getBSSID(), TEST_BSSID_FAILURE_REASON)); 297 } 298 299 /** 300 * Test the update and retrieval of the last connection time to a BSSID. 301 */ 302 @Test testSetBssidConnectionTimestampMs()303 public void testSetBssidConnectionTimestampMs() { 304 mWifiInfo.setSSID(TEST_SSID_1); 305 mWifiInfo.setBSSID(TEST_BSSID_1.toString()); 306 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 307 308 String ssid = mWifiInfo.getSSID(); 309 String bssid = mWifiInfo.getBSSID(); 310 assertEquals(0L, mWifiScoreCard.getBssidConnectionTimestampMs(ssid, bssid)); 311 assertEquals(0L, mWifiScoreCard.setBssidConnectionTimestampMs(ssid, bssid, 100L)); 312 assertEquals(100L, mWifiScoreCard.getBssidConnectionTimestampMs(ssid, bssid)); 313 } 314 315 /** 316 * Test identifiers. 317 */ 318 @Test testIdentifiers()319 public void testIdentifiers() throws Exception { 320 mWifiInfo.setSSID(TEST_SSID_1); 321 mWifiInfo.setBSSID(TEST_BSSID_1.toString()); 322 Pair<String, String> p1 = mWifiScoreCard.getL2KeyAndGroupHint(mWifiInfo); 323 assertNotNull(p1.first); 324 assertNotNull(p1.second); 325 mWifiInfo.setBSSID(TEST_BSSID_2.toString()); 326 Pair<String, String> p2 = mWifiScoreCard.getL2KeyAndGroupHint(mWifiInfo); 327 assertNotEquals(p1.first, p2.first); 328 assertEquals(p1.second, p2.second); 329 mWifiInfo.setBSSID(null); 330 Pair<String, String> p3 = mWifiScoreCard.getL2KeyAndGroupHint(mWifiInfo); 331 assertNull(p3.first); 332 assertNull(p3.second); 333 mWifiInfo.setBSSID("02:00:00:00:00:00"); 334 Pair<String, String> p4 = mWifiScoreCard.getL2KeyAndGroupHint(mWifiInfo); 335 assertNull(p4.first); 336 assertNull(p4.second); 337 } 338 339 /** 340 * Test rssi poll updates 341 */ 342 @Test testRssiPollUpdates()343 public void testRssiPollUpdates() throws Exception { 344 // Start out on one frequency 345 mWifiInfo.setFrequency(5805); 346 mWifiInfo.setRssi(-77); 347 mWifiInfo.setLinkSpeed(12); 348 mWifiScoreCard.noteSignalPoll(mWifiInfo); 349 // Switch channels for a bit 350 mWifiInfo.setFrequency(5290); 351 mWifiInfo.setRssi(-66); 352 mWifiInfo.setLinkSpeed(666); 353 mWifiScoreCard.noteSignalPoll(mWifiInfo); 354 // Back to the first channel 355 mWifiInfo.setFrequency(5805); 356 mWifiInfo.setRssi(-55); 357 mWifiInfo.setLinkSpeed(86); 358 mWifiScoreCard.noteSignalPoll(mWifiInfo); 359 360 double expectSum = -77 + -55; 361 double expectSumSq = 77 * 77 + 55 * 55; 362 363 // Now verify 364 WifiScoreCard.PerBssid perBssid = mWifiScoreCard.fetchByBssid(TEST_BSSID_1); 365 // Looking up the same thing twice should yield the same object. 366 assertTrue(perBssid.lookupSignal(Event.SIGNAL_POLL, 5805) 367 == perBssid.lookupSignal(Event.SIGNAL_POLL, 5805)); 368 // Check the rssi statistics for the first channel 369 assertEquals(2, perBssid.lookupSignal(Event.SIGNAL_POLL, 5805).rssi.count); 370 assertEquals(expectSum, perBssid.lookupSignal(Event.SIGNAL_POLL, 5805) 371 .rssi.sum, TOL); 372 assertEquals(expectSumSq, perBssid.lookupSignal(Event.SIGNAL_POLL, 5805) 373 .rssi.sumOfSquares, TOL); 374 assertEquals(-77.0, perBssid.lookupSignal(Event.SIGNAL_POLL, 5805) 375 .rssi.minValue, TOL); 376 assertEquals(-55.0, perBssid.lookupSignal(Event.SIGNAL_POLL, 5805) 377 .rssi.maxValue, TOL); 378 // Check the rssi statistics for the second channel 379 assertEquals(1, perBssid.lookupSignal(Event.SIGNAL_POLL, 5290).rssi.count); 380 // Check that the linkspeed was updated 381 assertEquals(666.0, perBssid.lookupSignal(Event.SIGNAL_POLL, 5290).linkspeed.sum, TOL); 382 } 383 384 /** 385 * Statistics on time-to-connect, connection duration 386 */ 387 @Test testDurationStatistics()388 public void testDurationStatistics() throws Exception { 389 // Start out disconnected; start connecting 390 mWifiInfo.setBSSID(android.net.wifi.WifiInfo.DEFAULT_MAC_ADDRESS); 391 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 392 // First poll has a bad RSSI 393 millisecondsPass(111); 394 mWifiInfo.setBSSID(TEST_BSSID_1.toString()); 395 mWifiInfo.setFrequency(5805); 396 mWifiInfo.setRssi(WifiInfo.INVALID_RSSI); 397 // A bit later, connection is complete (up through DHCP) 398 millisecondsPass(222); 399 mWifiInfo.setRssi(-55); 400 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 401 millisecondsPass(666); 402 // Rssi polls for 99 seconds 403 for (int i = 0; i < 99; i += 3) { 404 mWifiScoreCard.noteSignalPoll(mWifiInfo); 405 secondsPass(3); 406 } 407 // Make sure our simulated time adds up 408 assertEquals(mMilliSecondsSinceBoot, 99999); 409 // Validation success, rather late! 410 mWifiScoreCard.noteValidationSuccess(mWifiInfo); 411 // A long while later, wifi is toggled off 412 secondsPass(9900); 413 // Second validation success should not matter. 414 mWifiScoreCard.noteValidationSuccess(mWifiInfo); 415 mWifiInfo.setRssi(-88); 416 mWifiScoreCard.noteIpReachabilityLost(mWifiInfo); 417 mWifiScoreCard.noteWifiDisabled(mWifiInfo); 418 419 // Now verify 420 WifiScoreCard.PerBssid perBssid = mWifiScoreCard.fetchByBssid(TEST_BSSID_1); 421 assertEquals(1, perBssid.lookupSignal(Event.IP_CONFIGURATION_SUCCESS, 5805) 422 .elapsedMs.count); 423 assertEquals(333.0, perBssid.lookupSignal(Event.IP_CONFIGURATION_SUCCESS, 5805) 424 .elapsedMs.sum, TOL); 425 assertEquals(9999999.0, perBssid.lookupSignal(Event.WIFI_DISABLED, 5805) 426 .elapsedMs.maxValue, TOL); 427 assertEquals(999.0, perBssid.lookupSignal(Event.FIRST_POLL_AFTER_CONNECTION, 5805) 428 .elapsedMs.minValue, TOL); 429 assertEquals(99999.0, perBssid.lookupSignal(Event.VALIDATION_SUCCESS, 5805) 430 .elapsedMs.sum, TOL); 431 assertEquals(-88.0, perBssid.lookupSignal(Event.IP_REACHABILITY_LOST, 5805) 432 .rssi.sum, TOL); 433 assertNull(perBssid.lookupSignal(Event.SIGNAL_POLL, 5805).elapsedMs); 434 } 435 436 /** 437 * Firmware roam 438 */ 439 @Test testFirmwareRoam()440 public void testFirmwareRoam() throws Exception { 441 // Start out disconnected; start connecting 442 mWifiInfo.setBSSID(android.net.wifi.WifiInfo.DEFAULT_MAC_ADDRESS); 443 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 444 445 // First poll has a bad RSSI 446 millisecondsPass(111); 447 mWifiInfo.setBSSID(TEST_BSSID_1.toString()); 448 mWifiInfo.setSupplicantState(SupplicantState.COMPLETED); 449 mWifiInfo.setFrequency(5805); 450 mWifiInfo.setRssi(WifiInfo.INVALID_RSSI); 451 452 // A bit later, connection is complete (up through DHCP) 453 millisecondsPass(222); 454 mWifiInfo.setRssi(-55); 455 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 456 457 millisecondsPass(666); 458 mWifiInfo.setRssi(-77); 459 // Rssi polls for 99 seconds 460 for (int i = 0; i < 99; i += 9) { 461 mWifiScoreCard.noteSignalPoll(mWifiInfo); 462 secondsPass(9); 463 } 464 465 // Make sure our simulated time adds up 466 assertEquals(mMilliSecondsSinceBoot, 99999); 467 // Validation success, rather late! 468 mWifiScoreCard.noteValidationSuccess(mWifiInfo); 469 // Simulate a successful roam 470 mWifiScoreCard.noteSupplicantStateChanging(mWifiInfo, SupplicantState.COMPLETED); 471 millisecondsPass(1); 472 mWifiInfo.setBSSID(TEST_BSSID_2.toString()); 473 mWifiInfo.setRssi(-66); 474 mWifiInfo.setFrequency(2412); 475 mWifiInfo.setSupplicantState(SupplicantState.COMPLETED); 476 mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo); 477 secondsPass(9); 478 assertEquals(mMilliSecondsSinceBoot, 109000); 479 mWifiScoreCard.noteSignalPoll(mWifiInfo); 480 481 // Simulate an unsuccessful roam 482 secondsPass(1); 483 mWifiInfo.setRssi(-74); 484 mWifiScoreCard.noteSignalPoll(mWifiInfo); 485 secondsPass(1); 486 mWifiScoreCard.noteSupplicantStateChanging(mWifiInfo, SupplicantState.COMPLETED); 487 mWifiInfo.setBSSID(TEST_BSSID_1.toString()); 488 mWifiInfo.setFrequency(5805); 489 mWifiInfo.setSupplicantState(SupplicantState.COMPLETED); 490 mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo); 491 secondsPass(3); 492 mWifiScoreCard.noteIpReachabilityLost(mWifiInfo); 493 494 // Now verify 495 WifiScoreCard.PerBssid perBssid = mWifiScoreCard.fetchByBssid(TEST_BSSID_1); 496 assertEquals(1, perBssid.lookupSignal(Event.IP_CONFIGURATION_SUCCESS, 5805) 497 .elapsedMs.count); 498 assertEquals(-77, perBssid.lookupSignal(Event.LAST_POLL_BEFORE_ROAM, 5805) 499 .rssi.minValue, TOL); 500 assertEquals(1, perBssid.lookupSignal(Event.ROAM_FAILURE, 5805) 501 .rssi.count); 502 503 assertEquals(67, perBssid.estimatePercentInternetAvailability()); 504 505 perBssid = mWifiScoreCard.fetchByBssid(TEST_BSSID_2); 506 assertEquals(-66.0, perBssid.lookupSignal(Event.ROAM_SUCCESS, 2412) 507 .rssi.sum, TOL); 508 assertEquals(50, perBssid.estimatePercentInternetAvailability()); 509 } 510 511 /** 512 * Constructs a protobuf form of AccessPoint example. 513 */ makeSerializedAccessPointExample()514 private byte[] makeSerializedAccessPointExample() { 515 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 516 PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); 517 millisecondsPass(10); 518 // Association completes, a NetworkAgent is created 519 mWifiScoreCard.noteNetworkAgentCreated(mWifiInfo, TEST_NETWORK_AGENT_ID); 520 millisecondsPass(101); 521 mWifiInfo.setRssi(-55); 522 mWifiInfo.setFrequency(5805); 523 mWifiInfo.setLinkSpeed(384); 524 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 525 perNetwork.addFrequency(mWifiInfo.getFrequency()); 526 millisecondsPass(888); 527 mWifiScoreCard.noteSignalPoll(mWifiInfo); 528 millisecondsPass(1000); 529 mWifiInfo.setRssi(-44); 530 mWifiScoreCard.noteSignalPoll(mWifiInfo); 531 mWifiInfo.setFrequency(2432); 532 perNetwork.addFrequency(mWifiInfo.getFrequency()); 533 for (int round = 0; round < 4; round++) { 534 for (int i = 0; i < HISTOGRAM_COUNT.length; i++) { 535 if (HISTOGRAM_COUNT[i] > round) { 536 mWifiInfo.setRssi(HISTOGRAM_RSSI[i]); 537 mWifiScoreCard.noteSignalPoll(mWifiInfo); 538 } 539 } 540 } 541 makeUpdateLinkBandwidthExample(); 542 mWifiScoreCard.resetAllConnectionStates(); 543 544 WifiScoreCard.PerBssid perBssid = mWifiScoreCard.fetchByBssid(TEST_BSSID_1); 545 perBssid.lookupSignal(Event.SIGNAL_POLL, 2412).rssi.historicalMean = -42.0; 546 perBssid.lookupSignal(Event.SIGNAL_POLL, 2412).rssi.historicalVariance = 4.0; 547 checkSerializationBssidExample("before serialization", perBssid); 548 // Now convert to protobuf form 549 byte[] serialized = perBssid.toAccessPoint().toByteArray(); 550 return serialized; 551 } 552 private static final int[] HISTOGRAM_RSSI = {-80, -79, -78}; 553 private static final int[] HISTOGRAM_COUNT = {3, 1, 4}; 554 checkHistogramExample(String diag, IntHistogram rssiHistogram)555 private void checkHistogramExample(String diag, IntHistogram rssiHistogram) { 556 int i = 0; 557 for (IntHistogram.Bucket bucket : rssiHistogram) { 558 if (bucket.count != 0) { 559 assertTrue(diag, i < HISTOGRAM_COUNT.length); 560 assertEquals(diag, HISTOGRAM_RSSI[i], bucket.start); 561 assertEquals(diag, HISTOGRAM_COUNT[i], bucket.count); 562 i++; 563 } 564 } 565 assertEquals(diag, HISTOGRAM_COUNT.length, i); 566 } 567 568 /** 569 * Checks that the fields of the bssid serialization example are as expected 570 */ checkSerializationBssidExample(String diag, WifiScoreCard.PerBssid perBssid)571 private void checkSerializationBssidExample(String diag, WifiScoreCard.PerBssid perBssid) { 572 assertEquals(diag, 2, perBssid.lookupSignal(Event.SIGNAL_POLL, 5805).rssi.count); 573 assertEquals(diag, -55.0, perBssid.lookupSignal(Event.SIGNAL_POLL, 5805) 574 .rssi.minValue, TOL); 575 assertEquals(diag, -44.0, perBssid.lookupSignal(Event.SIGNAL_POLL, 5805) 576 .rssi.maxValue, TOL); 577 assertEquals(diag, 384.0, perBssid.lookupSignal(Event.FIRST_POLL_AFTER_CONNECTION, 5805) 578 .linkspeed.sum, TOL); 579 assertEquals(diag, 111.0, perBssid.lookupSignal(Event.IP_CONFIGURATION_SUCCESS, 5805) 580 .elapsedMs.minValue, TOL); 581 assertEquals(diag, 0, perBssid.lookupSignal(Event.SIGNAL_POLL, 2412).rssi.count); 582 assertEquals(diag, -42.0, perBssid.lookupSignal(Event.SIGNAL_POLL, 2412) 583 .rssi.historicalMean, TOL); 584 assertEquals(diag, 4.0, perBssid.lookupSignal(Event.SIGNAL_POLL, 2412) 585 .rssi.historicalVariance, TOL); 586 checkHistogramExample(diag, perBssid.lookupSignal(Event.SIGNAL_POLL, 587 2432).rssi.intHistogram); 588 } 589 590 /** 591 * Checks that the fields of the network are as expected with bssid serialization example 592 */ checkSerializationBssidExample(String diag, PerNetwork perNetwork)593 private void checkSerializationBssidExample(String diag, PerNetwork perNetwork) { 594 NetworkConnectionStats dailyStats = perNetwork.getRecentStats(); 595 assertEquals(diag, 1, dailyStats.getCount(CNT_CONNECTION_ATTEMPT)); 596 assertEquals(diag, 0, dailyStats.getCount(CNT_CONNECTION_FAILURE)); 597 assertEquals(diag, 1, dailyStats.getCount(CNT_CONNECTION_DURATION_SEC)); 598 assertEquals(diag, 0, dailyStats.getCount(CNT_SHORT_CONNECTION_NONLOCAL)); 599 assertEquals(diag, 0, dailyStats.getCount(CNT_DISCONNECTION_NONLOCAL)); 600 assertEquals(diag, 0, dailyStats.getCount(CNT_ASSOCIATION_REJECTION)); 601 assertEquals(diag, 0, dailyStats.getCount(CNT_ASSOCIATION_TIMEOUT)); 602 assertEquals(diag, 0, dailyStats.getCount(CNT_AUTHENTICATION_FAILURE)); 603 assertEquals(diag, 0, dailyStats.getCount(CNT_CONSECUTIVE_WRONG_PASSWORD_FAILURE)); 604 List<Integer> frequencies = perNetwork.getFrequencies(Long.MAX_VALUE); 605 assertEquals(diag, 2, frequencies.size()); 606 List<Integer> expectedFrequencies = new ArrayList<>(Arrays.asList(2432, 5805)); 607 assertEquals(diag, expectedFrequencies, frequencies); 608 } 609 610 /** 611 * AccessPoint serialization 612 */ 613 @Test testAccessPointSerialization()614 public void testAccessPointSerialization() throws Exception { 615 byte[] serialized = makeSerializedAccessPointExample(); 616 617 // Verify by parsing it and checking that we see the expected results 618 AccessPoint ap = AccessPoint.parseFrom(serialized); 619 assertEquals(5, ap.getEventStatsCount()); 620 for (Signal signal: ap.getEventStatsList()) { 621 if (signal.getFrequency() == 2412) { 622 assertFalse(signal.getRssi().hasCount()); 623 assertEquals(-42.0, signal.getRssi().getHistoricalMean(), TOL); 624 assertEquals(4.0, signal.getRssi().getHistoricalVariance(), TOL); 625 continue; 626 } 627 if (signal.getFrequency() == 2432) { 628 assertEquals(Event.SIGNAL_POLL, signal.getEvent()); 629 assertEquals(HISTOGRAM_RSSI[2], signal.getRssi().getBuckets(2).getLow()); 630 assertEquals(HISTOGRAM_COUNT[2], signal.getRssi().getBuckets(2).getNumber()); 631 continue; 632 } 633 assertEquals(5805, signal.getFrequency()); 634 switch (signal.getEvent()) { 635 case IP_CONFIGURATION_SUCCESS: 636 assertEquals(384.0, signal.getLinkspeed().getMaxValue(), TOL); 637 assertEquals(111.0, signal.getElapsedMs().getMinValue(), TOL); 638 break; 639 case SIGNAL_POLL: 640 assertEquals(2, signal.getRssi().getCount()); 641 break; 642 case FIRST_POLL_AFTER_CONNECTION: 643 assertEquals(-55.0, signal.getRssi().getSum(), TOL); 644 break; 645 default: 646 fail(signal.getEvent().toString()); 647 } 648 } 649 checkSerializationUpdateLinkBandwidthExample(ap.getBandwidthStatsAll()); 650 } 651 652 /** 653 * Serialization should be reproducible 654 */ 655 @Test testReproducableSerialization()656 public void testReproducableSerialization() throws Exception { 657 byte[] serialized = makeSerializedAccessPointExample(); 658 setUp(); 659 assertArrayEquals(serialized, makeSerializedAccessPointExample()); 660 } 661 662 /** 663 * AccessPoint Deserialization 664 */ 665 @Test testAccessPointDeserialization()666 public void testAccessPointDeserialization() throws Exception { 667 byte[] serialized = makeSerializedAccessPointExample(); 668 setUp(); // Get back to the initial state 669 670 WifiScoreCard.PerBssid perBssid = mWifiScoreCard.perBssidFromAccessPoint( 671 mWifiInfo.getSSID(), 672 AccessPoint.parseFrom(serialized)); 673 674 // Now verify 675 String diag = hexStringFromByteArray(serialized); 676 checkSerializationBssidExample(diag, perBssid); 677 } 678 679 /** 680 * Serialization of all internally represented networks 681 */ 682 @Test testNetworksSerialization()683 public void testNetworksSerialization() throws Exception { 684 makeSerializedAccessPointExample(); 685 686 byte[] serialized = mWifiScoreCard.getNetworkListByteArray(false); 687 byte[] cleaned = mWifiScoreCard.getNetworkListByteArray(true); 688 String base64Encoded = mWifiScoreCard.getNetworkListBase64(true); 689 690 setUp(); // Get back to the initial state 691 String diag = hexStringFromByteArray(serialized); 692 NetworkList networkList = NetworkList.parseFrom(serialized); 693 assertEquals(diag, 1, networkList.getNetworksCount()); 694 Network network = networkList.getNetworks(0); 695 assertEquals(diag, 1, network.getAccessPointsCount()); 696 AccessPoint accessPoint = network.getAccessPoints(0); 697 WifiScoreCard.PerBssid perBssid = mWifiScoreCard.perBssidFromAccessPoint(network.getSsid(), 698 accessPoint); 699 NetworkStats networkStats = network.getNetworkStats(); 700 PerNetwork perNetwork = mWifiScoreCard.perNetworkFromNetworkStats(network.getSsid(), 701 networkStats); 702 703 checkSerializationBssidExample(diag, perBssid); 704 checkSerializationBssidExample(diag, perNetwork); 705 // Leaving out the bssids should make the cleaned version shorter. 706 assertTrue(cleaned.length < serialized.length); 707 // Check the Base64 version 708 assertTrue(Arrays.equals(cleaned, Base64.decode(base64Encoded, Base64.DEFAULT))); 709 // Check that the network ids were carried over 710 assertEquals(TEST_NETWORK_AGENT_ID, network.getNetworkAgentId()); 711 assertEquals(TEST_NETWORK_CONFIG_ID, network.getNetworkConfigId()); 712 } 713 714 /** 715 * Installation of memory store does not crash 716 */ 717 @Test 718 public void testInstallationOfMemoryStoreDoesNotCrash() throws Exception { 719 mWifiScoreCard.installMemoryStore(mMemoryStore); 720 makeSerializedAccessPointExample(); 721 mWifiScoreCard.installMemoryStore(mMemoryStore); 722 } 723 724 /** 725 * Merge of lazy reads 726 */ 727 @Test 728 public void testLazyReads() { 729 // Install our own MemoryStore object, which records read requests 730 mWifiScoreCard.installMemoryStore(new WifiScoreCard.MemoryStore() { 731 @Override 732 public void read(String key, String name, WifiScoreCard.BlobListener listener) { 733 mKeys.add(key); 734 mBlobListeners.add(listener); 735 } 736 @Override 737 public void write(String key, String name, byte[] value) { 738 // ignore for now 739 } 740 @Override 741 public void setCluster(String key, String cluster) { 742 // ignore for now 743 } 744 @Override 745 public void removeCluster(String cluster) { 746 // ignore for now 747 } 748 }); 749 750 // Now make some changes 751 byte[] serialized = makeSerializedAccessPointExample(); 752 // 1 for perfBssid and 1 for perNetwork 753 assertEquals(2, mKeys.size()); 754 755 // Simulate the asynchronous completion of the read request 756 millisecondsPass(33); 757 mBlobListeners.get(0).onBlobRetrieved(serialized); 758 759 // Check that the historical mean and variance were updated accordingly 760 WifiScoreCard.PerBssid perBssid = mWifiScoreCard.fetchByBssid(TEST_BSSID_1); 761 assertEquals(-42.0, perBssid.lookupSignal(Event.SIGNAL_POLL, 2412) 762 .rssi.historicalMean, TOL); 763 assertEquals(4.0, perBssid.lookupSignal(Event.SIGNAL_POLL, 2412) 764 .rssi.historicalVariance, TOL); 765 } 766 767 /** 768 * Write test 769 */ 770 @Test 771 public void testWrites() throws Exception { 772 // Install our own MemoryStore object, which records write requests 773 mWifiScoreCard.installMemoryStore(new WifiScoreCard.MemoryStore() { 774 @Override 775 public void read(String key, String name, WifiScoreCard.BlobListener listener) { 776 // Just record these, never answer 777 mBlobListeners.add(listener); 778 } 779 @Override 780 public void write(String key, String name, byte[] value) { 781 mKeys.add(key); 782 mBlobs.add(value); 783 } 784 @Override 785 public void setCluster(String key, String cluster) { 786 } 787 @Override 788 public void removeCluster(String cluster) { 789 // ignore for now 790 } 791 }); 792 793 // Make some changes 794 byte[] serialized = makeSerializedAccessPointExample(); 795 // 1 for perfBssid and 1 for perNetwork 796 assertEquals(2, mBlobListeners.size()); 797 798 secondsPass(33); 799 800 // There should be one changed bssid now. We may have already done some writes. 801 mWifiScoreCard.doWrites(); 802 assertTrue(mKeys.size() > 0); 803 804 // The written blob should not contain the BSSID, though the full serialized version does 805 String writtenHex = hexStringFromByteArray(mBlobs.get(mKeys.size() - 1)); 806 String fullHex = hexStringFromByteArray(serialized); 807 String bssidHex = hexStringFromByteArray(TEST_BSSID_1.toByteArray()); 808 assertFalse(writtenHex, writtenHex.contains(bssidHex)); 809 assertTrue(fullHex, fullHex.contains(bssidHex)); 810 811 // A second write request should not find anything to write 812 final int beforeSize = mKeys.size(); 813 assertEquals(0, mWifiScoreCard.doWrites()); 814 assertEquals(beforeSize, mKeys.size()); 815 } 816 817 /** 818 * Calling doWrites before installing a MemoryStore should do nothing. 819 */ 820 @Test testNoWritesUntilReady()821 public void testNoWritesUntilReady() throws Exception { 822 makeSerializedAccessPointExample(); 823 assertEquals(0, mWifiScoreCard.doWrites()); 824 } 825 826 /** 827 * Installing a MemoryStore after startup should issue reads. 828 */ 829 @Test testReadAfterDelayedMemoryStoreInstallation()830 public void testReadAfterDelayedMemoryStoreInstallation() throws Exception { 831 makeSerializedAccessPointExample(); 832 mWifiScoreCard.installMemoryStore(mMemoryStore); 833 // 1 for requestReadBssid 834 verify(mMemoryStore, times(1)).read(any(), any(), any()); 835 } 836 837 /** 838 * Calling clear should forget the state. 839 */ 840 @Test testClearReallyDoesClearTheState()841 public void testClearReallyDoesClearTheState() throws Exception { 842 byte[] serialized = makeSerializedAccessPointExample(); 843 assertNotEquals(0, serialized.length); 844 mWifiScoreCard.clear(); 845 byte[] leftovers = mWifiScoreCard.getNetworkListByteArray(false); 846 assertEquals(0, leftovers.length); 847 } 848 849 /** 850 * Test that older items are evicted from memory. 851 */ 852 @Test testOlderItemsShouldBeEvicted()853 public void testOlderItemsShouldBeEvicted() throws Exception { 854 mWifiInfo.setRssi(-55); 855 mWifiInfo.setFrequency(5805); 856 mWifiInfo.setLinkSpeed(384); 857 mWifiScoreCard.installMemoryStore(mMemoryStore); 858 for (int i = 0; i < 256; i++) { 859 MacAddress bssid = MacAddress.fromBytes(new byte[]{2, 2, 2, 2, 2, (byte) i}); 860 mWifiInfo.setBSSID(bssid.toString()); 861 mWifiScoreCard.noteSignalPoll(mWifiInfo); 862 } 863 // 256 for requestReadBssid() and 1 for requestReadNetwork() 864 verify(mMemoryStore, times(256 + 1)).read(any(), any(), any()); 865 verify(mMemoryStore, atLeastOnce()).write(any(), any(), any()); // Assumes target size < 256 866 reset(mMemoryStore); 867 868 for (int i = 256 - 3; i < 256; i++) { 869 MacAddress bssid = MacAddress.fromBytes(new byte[]{2, 2, 2, 2, 2, (byte) i}); 870 mWifiInfo.setBSSID(bssid.toString()); 871 mWifiScoreCard.noteSignalPoll(mWifiInfo); 872 } 873 verify(mMemoryStore, never()).read(any(), any(), any()); // Assumes target size >= 3 874 875 for (int i = 0; i < 3; i++) { 876 MacAddress bssid = MacAddress.fromBytes(new byte[]{2, 2, 2, 2, 2, (byte) i}); 877 mWifiInfo.setBSSID(bssid.toString()); 878 mWifiScoreCard.noteSignalPoll(mWifiInfo); 879 } 880 verify(mMemoryStore, times(3)).read(any(), any(), any()); // Assumes target size < 253 881 } 882 makeAssocTimeOutExample()883 private void makeAssocTimeOutExample() { 884 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 885 millisecondsPass(1000); 886 mWifiScoreCard.noteConnectionFailure(mWifiInfo, -53, mWifiInfo.getSSID(), 887 WifiBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT); 888 } 889 makeAssocRejectionExample()890 private void makeAssocRejectionExample() { 891 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 892 millisecondsPass(1000); 893 mWifiScoreCard.noteConnectionFailure(mWifiInfo, -53, mWifiInfo.getSSID(), 894 WifiBlocklistMonitor.REASON_ASSOCIATION_REJECTION); 895 } 896 makeApUnableToHandleNewStaExample()897 private void makeApUnableToHandleNewStaExample() { 898 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 899 millisecondsPass(1000); 900 mWifiScoreCard.noteConnectionFailure(mWifiInfo, -53, mWifiInfo.getSSID(), 901 WifiBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA); 902 } 903 904 /** 905 * Check network stats after association timeout. 906 */ 907 @Test testNetworkAssocTimeOut()908 public void testNetworkAssocTimeOut() throws Exception { 909 makeAssocTimeOutExample(); 910 911 PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); 912 NetworkConnectionStats dailyStats = perNetwork.getRecentStats(); 913 914 assertEquals(1, dailyStats.getCount(CNT_CONNECTION_ATTEMPT)); 915 assertEquals(1, dailyStats.getCount(CNT_CONNECTION_FAILURE)); 916 assertEquals(0, dailyStats.getCount(CNT_CONNECTION_DURATION_SEC)); 917 assertEquals(0, dailyStats.getCount(CNT_ASSOCIATION_REJECTION)); 918 assertEquals(1, dailyStats.getCount(CNT_ASSOCIATION_TIMEOUT)); 919 assertEquals(0, dailyStats.getCount(CNT_AUTHENTICATION_FAILURE)); 920 assertEquals(1, dailyStats.getCount(CNT_CONSECUTIVE_CONNECTION_FAILURE)); 921 assertEquals(0, dailyStats.getCount(CNT_CONSECUTIVE_WRONG_PASSWORD_FAILURE)); 922 } 923 924 /** 925 * Check network stats after association rejection. 926 */ 927 @Test testNetworkAssocRejection()928 public void testNetworkAssocRejection() throws Exception { 929 makeAssocRejectionExample(); 930 makeApUnableToHandleNewStaExample(); 931 932 PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); 933 NetworkConnectionStats dailyStats = perNetwork.getRecentStats(); 934 935 assertEquals(2, dailyStats.getCount(CNT_CONNECTION_ATTEMPT)); 936 assertEquals(2, dailyStats.getCount(CNT_CONNECTION_FAILURE)); 937 assertEquals(0, dailyStats.getCount(CNT_CONNECTION_DURATION_SEC)); 938 assertEquals(1, dailyStats.getCount(CNT_ASSOCIATION_REJECTION)); 939 assertEquals(0, dailyStats.getCount(CNT_ASSOCIATION_TIMEOUT)); 940 assertEquals(0, dailyStats.getCount(CNT_AUTHENTICATION_FAILURE)); 941 assertEquals(2, dailyStats.getCount(CNT_CONSECUTIVE_CONNECTION_FAILURE)); 942 assertEquals(0, dailyStats.getCount(CNT_CONSECUTIVE_WRONG_PASSWORD_FAILURE)); 943 } 944 945 946 /** 947 * Check network stats after auth timeout/disconnection and a normal connection 948 */ 949 @Test testAuthTimeoutDisconnection()950 public void testAuthTimeoutDisconnection() throws Exception { 951 makeAuthFailureExample(); 952 mWifiScoreCard.resetAllConnectionStates(); 953 954 PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); 955 NetworkConnectionStats dailyStats = perNetwork.getRecentStats(); 956 957 assertEquals(1, dailyStats.getCount(CNT_CONNECTION_ATTEMPT)); 958 assertEquals(1, dailyStats.getCount(CNT_CONNECTION_FAILURE)); 959 assertEquals(0, dailyStats.getCount(CNT_CONNECTION_DURATION_SEC)); 960 assertEquals(0, dailyStats.getCount(CNT_ASSOCIATION_REJECTION)); 961 assertEquals(0, dailyStats.getCount(CNT_ASSOCIATION_TIMEOUT)); 962 assertEquals(1, dailyStats.getCount(CNT_AUTHENTICATION_FAILURE)); 963 assertEquals(1, dailyStats.getCount(CNT_CONSECUTIVE_CONNECTION_FAILURE)); 964 assertEquals(0, dailyStats.getCount(CNT_CONSECUTIVE_WRONG_PASSWORD_FAILURE)); 965 966 makeNormalConnectionExample(); 967 assertEquals(0, dailyStats.getCount(CNT_CONSECUTIVE_CONNECTION_FAILURE)); 968 } 969 makeAuthFailureAndWrongPassword()970 private void makeAuthFailureAndWrongPassword() { 971 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 972 millisecondsPass(500); 973 mWifiScoreCard.noteConnectionFailure(mWifiInfo, -53, mWifiInfo.getSSID(), 974 WifiBlocklistMonitor.REASON_AUTHENTICATION_FAILURE); 975 millisecondsPass(1000); 976 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 977 millisecondsPass(1000); 978 mWifiScoreCard.noteConnectionFailure(mWifiInfo, -53, mWifiInfo.getSSID(), 979 WifiBlocklistMonitor.REASON_WRONG_PASSWORD); 980 } 981 makeAuthFailureExample()982 private void makeAuthFailureExample() { 983 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 984 millisecondsPass(500); 985 mWifiScoreCard.noteConnectionFailure(mWifiInfo, -53, mWifiInfo.getSSID(), 986 WifiBlocklistMonitor.REASON_AUTHENTICATION_FAILURE); 987 } 988 989 /** 990 * Check network stats after authentication failure and wrong password. 991 */ 992 @Test testNetworkAuthenticationFailureWrongPassword()993 public void testNetworkAuthenticationFailureWrongPassword() throws Exception { 994 makeAuthFailureAndWrongPassword(); 995 PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); 996 NetworkConnectionStats dailyStats = perNetwork.getRecentStats(); 997 998 assertEquals(2, dailyStats.getCount(CNT_CONNECTION_ATTEMPT)); 999 assertEquals(1, dailyStats.getCount(CNT_CONNECTION_FAILURE)); 1000 assertEquals(0, dailyStats.getCount(CNT_CONNECTION_DURATION_SEC)); 1001 assertEquals(0, dailyStats.getCount(CNT_ASSOCIATION_REJECTION)); 1002 assertEquals(0, dailyStats.getCount(CNT_ASSOCIATION_TIMEOUT)); 1003 assertEquals(1, dailyStats.getCount(CNT_AUTHENTICATION_FAILURE)); 1004 assertEquals(1, dailyStats.getCount(CNT_CONSECUTIVE_CONNECTION_FAILURE)); 1005 assertEquals(1, dailyStats.getCount(CNT_CONSECUTIVE_WRONG_PASSWORD_FAILURE)); 1006 1007 makeNormalConnectionExample(); 1008 assertEquals(0, dailyStats.getCount(CNT_CONSECUTIVE_CONNECTION_FAILURE)); 1009 assertEquals(0, dailyStats.getCount(CNT_CONSECUTIVE_WRONG_PASSWORD_FAILURE)); 1010 } 1011 makeDisconnectionConnectingExample(boolean nonlocal)1012 private void makeDisconnectionConnectingExample(boolean nonlocal) { 1013 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 1014 millisecondsPass(500); 1015 int disconnectionReason = 3; 1016 if (nonlocal) { 1017 mWifiScoreCard.noteNonlocalDisconnect(WIFI_IFACE_NAME, disconnectionReason); 1018 } 1019 mWifiScoreCard.noteConnectionFailure(mWifiInfo, -53, mWifiInfo.getSSID(), 1020 WifiBlocklistMonitor.REASON_NONLOCAL_DISCONNECT_CONNECTING); 1021 millisecondsPass(500); 1022 } 1023 1024 /** 1025 * Check network stats after nonlocal disconnection in middle of connection 1026 */ 1027 @Test testDisconnectionConnecting()1028 public void testDisconnectionConnecting() throws Exception { 1029 makeDisconnectionConnectingExample(true); 1030 PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); 1031 NetworkConnectionStats dailyStats = perNetwork.getRecentStats(); 1032 1033 assertEquals(1, dailyStats.getCount(CNT_CONNECTION_ATTEMPT)); 1034 assertEquals(1, dailyStats.getCount(CNT_CONNECTION_FAILURE)); 1035 assertEquals(1, dailyStats.getCount(CNT_DISCONNECTION_NONLOCAL_CONNECTING)); 1036 assertEquals(0, dailyStats.getCount(CNT_CONNECTION_DURATION_SEC)); 1037 assertEquals(0, dailyStats.getCount(CNT_ASSOCIATION_REJECTION)); 1038 assertEquals(0, dailyStats.getCount(CNT_ASSOCIATION_TIMEOUT)); 1039 assertEquals(0, dailyStats.getCount(CNT_AUTHENTICATION_FAILURE)); 1040 assertEquals(0, dailyStats.getCount(CNT_CONSECUTIVE_WRONG_PASSWORD_FAILURE)); 1041 } 1042 1043 /** 1044 * Check network stats after local disconnection in middle of connection 1045 */ 1046 @Test testLocalDisconnectionConnecting()1047 public void testLocalDisconnectionConnecting() throws Exception { 1048 makeDisconnectionConnectingExample(false); 1049 PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); 1050 NetworkConnectionStats dailyStats = perNetwork.getRecentStats(); 1051 1052 assertEquals(1, dailyStats.getCount(CNT_CONNECTION_ATTEMPT)); 1053 assertEquals(1, dailyStats.getCount(CNT_CONNECTION_FAILURE)); 1054 assertEquals(1, dailyStats.getCount(CNT_DISCONNECTION_NONLOCAL_CONNECTING)); 1055 } 1056 1057 /** 1058 * Check network stats when a new connection attempt for SSID2 is issued 1059 * before disconnection of SSID1 1060 */ 1061 @Test testNetworkSwitchWithOverlapping()1062 public void testNetworkSwitchWithOverlapping() throws Exception { 1063 // Connect to SSID_1 1064 String ssid1 = mWifiInfo.getSSID(); 1065 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, ssid1); 1066 millisecondsPass(5000); 1067 1068 // Attempt to connect to SSID_2 1069 mWifiInfo.setSSID(TEST_SSID_2); 1070 mWifiInfo.setBSSID(TEST_BSSID_2.toString()); 1071 String ssid2 = mWifiInfo.getSSID(); 1072 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, ssid2); 1073 1074 // Disconnect from SSID_1 1075 millisecondsPass(100); 1076 int disconnectionReason = 4; 1077 mWifiScoreCard.noteNonlocalDisconnect(WIFI_IFACE_NAME, disconnectionReason); 1078 millisecondsPass(100); 1079 mWifiScoreCard.resetConnectionState(WIFI_IFACE_NAME); 1080 1081 // SSID_2 is connected and then disconnected 1082 millisecondsPass(2000); 1083 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 1084 millisecondsPass(2000); 1085 mWifiScoreCard.resetConnectionState(WIFI_IFACE_NAME); 1086 1087 PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(ssid1); 1088 assertEquals(5, perNetwork.getRecentStats().getCount(CNT_CONNECTION_DURATION_SEC)); 1089 1090 perNetwork = mWifiScoreCard.fetchByNetwork(ssid2); 1091 assertEquals(4, perNetwork.getRecentStats().getCount(CNT_CONNECTION_DURATION_SEC)); 1092 } 1093 1094 /** 1095 * Check network stats after 2 connection failures at low RSSI. 1096 */ 1097 @Test testNetworkConnectionFailureLowRssi()1098 public void testNetworkConnectionFailureLowRssi() throws Exception { 1099 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -83, mWifiInfo.getSSID()); 1100 millisecondsPass(1000); 1101 mWifiScoreCard.noteConnectionFailure(mWifiInfo, -83, mWifiInfo.getSSID(), 1102 WifiBlocklistMonitor.REASON_ASSOCIATION_REJECTION); 1103 millisecondsPass(3000); 1104 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -83, mWifiInfo.getSSID()); 1105 millisecondsPass(1000); 1106 mWifiScoreCard.noteConnectionFailure(mWifiInfo, -83, mWifiInfo.getSSID(), 1107 WifiBlocklistMonitor.REASON_ASSOCIATION_REJECTION); 1108 1109 PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); 1110 NetworkConnectionStats dailyStats = perNetwork.getRecentStats(); 1111 checkShortConnectionExample(dailyStats, 0); 1112 } 1113 makeShortConnectionExample(boolean addFwAlert)1114 private void makeShortConnectionExample(boolean addFwAlert) { 1115 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 1116 millisecondsPass(5000); 1117 mWifiInfo.setTxLinkSpeedMbps(100); 1118 mWifiInfo.setSuccessfulTxPacketsPerSecond(20.0); 1119 mWifiInfo.setRetriedTxPacketsRate(1.0); 1120 mWifiInfo.setRssi(-80); 1121 millisecondsPass(1000); 1122 mWifiScoreCard.noteSignalPoll(mWifiInfo); 1123 millisecondsPass(2000); 1124 int disconnectionReason = 34; 1125 mWifiScoreCard.noteNonlocalDisconnect(WIFI_IFACE_NAME, disconnectionReason); 1126 if (addFwAlert) { 1127 mWifiScoreCard.noteFirmwareAlert(6); 1128 } 1129 millisecondsPass(1000); 1130 mWifiScoreCard.resetAllConnectionStates(); 1131 } 1132 checkShortConnectionExample(NetworkConnectionStats stats, int scale)1133 private void checkShortConnectionExample(NetworkConnectionStats stats, int scale) { 1134 assertEquals(1 * scale, stats.getCount(CNT_CONNECTION_ATTEMPT)); 1135 assertEquals(0, stats.getCount(CNT_CONNECTION_FAILURE)); 1136 assertEquals(0, stats.getCount(CNT_DISCONNECTION_NONLOCAL_CONNECTING)); 1137 assertEquals(9 * scale, stats.getCount(CNT_CONNECTION_DURATION_SEC)); 1138 assertEquals(0, stats.getCount(CNT_ASSOCIATION_REJECTION)); 1139 assertEquals(0, stats.getCount(CNT_ASSOCIATION_TIMEOUT)); 1140 assertEquals(0, stats.getCount(CNT_AUTHENTICATION_FAILURE)); 1141 assertEquals(1 * scale, stats.getCount(CNT_SHORT_CONNECTION_NONLOCAL)); 1142 assertEquals(1 * scale, stats.getCount(CNT_DISCONNECTION_NONLOCAL)); 1143 assertEquals(0, stats.getCount(CNT_CONSECUTIVE_CONNECTION_FAILURE)); 1144 } 1145 makeShortConnectionOldRssiPollingExample()1146 private void makeShortConnectionOldRssiPollingExample() { 1147 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 1148 millisecondsPass(2000); 1149 mWifiInfo.setRssi(-55); 1150 millisecondsPass(1000); 1151 mWifiScoreCard.noteSignalPoll(mWifiInfo); 1152 millisecondsPass(29000); 1153 int disconnectionReason = 3; 1154 mWifiScoreCard.noteNonlocalDisconnect(WIFI_IFACE_NAME, disconnectionReason); 1155 millisecondsPass(1000); 1156 mWifiScoreCard.resetAllConnectionStates(); 1157 } 1158 checkShortConnectionOldPollingExample(NetworkConnectionStats stats)1159 private void checkShortConnectionOldPollingExample(NetworkConnectionStats stats) { 1160 assertEquals(1, stats.getCount(CNT_CONNECTION_ATTEMPT)); 1161 assertEquals(0, stats.getCount(CNT_CONNECTION_FAILURE)); 1162 assertEquals(0, stats.getCount(CNT_DISCONNECTION_NONLOCAL_CONNECTING)); 1163 assertEquals(33, stats.getCount(CNT_CONNECTION_DURATION_SEC)); 1164 assertEquals(0, stats.getCount(CNT_ASSOCIATION_REJECTION)); 1165 assertEquals(0, stats.getCount(CNT_ASSOCIATION_TIMEOUT)); 1166 assertEquals(0, stats.getCount(CNT_AUTHENTICATION_FAILURE)); 1167 assertEquals(0, stats.getCount(CNT_SHORT_CONNECTION_NONLOCAL)); 1168 assertEquals(0, stats.getCount(CNT_DISCONNECTION_NONLOCAL)); 1169 } 1170 1171 /** 1172 * Check network stats after RSSI poll and disconnection, pass FW alert check 1173 */ 1174 @Test testNetworkRssiPollShortNonlocalDisconnectionPassFwAlertCheck()1175 public void testNetworkRssiPollShortNonlocalDisconnectionPassFwAlertCheck() throws Exception { 1176 when(mDeviceConfigFacade.getHealthMonitorFwAlertValidTimeMs()).thenReturn(2000); 1177 // 1st connection session 1178 makeShortConnectionExample(/*addFwAlert*/true); 1179 // 2nd connection session 1180 makeNormalConnectionExample(); 1181 1182 PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); 1183 NetworkConnectionStats dailyStats = perNetwork.getRecentStats(); 1184 assertEquals(2, dailyStats.getCount(CNT_CONNECTION_ATTEMPT)); 1185 assertEquals(0, dailyStats.getCount(CNT_CONNECTION_FAILURE)); 1186 assertEquals(20, dailyStats.getCount(CNT_CONNECTION_DURATION_SEC)); 1187 assertEquals(0, dailyStats.getCount(CNT_ASSOCIATION_REJECTION)); 1188 assertEquals(0, dailyStats.getCount(CNT_ASSOCIATION_TIMEOUT)); 1189 assertEquals(0, dailyStats.getCount(CNT_AUTHENTICATION_FAILURE)); 1190 assertEquals(1, dailyStats.getCount(CNT_SHORT_CONNECTION_NONLOCAL)); 1191 assertEquals(1, dailyStats.getCount(CNT_DISCONNECTION_NONLOCAL)); 1192 } 1193 1194 /** 1195 * Check network stats after RSSI poll and disconnection, fail FW alert check 1196 */ 1197 @Test testNetworkRssiPollShortNonlocalDisconnectionFailFwAlertCheck()1198 public void testNetworkRssiPollShortNonlocalDisconnectionFailFwAlertCheck() throws Exception { 1199 when(mDeviceConfigFacade.getHealthMonitorFwAlertValidTimeMs()).thenReturn(2000); 1200 // 1st connection session 1201 makeShortConnectionExample(/*addFwAlert*/false); 1202 // 2nd connection session 1203 makeNormalConnectionExample(); 1204 1205 PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); 1206 NetworkConnectionStats dailyStats = perNetwork.getRecentStats(); 1207 assertEquals(0, dailyStats.getCount(CNT_SHORT_CONNECTION_NONLOCAL)); 1208 assertEquals(0, dailyStats.getCount(CNT_DISCONNECTION_NONLOCAL)); 1209 } 1210 1211 /** 1212 * Check network stats after short connection with an old RSSI polling 1213 */ 1214 @Test testShortNonlocalDisconnectionOldRssiPolling()1215 public void testShortNonlocalDisconnectionOldRssiPolling() throws Exception { 1216 makeShortConnectionOldRssiPollingExample(); 1217 PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); 1218 checkShortConnectionOldPollingExample(perNetwork.getRecentStats()); 1219 } 1220 makeNormalConnectionExample()1221 private void makeNormalConnectionExample() { 1222 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 1223 millisecondsPass(1000); 1224 mWifiInfo.setRssi(-55); 1225 millisecondsPass(7000); 1226 mWifiScoreCard.noteSignalPoll(mWifiInfo); 1227 millisecondsPass(3000); 1228 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 1229 mWifiScoreCard.resetAllConnectionStates(); 1230 } 1231 makeUpdateLinkBandwidthExample()1232 private void makeUpdateLinkBandwidthExample() { 1233 mWifiInfo.setRssi(-79); 1234 mWifiInfo.setFrequency(2437); 1235 mNewLlStats.on_time = 1000; 1236 mNewLlStats.timeStampInMs = 5_000; 1237 long txBytes = 2_000_000L; 1238 long rxBytes = 4_000_000L; 1239 PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); 1240 for (int i = 0; i < BANDWIDTH_STATS_COUNT_THR; i++) { 1241 addTotalBytes(txBytes, rxBytes); 1242 perNetwork.updateLinkBandwidth(mOldLlStats, mNewLlStats, mWifiInfo, mTotalTxBytes, 1243 mTotalRxBytes); 1244 } 1245 mWifiInfo.setFrequency(5210); 1246 txBytes = 5_000_000L; 1247 rxBytes = 1000L; 1248 for (int i = 0; i < BANDWIDTH_STATS_COUNT_THR + 2; i++) { 1249 addTotalBytes(txBytes, rxBytes); 1250 perNetwork.updateLinkBandwidth(mOldLlStats, mNewLlStats, mWifiInfo, mTotalTxBytes, 1251 mTotalRxBytes); 1252 } 1253 } 1254 checkSerializationUpdateLinkBandwidthExample(BandwidthStatsAll stats)1255 private void checkSerializationUpdateLinkBandwidthExample(BandwidthStatsAll stats) { 1256 assertEquals(2_000_000L * 8 / 1000 * BANDWIDTH_STATS_COUNT_THR, 1257 stats.getStats2G().getTx().getLevel(1).getValue()); 1258 assertEquals(4_000_000L * 8 / 1000 * BANDWIDTH_STATS_COUNT_THR, 1259 stats.getStats2G().getRx().getLevel(1).getValue()); 1260 assertEquals(BANDWIDTH_STATS_COUNT_THR, 1261 stats.getStats2G().getTx().getLevel(1).getCount()); 1262 assertEquals(BANDWIDTH_STATS_COUNT_THR, 1263 stats.getStats2G().getRx().getLevel(1).getCount()); 1264 1265 assertEquals(5_000_000L * 8 / 1000 * (BANDWIDTH_STATS_COUNT_THR + 2), 1266 stats.getStatsAbove2G().getTx().getLevel(1).getValue()); 1267 assertEquals(0, stats.getStatsAbove2G().getRx().getLevel(1).getValue()); 1268 assertEquals(BANDWIDTH_STATS_COUNT_THR + 2, 1269 stats.getStatsAbove2G().getTx().getLevel(1).getCount()); 1270 assertEquals(0, stats.getStatsAbove2G().getRx().getLevel(1).getCount()); 1271 } 1272 1273 /** 1274 * Constructs a protobuf form of Network example. 1275 */ makeSerializedNetworkExample()1276 private byte[] makeSerializedNetworkExample() { 1277 makeDisconnectionConnectingExample(true); 1278 makeShortConnectionExample(true); 1279 makeUpdateLinkBandwidthExample(); 1280 PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); 1281 checkSerializationNetworkExample("before serialization", perNetwork); 1282 // Now convert to protobuf form 1283 byte[] serialized = perNetwork.toNetworkStats().toByteArray(); 1284 return serialized; 1285 } 1286 1287 /** 1288 * Checks that the fields of the network serialization example are as expected. 1289 */ checkSerializationNetworkExample(String diag, PerNetwork perNetwork)1290 private void checkSerializationNetworkExample(String diag, PerNetwork perNetwork) { 1291 NetworkConnectionStats dailyStats = perNetwork.getRecentStats(); 1292 1293 assertEquals(diag, 2, dailyStats.getCount(CNT_CONNECTION_ATTEMPT)); 1294 assertEquals(diag, 1, dailyStats.getCount(CNT_CONNECTION_FAILURE)); 1295 assertEquals(diag, 1, dailyStats.getCount(CNT_DISCONNECTION_NONLOCAL_CONNECTING)); 1296 assertEquals(diag, 9, dailyStats.getCount(CNT_CONNECTION_DURATION_SEC)); 1297 assertEquals(diag, 1, dailyStats.getCount(CNT_SHORT_CONNECTION_NONLOCAL)); 1298 assertEquals(diag, 1, dailyStats.getCount(CNT_DISCONNECTION_NONLOCAL)); 1299 assertEquals(diag, 0, dailyStats.getCount(CNT_ASSOCIATION_REJECTION)); 1300 assertEquals(diag, 0, dailyStats.getCount(CNT_ASSOCIATION_TIMEOUT)); 1301 assertEquals(diag, 0, dailyStats.getCount(CNT_AUTHENTICATION_FAILURE)); 1302 assertEquals(diag, 0, dailyStats.getCount(CNT_CONSECUTIVE_WRONG_PASSWORD_FAILURE)); 1303 } 1304 1305 /** 1306 * Test NetworkStats serialization. 1307 */ 1308 @Test testNetworkStatsSerialization()1309 public void testNetworkStatsSerialization() throws Exception { 1310 byte[] serialized = makeSerializedNetworkExample(); 1311 1312 // Verify by parsing it and checking that we see the expected results 1313 NetworkStats ns = NetworkStats.parseFrom(serialized); 1314 ConnectionStats dailyStats = ns.getRecentStats(); 1315 assertEquals(2, dailyStats.getNumConnectionAttempt()); 1316 assertEquals(1, dailyStats.getNumConnectionFailure()); 1317 assertEquals(1, dailyStats.getNumDisconnectionNonlocalConnecting()); 1318 assertEquals(9, dailyStats.getConnectionDurationSec()); 1319 assertEquals(1, dailyStats.getNumDisconnectionNonlocal()); 1320 assertEquals(1, dailyStats.getNumShortConnectionNonlocal()); 1321 assertEquals(0, dailyStats.getNumAssociationRejection()); 1322 assertEquals(0, dailyStats.getNumAssociationTimeout()); 1323 assertEquals(0, dailyStats.getNumAuthenticationFailure()); 1324 1325 checkSerializationUpdateLinkBandwidthExample(ns.getBandwidthStatsAll()); 1326 } 1327 1328 /** 1329 * Test NetworkStats Deserialization. 1330 */ 1331 @Test testNetworkStatsDeserialization()1332 public void testNetworkStatsDeserialization() throws Exception { 1333 byte[] serialized = makeSerializedNetworkExample(); 1334 setUp(); // Get back to the initial state 1335 1336 PerNetwork perNetwork = mWifiScoreCard.perNetworkFromNetworkStats(mWifiInfo.getSSID(), 1337 NetworkStats.parseFrom(serialized)); 1338 1339 // Now verify 1340 String diag = hexStringFromByteArray(serialized); 1341 checkSerializationNetworkExample(diag, perNetwork); 1342 } 1343 1344 /** 1345 * Check network stats after network connection and then removeNetWork(). 1346 */ 1347 @Test testRemoveNetwork()1348 public void testRemoveNetwork() throws Exception { 1349 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 1350 millisecondsPass(1000); 1351 mWifiScoreCard.noteConnectionFailure(mWifiInfo, -53, mWifiInfo.getSSID(), 1352 WifiBlocklistMonitor.REASON_ASSOCIATION_REJECTION); 1353 mWifiScoreCard.removeNetwork(mWifiInfo.getSSID()); 1354 1355 PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); 1356 assertNull(perNetwork); 1357 } 1358 1359 @Test testUpdateAfterDailyDetection()1360 public void testUpdateAfterDailyDetection() throws Exception { 1361 for (int i = 0; i < DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT; i++) { 1362 makeShortConnectionExample(/*addFwAlert*/false); 1363 } 1364 1365 PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); 1366 perNetwork.updateAfterDailyDetection(); 1367 1368 checkShortConnectionExample(perNetwork.getRecentStats(), 0); 1369 checkShortConnectionExample(perNetwork.getStatsCurrBuild(), 1370 DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT); 1371 checkShortConnectionExample(perNetwork.getStatsPrevBuild(), 0); 1372 } 1373 1374 @Test testUpdateAfterSwBuildChange()1375 public void testUpdateAfterSwBuildChange() throws Exception { 1376 for (int i = 0; i < DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT; i++) { 1377 makeShortConnectionExample(/*addFwAlert*/false); 1378 } 1379 PerNetwork perNetwork = mWifiScoreCard.fetchByNetwork(mWifiInfo.getSSID()); 1380 perNetwork.updateAfterDailyDetection(); 1381 perNetwork.updateAfterSwBuildChange(); 1382 1383 checkShortConnectionExample(perNetwork.getRecentStats(), 0); 1384 checkShortConnectionExample(perNetwork.getStatsCurrBuild(), 0); 1385 checkShortConnectionExample(perNetwork.getStatsPrevBuild(), 1386 DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT); 1387 } 1388 makeRecentStatsWithGoodConnection()1389 private void makeRecentStatsWithGoodConnection() { 1390 for (int i = 0; i < DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT; i++) { 1391 makeNormalConnectionExample(); 1392 } 1393 } 1394 makeRecentStatsWithShortConnection()1395 private void makeRecentStatsWithShortConnection() { 1396 for (int i = 0; i < DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT; i++) { 1397 makeShortConnectionExample(/*addFwAlert*/false); 1398 } 1399 } 1400 makeRecentStatsWithAssocTimeOut()1401 private void makeRecentStatsWithAssocTimeOut() { 1402 for (int i = 0; i < DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT; i++) { 1403 makeAssocTimeOutExample(); 1404 } 1405 } 1406 makeRecentStatsWithAuthFailure()1407 private void makeRecentStatsWithAuthFailure() { 1408 for (int i = 0; i < DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT; i++) { 1409 makeAuthFailureExample(); 1410 } 1411 } 1412 checkStatsDeltaExample(FailureStats stats, int scale)1413 private void checkStatsDeltaExample(FailureStats stats, int scale) { 1414 assertEquals(0, stats.getCount(REASON_ASSOC_REJECTION)); 1415 assertEquals(1 * scale, stats.getCount(REASON_ASSOC_TIMEOUT)); 1416 assertEquals(1 * scale, stats.getCount(REASON_AUTH_FAILURE)); 1417 assertEquals(1 * scale, stats.getCount(REASON_CONNECTION_FAILURE)); 1418 assertEquals(1 * scale, stats.getCount(REASON_DISCONNECTION_NONLOCAL)); 1419 assertEquals(1 * scale, stats.getCount(REASON_SHORT_CONNECTION_NONLOCAL)); 1420 } 1421 1422 /** 1423 * Check if daily detection is skipped with insufficient daily stats. 1424 */ 1425 @Test testDailyDetectionWithInsufficientRecentStats()1426 public void testDailyDetectionWithInsufficientRecentStats() throws Exception { 1427 PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); 1428 makeShortConnectionExample(/*addFwAlert*/false); 1429 1430 FailureStats statsDec = new FailureStats(); 1431 FailureStats statsInc = new FailureStats(); 1432 FailureStats statsHigh = new FailureStats(); 1433 int detectionFlag = perNetwork.dailyDetection(statsDec, statsInc, statsHigh); 1434 assertEquals(WifiScoreCard.INSUFFICIENT_RECENT_STATS, detectionFlag); 1435 checkStatsDeltaExample(statsDec, 0); 1436 checkStatsDeltaExample(statsInc, 0); 1437 checkStatsDeltaExample(statsHigh, 0); 1438 perNetwork.updateAfterDailyDetection(); 1439 checkShortConnectionExample(perNetwork.getRecentStats(), 1); 1440 checkShortConnectionExample(perNetwork.getStatsPrevBuild(), 0); 1441 assertEquals(WifiHealthMonitor.REASON_NO_FAILURE, 1442 mWifiScoreCard.detectAbnormalConnectionFailure(mWifiInfo.getSSID())); 1443 } 1444 1445 /** 1446 * Run a few days with mostly good connection and some failures, 1447 * followed by a SW build change which results 1448 * in performance regression. Check if the regression is detected properly. 1449 */ 1450 @Test testRegressionAfterSwBuildChange()1451 public void testRegressionAfterSwBuildChange() throws Exception { 1452 PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); 1453 int numGoodConnectionDays = 4; 1454 for (int i = 0; i < numGoodConnectionDays; i++) { 1455 makeRecentStatsWithGoodConnection(); 1456 perNetwork.updateAfterDailyDetection(); 1457 } 1458 // Extra day with mixed failures 1459 makeRecentStatsWithShortConnection(); 1460 makeRecentStatsWithAssocTimeOut(); 1461 makeRecentStatsWithAuthFailure(); 1462 perNetwork.updateAfterDailyDetection(); 1463 1464 perNetwork.updateAfterSwBuildChange(); 1465 // Add >2x failures after the SW build change 1466 int numBadConnectionDays = 4; 1467 for (int i = 0; i < numBadConnectionDays; i++) { 1468 makeRecentStatsWithAssocTimeOut(); 1469 makeRecentStatsWithAuthFailure(); 1470 makeRecentStatsWithShortConnection(); 1471 } 1472 1473 assertEquals(WifiHealthMonitor.REASON_SHORT_CONNECTION_NONLOCAL, 1474 mWifiScoreCard.detectAbnormalDisconnection(WIFI_IFACE_NAME)); 1475 FailureStats statsDec = new FailureStats(); 1476 FailureStats statsInc = new FailureStats(); 1477 FailureStats statsHigh = new FailureStats(); 1478 int detectionFlag = perNetwork.dailyDetection(statsDec, statsInc, statsHigh); 1479 assertEquals(WifiScoreCard.SUFFICIENT_RECENT_PREV_STATS, detectionFlag); 1480 checkStatsDeltaExample(statsDec, 0); 1481 checkStatsDeltaExample(statsInc, 1); 1482 checkStatsDeltaExample(statsHigh, 0); 1483 } 1484 1485 /** 1486 * Check regression detection is missed due to low failure count 1487 */ 1488 @Test testMissRegressionDetectionDuetoLowFailureCnt()1489 public void testMissRegressionDetectionDuetoLowFailureCnt() throws Exception { 1490 PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); 1491 int numGoodConnectionDays = 1; 1492 for (int i = 0; i < numGoodConnectionDays; i++) { 1493 makeRecentStatsWithGoodConnection(); 1494 perNetwork.updateAfterDailyDetection(); 1495 } 1496 1497 perNetwork.updateAfterSwBuildChange(); 1498 makeRecentStatsWithGoodConnection(); 1499 // Add a small number of failures for each failure type after the SW build change 1500 for (int i = 0; i < mDeviceConfigFacade.getAuthFailureCountMin() - 1; i++) { 1501 makeShortConnectionExample(/*addFwAlert*/false); 1502 makeAssocTimeOutExample(); 1503 makeAuthFailureExample(); 1504 } 1505 1506 FailureStats statsDec = new FailureStats(); 1507 FailureStats statsInc = new FailureStats(); 1508 FailureStats statsHigh = new FailureStats(); 1509 int detectionFlag = perNetwork.dailyDetection(statsDec, statsInc, statsHigh); 1510 assertEquals(WifiScoreCard.SUFFICIENT_RECENT_PREV_STATS, detectionFlag); 1511 checkStatsDeltaExample(statsDec, 0); 1512 checkStatsDeltaExample(statsInc, 0); 1513 checkStatsDeltaExample(statsHigh, 0); 1514 assertEquals(WifiHealthMonitor.REASON_NO_FAILURE, 1515 mWifiScoreCard.detectAbnormalConnectionFailure(mWifiInfo.getSSID())); 1516 } 1517 1518 /** 1519 * Run a few days with bad connections, followed by a SW build change which results 1520 * in performance improvement. Check if the improvement is detected properly. 1521 */ 1522 @Test testImprovementAfterSwBuildChange()1523 public void testImprovementAfterSwBuildChange() throws Exception { 1524 PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); 1525 for (int i = 0; i < 2; i++) { 1526 makeRecentStatsWithShortConnection(); 1527 makeRecentStatsWithAssocTimeOut(); 1528 makeRecentStatsWithAuthFailure(); 1529 perNetwork.updateAfterDailyDetection(); 1530 } 1531 1532 perNetwork.updateAfterSwBuildChange(); 1533 // Add <50% failures after the SW build change 1534 int numGoodConnectionDays = 4; 1535 for (int i = 0; i < numGoodConnectionDays; i++) { 1536 makeRecentStatsWithGoodConnection(); 1537 } 1538 makeRecentStatsWithAssocTimeOut(); 1539 makeRecentStatsWithAuthFailure(); 1540 makeRecentStatsWithShortConnection(); 1541 1542 assertEquals(WifiHealthMonitor.REASON_NO_FAILURE, 1543 mWifiScoreCard.detectAbnormalConnectionFailure(mWifiInfo.getSSID())); 1544 FailureStats statsDec = new FailureStats(); 1545 FailureStats statsInc = new FailureStats(); 1546 FailureStats statsHigh = new FailureStats(); 1547 perNetwork.dailyDetection(statsDec, statsInc, statsHigh); 1548 checkStatsDeltaExample(statsDec, 1); 1549 checkStatsDeltaExample(statsInc, 0); 1550 checkStatsDeltaExample(statsHigh, 0); 1551 } 1552 1553 @Test testPoorConnectionWithoutHistory()1554 public void testPoorConnectionWithoutHistory() throws Exception { 1555 PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); 1556 1557 makeRecentStatsWithShortConnection(); // Day 1 1558 makeRecentStatsWithAuthFailure(); 1559 makeRecentStatsWithAssocTimeOut(); 1560 1561 assertEquals(WifiHealthMonitor.REASON_ASSOC_TIMEOUT, 1562 mWifiScoreCard.detectAbnormalConnectionFailure(mWifiInfo.getSSID())); 1563 FailureStats statsDec = new FailureStats(); 1564 FailureStats statsInc = new FailureStats(); 1565 FailureStats statsHigh = new FailureStats(); 1566 int detectionFlag = perNetwork.dailyDetection(statsDec, statsInc, statsHigh); 1567 assertEquals(WifiScoreCard.SUFFICIENT_RECENT_STATS_ONLY, detectionFlag); 1568 checkStatsDeltaExample(statsDec, 0); 1569 checkStatsDeltaExample(statsInc, 0); 1570 checkStatsDeltaExample(statsHigh, 1); 1571 } 1572 1573 @Test testHighAuthFailureRate()1574 public void testHighAuthFailureRate() throws Exception { 1575 makeRecentStatsWithGoodConnection(); 1576 makeRecentStatsWithAuthFailure(); 1577 assertEquals(WifiHealthMonitor.REASON_AUTH_FAILURE, 1578 mWifiScoreCard.detectAbnormalConnectionFailure(mWifiInfo.getSSID())); 1579 } 1580 1581 @Test testAddGetFrequencies()1582 public void testAddGetFrequencies() { 1583 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 1584 PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); 1585 millisecondsPass(100); 1586 perNetwork.addFrequency(5805); 1587 millisecondsPass(1000); 1588 perNetwork.addFrequency(2432); 1589 assertEquals(2, perNetwork.getFrequencies(Long.MAX_VALUE).size()); 1590 assertEquals(2432, (int) perNetwork.getFrequencies(Long.MAX_VALUE).get(0)); 1591 assertEquals(5805, (int) perNetwork.getFrequencies(Long.MAX_VALUE).get(1)); 1592 // Check over aged channel will not return. 1593 assertEquals(1, perNetwork.getFrequencies(900L).size()); 1594 assertEquals(2432, (int) perNetwork.getFrequencies(Long.MAX_VALUE).get(0)); 1595 } 1596 addTotalBytes(long txBytes, long rxBytes)1597 private void addTotalBytes(long txBytes, long rxBytes) { 1598 mTotalTxBytes += txBytes; 1599 mTotalRxBytes += rxBytes; 1600 } 1601 subtractTotalBytes(long txBytes, long rxBytes)1602 private void subtractTotalBytes(long txBytes, long rxBytes) { 1603 mTotalTxBytes -= txBytes; 1604 mTotalRxBytes -= rxBytes; 1605 } 1606 1607 @Test testLinkBandwidthTwoRadioStatsVariousTxTraffic()1608 public void testLinkBandwidthTwoRadioStatsVariousTxTraffic() { 1609 mWifiInfo.setRssi(-70); 1610 mWifiInfo.setFrequency(2437); 1611 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 1612 PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); 1613 mNewLlStats.on_time = 3000; 1614 mOldLlStats.radioStats = new WifiLinkLayerStats.RadioStat[2]; 1615 mOldLlStats.radioStats[0] = new WifiLinkLayerStats.RadioStat(); 1616 mOldLlStats.radioStats[1] = new WifiLinkLayerStats.RadioStat(); 1617 mNewLlStats.radioStats = new WifiLinkLayerStats.RadioStat[2]; 1618 mNewLlStats.radioStats[0] = new WifiLinkLayerStats.RadioStat(); 1619 mNewLlStats.radioStats[1] = new WifiLinkLayerStats.RadioStat(); 1620 mNewLlStats.radioStats[0].on_time = 500; 1621 mNewLlStats.radioStats[1].on_time = 500; 1622 mOldLlStats.timeStampInMs = 7_000; 1623 mNewLlStats.timeStampInMs = 10_000; 1624 long txBytes = 350_000L; 1625 long rxBytes = 4_000_000L; 1626 for (int i = 0; i < BANDWIDTH_STATS_COUNT_THR - 1; i++) { 1627 addTotalBytes(txBytes, rxBytes); 1628 millisecondsPass(3_000); 1629 perNetwork.updateLinkBandwidth(mOldLlStats, mNewLlStats, mWifiInfo, mTotalTxBytes, 1630 mTotalRxBytes); 1631 } 1632 1633 assertEquals(10_000, perNetwork.getTxLinkBandwidthKbps()); 1634 assertEquals(32_000, perNetwork.getRxLinkBandwidthKbps()); 1635 1636 txBytes = 400_000L; 1637 rxBytes = 200_000L; 1638 for (int i = 0; i < BANDWIDTH_STATS_COUNT_THR - 1; i++) { 1639 addTotalBytes(txBytes, rxBytes); 1640 millisecondsPass(3_000); 1641 perNetwork.updateLinkBandwidth(mOldLlStats, mNewLlStats, mWifiInfo, mTotalTxBytes, 1642 mTotalRxBytes); 1643 } 1644 1645 assertEquals(3_200, perNetwork.getTxLinkBandwidthKbps()); 1646 } 1647 1648 @Test testLinkBandwidthTwoBssidThreeSignalLevelOneBand()1649 public void testLinkBandwidthTwoBssidThreeSignalLevelOneBand() { 1650 mWifiInfo.setRssi(-70); 1651 mWifiInfo.setFrequency(2437); 1652 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 1653 PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); 1654 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 1655 mNewLlStats.on_time = 1000; 1656 mOldLlStats.timeStampInMs = 7_000; 1657 mNewLlStats.timeStampInMs = 10_000; 1658 long txBytes = 2_000_000L; 1659 long rxBytes = 4_000_000L; 1660 // Add BANDWIDTH_STATS_COUNT_THR - 2 polls at BSSID 1 at 1st level 1661 for (int i = 0; i < BANDWIDTH_STATS_COUNT_THR - 2; i++) { 1662 addTotalBytes(txBytes, rxBytes); 1663 millisecondsPass(3_000); 1664 perNetwork.updateLinkBandwidth(mOldLlStats, mNewLlStats, mWifiInfo, mTotalTxBytes, 1665 mTotalRxBytes); 1666 } 1667 // Add BANDWIDTH_STATS_COUNT_THR - 2 polls at BSSID 2 at 2nd level 1668 mWifiInfo.setBSSID(TEST_BSSID_2.toString()); 1669 mNewLlStats.on_time = 2000; 1670 mWifiInfo.setRssi(-54); 1671 txBytes = 6_000_000L; 1672 rxBytes = 100_000L; 1673 for (int i = 0; i < BANDWIDTH_STATS_COUNT_THR - 2; i++) { 1674 addTotalBytes(txBytes, rxBytes); 1675 millisecondsPass(3_000); 1676 perNetwork.updateLinkBandwidth(mOldLlStats, mNewLlStats, mWifiInfo, mTotalTxBytes, 1677 mTotalRxBytes); 1678 } 1679 1680 // Add BANDWIDTH_STATS_COUNT_THR - 2 polls at BSSID 2 at 3rd level 1681 rxBytes = 4_000_000L; 1682 mWifiInfo.setRssi(-65); 1683 for (int i = 0; i < BANDWIDTH_STATS_COUNT_THR - 2; i++) { 1684 addTotalBytes(txBytes, rxBytes); 1685 millisecondsPass(3_000); 1686 perNetwork.updateLinkBandwidth(mOldLlStats, mNewLlStats, mWifiInfo, mTotalTxBytes, 1687 mTotalRxBytes); 1688 } 1689 1690 assertEquals(23_619, perNetwork.getTxLinkBandwidthKbps()); 1691 assertEquals(16_677, perNetwork.getRxLinkBandwidthKbps()); 1692 } 1693 1694 1695 @Test testLinkBandwidthAfterLongTimeGap()1696 public void testLinkBandwidthAfterLongTimeGap() { 1697 mWifiInfo.setRssi(-70); 1698 mWifiInfo.setFrequency(2437); 1699 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 1700 PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); 1701 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 1702 mNewLlStats.on_time = 1000; 1703 mOldLlStats.timeStampInMs = 7_000; 1704 mNewLlStats.timeStampInMs = 10_000; 1705 long txBytes = 2_000_000L; 1706 long rxBytes = 4_000_000L; 1707 // Add BANDWIDTH_STATS_COUNT_THR polls with regular interval 1708 for (int i = 0; i < BANDWIDTH_STATS_COUNT_THR * 2; i++) { 1709 addTotalBytes(txBytes * i, rxBytes * i); 1710 millisecondsPass(3_000); 1711 perNetwork.updateLinkBandwidth(mOldLlStats, mNewLlStats, mWifiInfo, mTotalTxBytes, 1712 mTotalRxBytes); 1713 } 1714 // One update with a very large time interval 1715 mWifiInfo.setRssi(-64); 1716 addTotalBytes(txBytes, rxBytes); 1717 millisecondsPass(26 * 24 * 3_600_000L); 1718 perNetwork.updateLinkBandwidth(mOldLlStats, mNewLlStats, mWifiInfo, mTotalTxBytes, 1719 mTotalRxBytes); 1720 assertEquals(16_000, perNetwork.getTxLinkBandwidthKbps()); 1721 assertEquals(32_000, perNetwork.getRxLinkBandwidthKbps()); 1722 } 1723 1724 @Test testLinkBandwidthInvalidTrafficStats()1725 public void testLinkBandwidthInvalidTrafficStats() { 1726 mWifiInfo.setRssi(-70); 1727 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 1728 PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); 1729 mWifiInfo.setFrequency(5210); 1730 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 1731 mNewLlStats.on_time = 1000; 1732 mOldLlStats.timeStampInMs = 7_000; 1733 mNewLlStats.timeStampInMs = 10_000; 1734 long txBytes = 2_000_000L; 1735 long rxBytes = 100_000L; 1736 int[] reportedKbps = new int[]{400_000, 300_000}; 1737 int[] l2Kbps = new int[]{800_000, 700_000}; 1738 // Add BANDWIDTH_STATS_COUNT_THR polls with one of them has invalid traffic stats 1739 for (int i = 0; i < BANDWIDTH_STATS_COUNT_THR; i++) { 1740 if (i == 1) { 1741 subtractTotalBytes(txBytes, rxBytes); 1742 } else { 1743 addTotalBytes(txBytes, rxBytes); 1744 } 1745 millisecondsPass(3_000); 1746 perNetwork.updateLinkBandwidth(mOldLlStats, mNewLlStats, mWifiInfo, mTotalTxBytes, 1747 mTotalRxBytes); 1748 perNetwork.updateBwMetrics(reportedKbps, l2Kbps); 1749 } 1750 1751 assertEquals(16_000, perNetwork.getTxLinkBandwidthKbps()); 1752 assertEquals(LINK_BANDWIDTH_INIT_KBPS[1][LINK_RX][2], perNetwork.getRxLinkBandwidthKbps()); 1753 BandwidthEstimatorStats stats = mWifiScoreCard.dumpBandwidthEstimatorStats(); 1754 assertEquals(0, stats.stats2G.tx.level.length); 1755 assertEquals(0, stats.stats2G.rx.level.length); 1756 } 1757 1758 @Test testLinkBandwidthOneBssidTwoSignalLevelTwoBand()1759 public void testLinkBandwidthOneBssidTwoSignalLevelTwoBand() { 1760 mWifiInfo.setRssi(-70); 1761 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 1762 PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); 1763 mWifiInfo.setFrequency(5210); 1764 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 1765 mNewLlStats.on_time = 1000; 1766 mOldLlStats.timeStampInMs = 7_000; 1767 mNewLlStats.timeStampInMs = 10_000; 1768 long txBytes = 2_000_000L; 1769 long rxBytes = 100_000L; 1770 int [] reportedKbps = new int[]{40_000, 30_000}; 1771 int [] l2Kbps = new int[]{80_000, 70_000}; 1772 // Add BANDWIDTH_STATS_COUNT_THR polls at 1st level and 1st band 1773 for (int i = 0; i < BANDWIDTH_STATS_COUNT_THR; i++) { 1774 addTotalBytes(txBytes, rxBytes); 1775 millisecondsPass(3_000); 1776 perNetwork.updateLinkBandwidth(mOldLlStats, mNewLlStats, mWifiInfo, mTotalTxBytes, 1777 mTotalRxBytes); 1778 perNetwork.updateBwMetrics(reportedKbps, l2Kbps); 1779 } 1780 // Add BANDWIDTH_STATS_COUNT_THR polls at 2nd level and 1st band 1781 mWifiInfo.setRssi(-65); 1782 rxBytes = 7_000_000L; 1783 for (int i = 0; i < BANDWIDTH_STATS_COUNT_THR; i++) { 1784 addTotalBytes(txBytes, rxBytes); 1785 millisecondsPass(3_000); 1786 perNetwork.updateLinkBandwidth(mOldLlStats, mNewLlStats, mWifiInfo, mTotalTxBytes, 1787 mTotalRxBytes); 1788 perNetwork.updateBwMetrics(reportedKbps, l2Kbps); 1789 } 1790 1791 // Add BANDWIDTH_STATS_COUNT_THR * 2 polls at 1st level and 2nd band 1792 mWifiInfo.setRssi(-70); 1793 mWifiInfo.setFrequency(2437); 1794 txBytes = 6_000_000L; 1795 mNewLlStats.on_time = 2000; 1796 for (int i = 0; i < (2 * BANDWIDTH_STATS_COUNT_THR); i++) { 1797 addTotalBytes(txBytes, rxBytes); 1798 millisecondsPass(3_000); 1799 perNetwork.updateLinkBandwidth(mOldLlStats, mNewLlStats, mWifiInfo, mTotalTxBytes, 1800 mTotalRxBytes); 1801 perNetwork.updateBwMetrics(reportedKbps, l2Kbps); 1802 } 1803 1804 // Expect stats of 1st level and 2nd band are used 1805 assertEquals(23_949, perNetwork.getTxLinkBandwidthKbps()); 1806 assertEquals(28_173, perNetwork.getRxLinkBandwidthKbps()); 1807 1808 BandwidthEstimatorStats stats = mWifiScoreCard.dumpBandwidthEstimatorStats(); 1809 assertEquals(1, stats.stats2G.tx.level.length); 1810 assertEquals(1, stats.stats2G.rx.level.length); 1811 1812 assertEquals(2, stats.stats2G.rx.level[0].signalLevel); 1813 assertEquals(BANDWIDTH_STATS_COUNT_THR - 1, stats.stats2G.rx.level[0].count); 1814 assertEquals(28_000, stats.stats2G.rx.level[0].avgBandwidthKbps); 1815 assertEquals(150, stats.stats2G.rx.level[0].l2ErrorPercent); 1816 assertEquals(7, stats.stats2G.rx.level[0].bandwidthEstErrorPercent); 1817 1818 assertEquals(2, stats.stats2G.tx.level[0].signalLevel); 1819 assertEquals(BANDWIDTH_STATS_COUNT_THR - 1, stats.stats2G.tx.level[0].count); 1820 assertEquals(24_000, stats.stats2G.tx.level[0].avgBandwidthKbps); 1821 assertEquals(233, stats.stats2G.tx.level[0].l2ErrorPercent); 1822 assertEquals(66, stats.stats2G.tx.level[0].bandwidthEstErrorPercent); 1823 1824 assertEquals(0, stats.statsAbove2G.tx.level.length); 1825 assertEquals(0, stats.statsAbove2G.rx.level.length); 1826 } 1827 1828 @Test testLinkBandwidthLargeByteCountReturnNonNegativeValue()1829 public void testLinkBandwidthLargeByteCountReturnNonNegativeValue() { 1830 mWifiInfo.setRssi(-70); 1831 mWifiInfo.setRxLinkSpeedMbps(200_000); 1832 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 1833 PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); 1834 mWifiInfo.setFrequency(5210); 1835 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 1836 mOldLlStats.timeStampInMs = 7_000; 1837 mNewLlStats.timeStampInMs = 10_000; 1838 long txBytes = 8_000_000_000L; 1839 long rxBytes = 16_000_000_000L; 1840 int [] reportedKbps = new int[]{400_000, 300_000}; 1841 int [] l2Kbps = new int[]{800_000, 700_000}; 1842 1843 // Report a small on_time so that the calculated BW overflows at 5G 1844 mNewLlStats.on_time = 10; 1845 for (int i = 0; i < BANDWIDTH_STATS_COUNT_THR + 2; i++) { 1846 addTotalBytes(txBytes, rxBytes); 1847 millisecondsPass(3_000); 1848 perNetwork.updateLinkBandwidth(mOldLlStats, mNewLlStats, mWifiInfo, mTotalTxBytes, 1849 mTotalRxBytes); 1850 perNetwork.updateBwMetrics(reportedKbps, l2Kbps); 1851 } 1852 // Report a larger on_time so that the calculated BW won't overflows at 2G 1853 mWifiInfo.setFrequency(2412); 1854 mNewLlStats.on_time = 1000; 1855 for (int i = 0; i < BANDWIDTH_STATS_COUNT_THR + 2; i++) { 1856 addTotalBytes(txBytes, rxBytes); 1857 millisecondsPass(3_000); 1858 perNetwork.updateLinkBandwidth(mOldLlStats, mNewLlStats, mWifiInfo, mTotalTxBytes, 1859 mTotalRxBytes); 1860 perNetwork.updateBwMetrics(reportedKbps, l2Kbps); 1861 } 1862 1863 // Report cold start BW for Tx because the calculated value is higher than 1864 // txLinkSpeedMbps. 1865 assertEquals(10_000, perNetwork.getTxLinkBandwidthKbps()); 1866 assertEquals(128_000_000, perNetwork.getRxLinkBandwidthKbps()); 1867 1868 BandwidthEstimatorStats stats = mWifiScoreCard.dumpBandwidthEstimatorStats(); 1869 assertEquals(0, stats.statsAbove2G.tx.level.length); 1870 assertEquals(0, stats.statsAbove2G.rx.level.length); 1871 assertEquals(0, stats.stats2G.tx.level.length); 1872 assertEquals(1, stats.stats2G.rx.level.length); 1873 assertEquals(128_000_000, stats.stats2G.rx.level[0].avgBandwidthKbps); 1874 assertEquals(1, stats.stats2G.rx.level[0].count); 1875 1876 mNewLlStats.on_time = 2000; 1877 for (int i = 0; i < BANDWIDTH_STATS_COUNT_THR + 2; i++) { 1878 addTotalBytes(txBytes, rxBytes); 1879 millisecondsPass(3_000); 1880 perNetwork.updateLinkBandwidth(mOldLlStats, mNewLlStats, mWifiInfo, mTotalTxBytes, 1881 mTotalRxBytes); 1882 perNetwork.updateBwMetrics(reportedKbps, l2Kbps); 1883 } 1884 stats = mWifiScoreCard.dumpBandwidthEstimatorStats(); 1885 assertEquals(64_000_000, stats.stats2G.rx.level[0].avgBandwidthKbps); 1886 assertEquals(BANDWIDTH_STATS_COUNT_THR + 2, stats.stats2G.rx.level[0].count); 1887 } 1888 1889 @Test testLinkBandwidthInvalidBytes()1890 public void testLinkBandwidthInvalidBytes() { 1891 mWifiInfo.setRssi(-70); 1892 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 1893 PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); 1894 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 1895 mOldLlStats.timeStampInMs = 7_000; 1896 mNewLlStats.timeStampInMs = 10_000; 1897 long txBytes = 8_000_000_000L; 1898 long rxBytes = 16_000_000_000L; 1899 mWifiInfo.setFrequency(2412); 1900 mNewLlStats.on_time = 1000; 1901 for (int i = 0; i < BANDWIDTH_STATS_COUNT_THR + 2; i++) { 1902 addTotalBytes(txBytes, rxBytes); 1903 millisecondsPass(3_000); 1904 perNetwork.updateLinkBandwidth(mOldLlStats, mNewLlStats, mWifiInfo, mTotalTxBytes, 1905 mTotalRxBytes); 1906 } 1907 assertEquals(10_000, perNetwork.getTxLinkBandwidthKbps()); 1908 assertEquals(10_000, perNetwork.getRxLinkBandwidthKbps()); 1909 } 1910 1911 @Test testLinkBandwidthLowOnTimeHighSignalLevel()1912 public void testLinkBandwidthLowOnTimeHighSignalLevel() { 1913 // Add polls with zero on_time and high signal level 1914 mWifiInfo.setRssi(-53); 1915 int signalLevel = RssiUtil.calculateSignalLevel(mContext, mWifiInfo.getRssi()); 1916 mWifiInfo.setFrequency(5210); 1917 mWifiScoreCard.noteConnectionAttempt(mWifiInfo, -53, mWifiInfo.getSSID()); 1918 PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); 1919 mWifiInfo.setFrequency(5210); 1920 mWifiScoreCard.noteIpConfiguration(mWifiInfo); 1921 mNewLlStats.on_time = 5; 1922 mOldLlStats.timeStampInMs = 7_000; 1923 mNewLlStats.timeStampInMs = 10_000; 1924 long txBytes = 2_000_000L; 1925 long rxBytes = 100_000L; 1926 for (int i = 0; i < BANDWIDTH_STATS_COUNT_THR; i++) { 1927 addTotalBytes(txBytes, rxBytes); 1928 millisecondsPass(3_000); 1929 perNetwork.updateLinkBandwidth(mOldLlStats, mNewLlStats, mWifiInfo, mTotalTxBytes, 1930 mTotalRxBytes); 1931 } 1932 1933 // Expect cold-start value 1934 assertEquals(LINK_BANDWIDTH_INIT_KBPS[1][LINK_TX][signalLevel], 1935 perNetwork.getTxLinkBandwidthKbps()); 1936 assertEquals(LINK_BANDWIDTH_INIT_KBPS[1][LINK_RX][signalLevel], 1937 perNetwork.getRxLinkBandwidthKbps()); 1938 } 1939 1940 @Test testGetLinkBandwidthWithoutUpdateReturnLevel0Band0Value()1941 public void testGetLinkBandwidthWithoutUpdateReturnLevel0Band0Value() { 1942 PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID()); 1943 1944 // Call getLinkBandwidth() without updateLinkBandwidth() 1945 // Expect cold-start value at level 0 and band 0 1946 assertEquals(LINK_BANDWIDTH_INIT_KBPS[0][LINK_TX][0], 1947 perNetwork.getTxLinkBandwidthKbps()); 1948 assertEquals(LINK_BANDWIDTH_INIT_KBPS[0][LINK_RX][0], 1949 perNetwork.getRxLinkBandwidthKbps()); 1950 } 1951 } 1952