WifiMetricsTest.java revision 031cdffdaf223772d4ea52569ec7a08d00013208
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 */ 16package com.android.server.wifi; 17 18import static org.junit.Assert.assertEquals; 19import static org.junit.Assert.assertTrue; 20import static org.mockito.Mockito.*; 21 22import android.net.NetworkAgent; 23import android.net.wifi.ScanResult; 24import android.net.wifi.SupplicantState; 25import android.net.wifi.WifiConfiguration; 26import android.net.wifi.WifiManager; 27import android.net.wifi.WifiSsid; 28import android.os.Handler; 29import android.os.test.TestLooper; 30import android.test.suitebuilder.annotation.SmallTest; 31import android.util.Base64; 32 33 34import com.android.server.wifi.hotspot2.NetworkDetail; 35import com.android.server.wifi.nano.WifiMetricsProto; 36import com.android.server.wifi.nano.WifiMetricsProto.StaEvent; 37 38import org.junit.Before; 39import org.junit.Test; 40import org.mockito.Mock; 41import org.mockito.MockitoAnnotations; 42 43import java.io.ByteArrayOutputStream; 44import java.io.FileDescriptor; 45import java.io.PrintWriter; 46import java.io.StringWriter; 47import java.util.ArrayList; 48import java.util.BitSet; 49import java.util.List; 50import java.util.regex.Matcher; 51import java.util.regex.Pattern; 52 53/** 54 * Unit tests for {@link com.android.server.wifi.WifiMetrics}. 55 */ 56@SmallTest 57public class WifiMetricsTest { 58 59 WifiMetrics mWifiMetrics; 60 WifiMetricsProto.WifiLog mDeserializedWifiMetrics; 61 TestLooper mTestLooper; 62 @Mock Clock mClock; 63 64 @Before 65 public void setUp() throws Exception { 66 MockitoAnnotations.initMocks(this); 67 mDeserializedWifiMetrics = null; 68 when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 0); 69 mTestLooper = new TestLooper(); 70 mWifiMetrics = new WifiMetrics(mClock, mTestLooper.getLooper()); 71 } 72 73 /** 74 * Test that startConnectionEvent and endConnectionEvent can be called repeatedly and out of 75 * order. Only tests no exception occurs. Creates 3 ConnectionEvents. 76 */ 77 @Test 78 public void startAndEndConnectionEventSucceeds() throws Exception { 79 //Start and end Connection event 80 mWifiMetrics.startConnectionEvent(null, "RED", 81 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 82 mWifiMetrics.endConnectionEvent( 83 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, 84 WifiMetricsProto.ConnectionEvent.HLF_DHCP); 85 //end Connection event without starting one 86 mWifiMetrics.endConnectionEvent( 87 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, 88 WifiMetricsProto.ConnectionEvent.HLF_DHCP); 89 //start two ConnectionEvents in a row 90 mWifiMetrics.startConnectionEvent(null, "BLUE", 91 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 92 mWifiMetrics.startConnectionEvent(null, "GREEN", 93 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 94 } 95 96 private static final long TEST_RECORD_DURATION_SEC = 12 * 60 * 60; 97 private static final long TEST_RECORD_DURATION_MILLIS = TEST_RECORD_DURATION_SEC * 1000; 98 99 /** 100 * Simulate how dumpsys gets the proto from mWifiMetrics, filter the proto bytes out and 101 * deserialize them into mDeserializedWifiMetrics 102 */ 103 public void dumpProtoAndDeserialize() throws Exception { 104 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 105 PrintWriter writer = new PrintWriter(stream); 106 String[] args = new String[0]; 107 108 when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_RECORD_DURATION_MILLIS); 109 //Test proto dump, by passing in proto arg option 110 args = new String[]{WifiMetrics.PROTO_DUMP_ARG}; 111 mWifiMetrics.dump(null, writer, args); 112 writer.flush(); 113 Pattern pattern = Pattern.compile( 114 "(?<=WifiMetrics:\\n)([\\s\\S]*)(?=EndWifiMetrics)"); 115 Matcher matcher = pattern.matcher(stream.toString()); 116 assertTrue("Proto Byte string found in WifiMetrics.dump():\n" + stream.toString(), 117 matcher.find()); 118 String protoByteString = matcher.group(1); 119 byte[] protoBytes = Base64.decode(protoByteString, Base64.DEFAULT); 120 mDeserializedWifiMetrics = WifiMetricsProto.WifiLog.parseFrom(protoBytes); 121 } 122 123 /** 124 * Gets the 'clean dump' proto bytes from mWifiMetrics & deserializes it into 125 * mDeserializedWifiMetrics 126 */ 127 public void cleanDumpProtoAndDeserialize() throws Exception { 128 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 129 PrintWriter writer = new PrintWriter(stream); 130 String[] args = new String[0]; 131 132 when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_RECORD_DURATION_MILLIS); 133 //Test proto dump, by passing in proto arg option 134 args = new String[]{WifiMetrics.PROTO_DUMP_ARG, WifiMetrics.CLEAN_DUMP_ARG}; 135 mWifiMetrics.dump(null, writer, args); 136 writer.flush(); 137 String protoByteString = stream.toString(); 138 byte[] protoBytes = Base64.decode(protoByteString, Base64.DEFAULT); 139 mDeserializedWifiMetrics = WifiMetricsProto.WifiLog.parseFrom(protoBytes); 140 } 141 142 /** Verifies that dump() includes the expected header */ 143 @Test 144 public void stateDumpIncludesHeader() throws Exception { 145 assertStringContains(getStateDump(), "WifiMetrics"); 146 } 147 148 /** Verifies that dump() includes correct alert count when there are no alerts. */ 149 @Test 150 public void stateDumpAlertCountIsCorrectWithNoAlerts() throws Exception { 151 assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=()"); 152 } 153 154 /** Verifies that dump() includes correct alert count when there is one alert. */ 155 @Test 156 public void stateDumpAlertCountIsCorrectWithOneAlert() throws Exception { 157 mWifiMetrics.incrementAlertReasonCount(1); 158 assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=(1,1)"); 159 } 160 161 /** Verifies that dump() includes correct alert count when there are multiple alerts. */ 162 @Test 163 public void stateDumpAlertCountIsCorrectWithMultipleAlerts() throws Exception { 164 mWifiMetrics.incrementAlertReasonCount(1); 165 mWifiMetrics.incrementAlertReasonCount(1); 166 mWifiMetrics.incrementAlertReasonCount(16); 167 assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=(1,2),(16,1)"); 168 } 169 170 @Test 171 public void testDumpProtoAndDeserialize() throws Exception { 172 setAndIncrementMetrics(); 173 dumpProtoAndDeserialize(); 174 assertDeserializedMetricsCorrect(); 175 } 176 177 private static final int NUM_OPEN_NETWORKS = 2; 178 private static final int NUM_PERSONAL_NETWORKS = 3; 179 private static final int NUM_ENTERPRISE_NETWORKS = 5; 180 private static final int NUM_SAVED_NETWORKS = NUM_OPEN_NETWORKS + NUM_PERSONAL_NETWORKS 181 + NUM_ENTERPRISE_NETWORKS; 182 private static final int NUM_HIDDEN_NETWORKS = NUM_OPEN_NETWORKS; 183 private static final int NUM_PASSPOINT_NETWORKS = NUM_ENTERPRISE_NETWORKS; 184 private static final int NUM_NETWORKS_ADDED_BY_USER = 1; 185 private static final int NUM_NETWORKS_ADDED_BY_APPS = NUM_SAVED_NETWORKS 186 - NUM_NETWORKS_ADDED_BY_USER; 187 private static final boolean TEST_VAL_IS_LOCATION_ENABLED = true; 188 private static final boolean IS_SCANNING_ALWAYS_ENABLED = true; 189 private static final int NUM_EMPTY_SCAN_RESULTS = 19; 190 private static final int NUM_NON_EMPTY_SCAN_RESULTS = 23; 191 private static final int NUM_SCAN_UNKNOWN = 1; 192 private static final int NUM_SCAN_SUCCESS = 2; 193 private static final int NUM_SCAN_FAILURE_INTERRUPTED = 3; 194 private static final int NUM_SCAN_FAILURE_INVALID_CONFIGURATION = 5; 195 private static final int NUM_WIFI_UNKNOWN_SCREEN_OFF = 3; 196 private static final int NUM_WIFI_UNKNOWN_SCREEN_ON = 5; 197 private static final int NUM_WIFI_ASSOCIATED_SCREEN_OFF = 7; 198 private static final int NUM_WIFI_ASSOCIATED_SCREEN_ON = 11; 199 private static final int NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD = 11; 200 private static final int NUM_CONNECTIVITY_WATCHDOG_PNO_BAD = 12; 201 private static final int NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD = 13; 202 private static final int NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD = 14; 203 private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS = 1; 204 private static final int NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL = 2; 205 private static final int NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL = 3; 206 private static final int NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL = 4; 207 private static final int NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL = 5; 208 private static final int NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL = 6; 209 private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION = 7; 210 private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION = 8; 211 private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP = 9; 212 private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER = 10; 213 private static final int NUM_LAST_RESORT_WATCHDOG_SUCCESSES = 5; 214 private static final int NUM_RSSI_LEVELS_TO_INCREMENT = 20; 215 private static final int FIRST_RSSI_LEVEL = -80; 216 private static final int NUM_OPEN_NETWORK_SCAN_RESULTS = 1; 217 private static final int NUM_PERSONAL_NETWORK_SCAN_RESULTS = 4; 218 private static final int NUM_ENTERPRISE_NETWORK_SCAN_RESULTS = 3; 219 private static final int NUM_HIDDEN_NETWORK_SCAN_RESULTS = 1; 220 private static final int NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS = 1; 221 private static final int NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS = 2; 222 private static final int NUM_SCANS = 5; 223 private static final int NUM_TOTAL_SCAN_RESULTS = 8; 224 private static final int MIN_RSSI_LEVEL = -127; 225 private static final int MAX_RSSI_LEVEL = 0; 226 private static final int WIFI_SCORE_RANGE_MIN = 0; 227 private static final int NUM_WIFI_SCORES_TO_INCREMENT = 20; 228 private static final int WIFI_SCORE_RANGE_MAX = 60; 229 private static final int NUM_OUT_OF_BOUND_ENTRIES = 10; 230 private static final int MAX_NUM_SOFTAP_RETURN_CODES = 3; 231 private static final int NUM_SOFTAP_START_SUCCESS = 3; 232 private static final int NUM_SOFTAP_FAILED_GENERAL_ERROR = 2; 233 private static final int NUM_SOFTAP_FAILED_NO_CHANNEL = 1; 234 235 private ScanDetail buildMockScanDetail(boolean hidden, NetworkDetail.HSRelease hSRelease, 236 String capabilities) { 237 ScanDetail mockScanDetail = mock(ScanDetail.class); 238 NetworkDetail mockNetworkDetail = mock(NetworkDetail.class); 239 ScanResult mockScanResult = mock(ScanResult.class); 240 when(mockScanDetail.getNetworkDetail()).thenReturn(mockNetworkDetail); 241 when(mockScanDetail.getScanResult()).thenReturn(mockScanResult); 242 when(mockNetworkDetail.isHiddenBeaconFrame()).thenReturn(hidden); 243 when(mockNetworkDetail.getHSRelease()).thenReturn(hSRelease); 244 mockScanResult.capabilities = capabilities; 245 return mockScanDetail; 246 } 247 248 private List<ScanDetail> buildMockScanDetailList() { 249 List<ScanDetail> mockScanDetails = new ArrayList<ScanDetail>(); 250 mockScanDetails.add(buildMockScanDetail(true, null, "[ESS]")); 251 mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-PSK-CCMP][ESS]")); 252 mockScanDetails.add(buildMockScanDetail(false, null, "[WPA-PSK-CCMP]")); 253 mockScanDetails.add(buildMockScanDetail(false, null, "[WPA-PSK-CCMP]")); 254 mockScanDetails.add(buildMockScanDetail(false, null, "[WEP]")); 255 mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R2, 256 "[WPA-EAP-CCMP]")); 257 mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R2, 258 "[WPA2-EAP+FT/EAP-CCMP]")); 259 mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R1, 260 "[WPA-EAP-CCMP]")); 261 return mockScanDetails; 262 } 263 264 private List<WifiConfiguration> buildSavedNetworkList() { 265 List<WifiConfiguration> testSavedNetworks = new ArrayList<WifiConfiguration>(); 266 for (int i = 0; i < NUM_OPEN_NETWORKS; i++) { 267 testSavedNetworks.add(WifiConfigurationTestUtil.createOpenHiddenNetwork()); 268 } 269 for (int i = 0; i < NUM_PERSONAL_NETWORKS; i++) { 270 testSavedNetworks.add(WifiConfigurationTestUtil.createPskNetwork()); 271 } 272 for (int i = 0; i < NUM_ENTERPRISE_NETWORKS; i++) { 273 // Passpoint networks are counted in both Passpoint and Enterprise counters 274 testSavedNetworks.add(WifiConfigurationTestUtil.createPasspointNetwork()); 275 } 276 testSavedNetworks.get(0).selfAdded = true; 277 return testSavedNetworks; 278 } 279 280 /** 281 * Set simple metrics, increment others 282 */ 283 public void setAndIncrementMetrics() throws Exception { 284 mWifiMetrics.updateSavedNetworks(buildSavedNetworkList()); 285 mWifiMetrics.setIsLocationEnabled(TEST_VAL_IS_LOCATION_ENABLED); 286 mWifiMetrics.setIsScanningAlwaysEnabled(IS_SCANNING_ALWAYS_ENABLED); 287 288 for (int i = 0; i < NUM_EMPTY_SCAN_RESULTS; i++) { 289 mWifiMetrics.incrementEmptyScanResultCount(); 290 } 291 for (int i = 0; i < NUM_NON_EMPTY_SCAN_RESULTS; i++) { 292 mWifiMetrics.incrementNonEmptyScanResultCount(); 293 } 294 mWifiMetrics.incrementScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN, 295 NUM_SCAN_UNKNOWN); 296 mWifiMetrics.incrementScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS, 297 NUM_SCAN_SUCCESS); 298 mWifiMetrics.incrementScanReturnEntry( 299 WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED, 300 NUM_SCAN_FAILURE_INTERRUPTED); 301 mWifiMetrics.incrementScanReturnEntry( 302 WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION, 303 NUM_SCAN_FAILURE_INVALID_CONFIGURATION); 304 for (int i = 0; i < NUM_WIFI_UNKNOWN_SCREEN_OFF; i++) { 305 mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, 306 false); 307 } 308 for (int i = 0; i < NUM_WIFI_UNKNOWN_SCREEN_ON; i++) { 309 mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, 310 true); 311 } 312 for (int i = 0; i < NUM_WIFI_ASSOCIATED_SCREEN_OFF; i++) { 313 mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, 314 false); 315 } 316 for (int i = 0; i < NUM_WIFI_ASSOCIATED_SCREEN_ON; i++) { 317 mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, 318 true); 319 } 320 for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD; i++) { 321 mWifiMetrics.incrementNumConnectivityWatchdogPnoGood(); 322 } 323 for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_PNO_BAD; i++) { 324 mWifiMetrics.incrementNumConnectivityWatchdogPnoBad(); 325 } 326 for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD; i++) { 327 mWifiMetrics.incrementNumConnectivityWatchdogBackgroundGood(); 328 } 329 for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD; i++) { 330 mWifiMetrics.incrementNumConnectivityWatchdogBackgroundBad(); 331 } 332 for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS; i++) { 333 mWifiMetrics.incrementNumLastResortWatchdogTriggers(); 334 } 335 mWifiMetrics.addCountToNumLastResortWatchdogBadAssociationNetworksTotal( 336 NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL); 337 mWifiMetrics.addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal( 338 NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL); 339 mWifiMetrics.addCountToNumLastResortWatchdogBadDhcpNetworksTotal( 340 NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL); 341 mWifiMetrics.addCountToNumLastResortWatchdogBadOtherNetworksTotal( 342 NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL); 343 mWifiMetrics.addCountToNumLastResortWatchdogAvailableNetworksTotal( 344 NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL); 345 for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION; i++) { 346 mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadAssociation(); 347 } 348 for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION; i++) { 349 mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadAuthentication(); 350 } 351 for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP; i++) { 352 mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadDhcp(); 353 } 354 for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER; i++) { 355 mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadOther(); 356 } 357 for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_SUCCESSES; i++) { 358 mWifiMetrics.incrementNumLastResortWatchdogSuccesses(); 359 } 360 for (int i = 0; i < NUM_RSSI_LEVELS_TO_INCREMENT; i++) { 361 for (int j = 0; j <= i; j++) { 362 mWifiMetrics.incrementRssiPollRssiCount(MIN_RSSI_LEVEL + i); 363 } 364 } 365 for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) { 366 mWifiMetrics.incrementRssiPollRssiCount(MIN_RSSI_LEVEL - i); 367 } 368 for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) { 369 mWifiMetrics.incrementRssiPollRssiCount(MAX_RSSI_LEVEL + i); 370 } 371 // Test alert-reason clamping. 372 mWifiMetrics.incrementAlertReasonCount(WifiLoggerHal.WIFI_ALERT_REASON_MIN - 1); 373 mWifiMetrics.incrementAlertReasonCount(WifiLoggerHal.WIFI_ALERT_REASON_MAX + 1); 374 // Simple cases for alert reason. 375 mWifiMetrics.incrementAlertReasonCount(1); 376 mWifiMetrics.incrementAlertReasonCount(1); 377 mWifiMetrics.incrementAlertReasonCount(1); 378 mWifiMetrics.incrementAlertReasonCount(2); 379 List<ScanDetail> mockScanDetails = buildMockScanDetailList(); 380 for (int i = 0; i < NUM_SCANS; i++) { 381 mWifiMetrics.countScanResults(mockScanDetails); 382 } 383 for (int score = WIFI_SCORE_RANGE_MIN; score < NUM_WIFI_SCORES_TO_INCREMENT; score++) { 384 for (int offset = 0; offset <= score; offset++) { 385 mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MIN + score); 386 } 387 } 388 for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) { 389 mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MIN - i); 390 } 391 for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) { 392 mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MAX + i); 393 } 394 395 // increment soft ap start return codes 396 for (int i = 0; i < NUM_SOFTAP_START_SUCCESS; i++) { 397 mWifiMetrics.incrementSoftApStartResult(true, 0); 398 } 399 for (int i = 0; i < NUM_SOFTAP_FAILED_GENERAL_ERROR; i++) { 400 mWifiMetrics.incrementSoftApStartResult(false, WifiManager.SAP_START_FAILURE_GENERAL); 401 } 402 for (int i = 0; i < NUM_SOFTAP_FAILED_NO_CHANNEL; i++) { 403 mWifiMetrics.incrementSoftApStartResult(false, 404 WifiManager.SAP_START_FAILURE_NO_CHANNEL); 405 } 406 } 407 408 /** 409 * Assert that values in deserializedWifiMetrics match those set in 'setAndIncrementMetrics' 410 */ 411 public void assertDeserializedMetricsCorrect() throws Exception { 412 assertEquals("mDeserializedWifiMetrics.numSavedNetworks == NUM_SAVED_NETWORKS", 413 mDeserializedWifiMetrics.numSavedNetworks, NUM_SAVED_NETWORKS); 414 assertEquals("mDeserializedWifiMetrics.numOpenNetworks == NUM_OPEN_NETWORKS", 415 mDeserializedWifiMetrics.numOpenNetworks, NUM_OPEN_NETWORKS); 416 assertEquals("mDeserializedWifiMetrics.numPersonalNetworks == NUM_PERSONAL_NETWORKS", 417 mDeserializedWifiMetrics.numPersonalNetworks, NUM_PERSONAL_NETWORKS); 418 assertEquals("mDeserializedWifiMetrics.numEnterpriseNetworks " 419 + "== NUM_ENTERPRISE_NETWORKS", 420 mDeserializedWifiMetrics.numEnterpriseNetworks, NUM_ENTERPRISE_NETWORKS); 421 assertEquals("mDeserializedWifiMetrics.numNetworksAddedByUser " 422 + "== NUM_NETWORKS_ADDED_BY_USER", 423 mDeserializedWifiMetrics.numNetworksAddedByUser, NUM_NETWORKS_ADDED_BY_USER); 424 assertEquals(NUM_HIDDEN_NETWORKS, mDeserializedWifiMetrics.numHiddenNetworks); 425 assertEquals(NUM_PASSPOINT_NETWORKS, mDeserializedWifiMetrics.numPasspointNetworks); 426 assertEquals("mDeserializedWifiMetrics.numNetworksAddedByApps " 427 + "== NUM_NETWORKS_ADDED_BY_APPS", 428 mDeserializedWifiMetrics.numNetworksAddedByApps, NUM_NETWORKS_ADDED_BY_APPS); 429 assertEquals("mDeserializedWifiMetrics.isLocationEnabled == TEST_VAL_IS_LOCATION_ENABLED", 430 mDeserializedWifiMetrics.isLocationEnabled, TEST_VAL_IS_LOCATION_ENABLED); 431 assertEquals("mDeserializedWifiMetrics.isScanningAlwaysEnabled " 432 + "== IS_SCANNING_ALWAYS_ENABLED", 433 mDeserializedWifiMetrics.isScanningAlwaysEnabled, IS_SCANNING_ALWAYS_ENABLED); 434 assertEquals("mDeserializedWifiMetrics.numEmptyScanResults == NUM_EMPTY_SCAN_RESULTS", 435 mDeserializedWifiMetrics.numEmptyScanResults, NUM_EMPTY_SCAN_RESULTS); 436 assertEquals("mDeserializedWifiMetrics.numNonEmptyScanResults == " 437 + "NUM_NON_EMPTY_SCAN_RESULTS", 438 mDeserializedWifiMetrics.numNonEmptyScanResults, NUM_NON_EMPTY_SCAN_RESULTS); 439 assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_UNKNOWN, 440 NUM_SCAN_UNKNOWN); 441 assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_SUCCESS, 442 NUM_SCAN_SUCCESS); 443 assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED, 444 NUM_SCAN_FAILURE_INTERRUPTED); 445 assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION, 446 NUM_SCAN_FAILURE_INVALID_CONFIGURATION); 447 assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, false, 448 NUM_WIFI_UNKNOWN_SCREEN_OFF); 449 assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, true, 450 NUM_WIFI_UNKNOWN_SCREEN_ON); 451 assertSystemStateEntryEquals( 452 WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, false, NUM_WIFI_ASSOCIATED_SCREEN_OFF); 453 assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, true, 454 NUM_WIFI_ASSOCIATED_SCREEN_ON); 455 assertEquals(mDeserializedWifiMetrics.numConnectivityWatchdogPnoGood, 456 NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD); 457 assertEquals(mDeserializedWifiMetrics.numConnectivityWatchdogPnoBad, 458 NUM_CONNECTIVITY_WATCHDOG_PNO_BAD); 459 assertEquals(mDeserializedWifiMetrics.numConnectivityWatchdogBackgroundGood, 460 NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD); 461 assertEquals(mDeserializedWifiMetrics.numConnectivityWatchdogBackgroundBad, 462 NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD); 463 assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS, 464 mDeserializedWifiMetrics.numLastResortWatchdogTriggers); 465 assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL, 466 mDeserializedWifiMetrics.numLastResortWatchdogBadAssociationNetworksTotal); 467 assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL, 468 mDeserializedWifiMetrics.numLastResortWatchdogBadAuthenticationNetworksTotal); 469 assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL, 470 mDeserializedWifiMetrics.numLastResortWatchdogBadDhcpNetworksTotal); 471 assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL, 472 mDeserializedWifiMetrics.numLastResortWatchdogBadOtherNetworksTotal); 473 assertEquals(NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL, 474 mDeserializedWifiMetrics.numLastResortWatchdogAvailableNetworksTotal); 475 assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION, 476 mDeserializedWifiMetrics.numLastResortWatchdogTriggersWithBadAssociation); 477 assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION, 478 mDeserializedWifiMetrics.numLastResortWatchdogTriggersWithBadAuthentication); 479 assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP, 480 mDeserializedWifiMetrics.numLastResortWatchdogTriggersWithBadDhcp); 481 assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER, 482 mDeserializedWifiMetrics.numLastResortWatchdogTriggersWithBadOther); 483 assertEquals(NUM_LAST_RESORT_WATCHDOG_SUCCESSES, 484 mDeserializedWifiMetrics.numLastResortWatchdogSuccesses); 485 assertEquals(TEST_RECORD_DURATION_SEC, 486 mDeserializedWifiMetrics.recordDurationSec); 487 for (int i = 0; i < NUM_RSSI_LEVELS_TO_INCREMENT; i++) { 488 assertEquals(MIN_RSSI_LEVEL + i, mDeserializedWifiMetrics.rssiPollRssiCount[i].rssi); 489 assertEquals(i + 1, mDeserializedWifiMetrics.rssiPollRssiCount[i].count); 490 } 491 StringBuilder sb_rssi = new StringBuilder(); 492 sb_rssi.append("Number of RSSIs = " + mDeserializedWifiMetrics.rssiPollRssiCount.length); 493 assertTrue(sb_rssi.toString(), (mDeserializedWifiMetrics.rssiPollRssiCount.length 494 <= (MAX_RSSI_LEVEL - MIN_RSSI_LEVEL + 1))); 495 assertEquals(2, mDeserializedWifiMetrics.alertReasonCount[0].count); // Clamped reasons. 496 assertEquals(3, mDeserializedWifiMetrics.alertReasonCount[1].count); 497 assertEquals(1, mDeserializedWifiMetrics.alertReasonCount[2].count); 498 assertEquals(3, mDeserializedWifiMetrics.alertReasonCount.length); 499 assertEquals(NUM_TOTAL_SCAN_RESULTS * NUM_SCANS, 500 mDeserializedWifiMetrics.numTotalScanResults); 501 assertEquals(NUM_OPEN_NETWORK_SCAN_RESULTS * NUM_SCANS, 502 mDeserializedWifiMetrics.numOpenNetworkScanResults); 503 assertEquals(NUM_PERSONAL_NETWORK_SCAN_RESULTS * NUM_SCANS, 504 mDeserializedWifiMetrics.numPersonalNetworkScanResults); 505 assertEquals(NUM_ENTERPRISE_NETWORK_SCAN_RESULTS * NUM_SCANS, 506 mDeserializedWifiMetrics.numEnterpriseNetworkScanResults); 507 assertEquals(NUM_HIDDEN_NETWORK_SCAN_RESULTS * NUM_SCANS, 508 mDeserializedWifiMetrics.numHiddenNetworkScanResults); 509 assertEquals(NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS * NUM_SCANS, 510 mDeserializedWifiMetrics.numHotspot2R1NetworkScanResults); 511 assertEquals(NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS * NUM_SCANS, 512 mDeserializedWifiMetrics.numHotspot2R2NetworkScanResults); 513 assertEquals(NUM_SCANS, 514 mDeserializedWifiMetrics.numScans); 515 for (int score_index = 0; score_index < NUM_WIFI_SCORES_TO_INCREMENT; score_index++) { 516 assertEquals(WIFI_SCORE_RANGE_MIN + score_index, 517 mDeserializedWifiMetrics.wifiScoreCount[score_index].score); 518 assertEquals(score_index + 1, 519 mDeserializedWifiMetrics.wifiScoreCount[score_index].count); 520 } 521 StringBuilder sb_wifi_score = new StringBuilder(); 522 sb_wifi_score.append("Number of wifi_scores = " 523 + mDeserializedWifiMetrics.wifiScoreCount.length); 524 assertTrue(sb_wifi_score.toString(), (mDeserializedWifiMetrics.wifiScoreCount.length 525 <= (WIFI_SCORE_RANGE_MAX - WIFI_SCORE_RANGE_MIN + 1))); 526 StringBuilder sb_wifi_limits = new StringBuilder(); 527 sb_wifi_limits.append("Wifi Score limit is " + NetworkAgent.WIFI_BASE_SCORE 528 + ">= " + WIFI_SCORE_RANGE_MAX); 529 assertTrue(sb_wifi_limits.toString(), NetworkAgent.WIFI_BASE_SCORE <= WIFI_SCORE_RANGE_MAX); 530 assertEquals(MAX_NUM_SOFTAP_RETURN_CODES, mDeserializedWifiMetrics.softApReturnCode.length); 531 assertEquals(WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY, 532 mDeserializedWifiMetrics.softApReturnCode[0].startResult); 533 assertEquals(NUM_SOFTAP_START_SUCCESS, mDeserializedWifiMetrics.softApReturnCode[0].count); 534 assertEquals(WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR, 535 mDeserializedWifiMetrics.softApReturnCode[1].startResult); 536 assertEquals(NUM_SOFTAP_FAILED_GENERAL_ERROR, 537 mDeserializedWifiMetrics.softApReturnCode[1].count); 538 assertEquals(WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL, 539 mDeserializedWifiMetrics.softApReturnCode[2].startResult); 540 assertEquals(NUM_SOFTAP_FAILED_NO_CHANNEL, 541 mDeserializedWifiMetrics.softApReturnCode[2].count); 542 } 543 544 /** 545 * Assert deserialized metrics Scan Return Entry equals count 546 */ 547 public void assertScanReturnEntryEquals(int returnCode, int count) { 548 for (int i = 0; i < mDeserializedWifiMetrics.scanReturnEntries.length; i++) { 549 if (mDeserializedWifiMetrics.scanReturnEntries[i].scanReturnCode == returnCode) { 550 assertEquals(mDeserializedWifiMetrics.scanReturnEntries[i].scanResultsCount, count); 551 return; 552 } 553 } 554 assertEquals(null, count); 555 } 556 557 /** 558 * Assert deserialized metrics SystemState entry equals count 559 */ 560 public void assertSystemStateEntryEquals(int state, boolean screenOn, int count) { 561 for (int i = 0; i < mDeserializedWifiMetrics.wifiSystemStateEntries.length; i++) { 562 if (mDeserializedWifiMetrics.wifiSystemStateEntries[i].wifiState == state 563 && mDeserializedWifiMetrics.wifiSystemStateEntries[i].isScreenOn == screenOn) { 564 assertEquals(mDeserializedWifiMetrics.wifiSystemStateEntries[i].wifiStateCount, 565 count); 566 return; 567 } 568 } 569 assertEquals(null, count); 570 } 571 /** 572 * Combination of all other WifiMetrics unit tests, an internal-integration test, or functional 573 * test 574 */ 575 @Test 576 public void setMetricsSerializeDeserializeAssertMetricsSame() throws Exception { 577 setAndIncrementMetrics(); 578 startAndEndConnectionEventSucceeds(); 579 dumpProtoAndDeserialize(); 580 assertDeserializedMetricsCorrect(); 581 assertEquals("mDeserializedWifiMetrics.connectionEvent.length", 582 2, mDeserializedWifiMetrics.connectionEvent.length); 583 //<TODO> test individual connectionEvents for correctness, 584 // check scanReturnEntries & wifiSystemStateEntries counts and individual elements 585 // pending their implementation</TODO> 586 } 587 588 private static final String SSID = "red"; 589 private static final int CONFIG_DTIM = 3; 590 private static final int NETWORK_DETAIL_WIFIMODE = 5; 591 private static final int NETWORK_DETAIL_DTIM = 7; 592 private static final int SCAN_RESULT_LEVEL = -30; 593 /** 594 * Test that WifiMetrics is correctly getting data from ScanDetail and WifiConfiguration 595 */ 596 @Test 597 public void testScanDetailAndWifiConfigurationUsage() throws Exception { 598 //Setup mock configs and scan details 599 NetworkDetail networkDetail = mock(NetworkDetail.class); 600 when(networkDetail.getWifiMode()).thenReturn(NETWORK_DETAIL_WIFIMODE); 601 when(networkDetail.getSSID()).thenReturn(SSID); 602 when(networkDetail.getDtimInterval()).thenReturn(NETWORK_DETAIL_DTIM); 603 ScanResult scanResult = mock(ScanResult.class); 604 scanResult.level = SCAN_RESULT_LEVEL; 605 WifiConfiguration config = mock(WifiConfiguration.class); 606 config.SSID = "\"" + SSID + "\""; 607 config.dtimInterval = CONFIG_DTIM; 608 WifiConfiguration.NetworkSelectionStatus networkSelectionStat = 609 mock(WifiConfiguration.NetworkSelectionStatus.class); 610 when(networkSelectionStat.getCandidate()).thenReturn(scanResult); 611 when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStat); 612 ScanDetail scanDetail = mock(ScanDetail.class); 613 when(scanDetail.getNetworkDetail()).thenReturn(networkDetail); 614 when(scanDetail.getScanResult()).thenReturn(scanResult); 615 616 //Create a connection event using only the config 617 mWifiMetrics.startConnectionEvent(config, "Red", 618 WifiMetricsProto.ConnectionEvent.ROAM_NONE); 619 mWifiMetrics.endConnectionEvent( 620 WifiMetrics.ConnectionEvent.FAILURE_NONE, 621 WifiMetricsProto.ConnectionEvent.HLF_NONE); 622 623 //Create a connection event using the config and a scan detail 624 mWifiMetrics.startConnectionEvent(config, "Green", 625 WifiMetricsProto.ConnectionEvent.ROAM_NONE); 626 mWifiMetrics.setConnectionScanDetail(scanDetail); 627 mWifiMetrics.endConnectionEvent( 628 WifiMetrics.ConnectionEvent.FAILURE_NONE, 629 WifiMetricsProto.ConnectionEvent.HLF_NONE); 630 631 //Dump proto from mWifiMetrics and deserialize it to mDeserializedWifiMetrics 632 dumpProtoAndDeserialize(); 633 634 //Check that the correct values are being flowed through 635 assertEquals(mDeserializedWifiMetrics.connectionEvent.length, 2); 636 assertEquals(mDeserializedWifiMetrics.connectionEvent[0].routerFingerprint.dtim, 637 CONFIG_DTIM); 638 assertEquals(mDeserializedWifiMetrics.connectionEvent[0].signalStrength, SCAN_RESULT_LEVEL); 639 assertEquals(mDeserializedWifiMetrics.connectionEvent[1].routerFingerprint.dtim, 640 NETWORK_DETAIL_DTIM); 641 assertEquals(mDeserializedWifiMetrics.connectionEvent[1].signalStrength, 642 SCAN_RESULT_LEVEL); 643 assertEquals(mDeserializedWifiMetrics.connectionEvent[1].routerFingerprint.routerTechnology, 644 NETWORK_DETAIL_WIFIMODE); 645 } 646 647 /** 648 * Test that WifiMetrics is being cleared after dumping via proto 649 */ 650 @Test 651 public void testMetricsClearedAfterProtoRequested() throws Exception { 652 // Create 3 ConnectionEvents 653 mWifiMetrics.startConnectionEvent(null, "RED", 654 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 655 mWifiMetrics.endConnectionEvent( 656 WifiMetrics.ConnectionEvent.FAILURE_NONE, 657 WifiMetricsProto.ConnectionEvent.HLF_NONE); 658 mWifiMetrics.startConnectionEvent(null, "YELLOW", 659 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 660 mWifiMetrics.endConnectionEvent( 661 WifiMetrics.ConnectionEvent.FAILURE_NONE, 662 WifiMetricsProto.ConnectionEvent.HLF_NONE); 663 mWifiMetrics.startConnectionEvent(null, "GREEN", 664 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 665 mWifiMetrics.endConnectionEvent( 666 WifiMetrics.ConnectionEvent.FAILURE_NONE, 667 WifiMetricsProto.ConnectionEvent.HLF_NONE); 668 mWifiMetrics.startConnectionEvent(null, "ORANGE", 669 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 670 mWifiMetrics.endConnectionEvent( 671 WifiMetrics.ConnectionEvent.FAILURE_NONE, 672 WifiMetricsProto.ConnectionEvent.HLF_NONE); 673 674 //Dump proto and deserialize 675 //This should clear all the metrics in mWifiMetrics, 676 dumpProtoAndDeserialize(); 677 //Check there are only 3 connection events 678 assertEquals(mDeserializedWifiMetrics.connectionEvent.length, 4); 679 assertEquals(mDeserializedWifiMetrics.rssiPollRssiCount.length, 0); 680 assertEquals(mDeserializedWifiMetrics.alertReasonCount.length, 0); 681 682 // Create 2 ConnectionEvents 683 mWifiMetrics.startConnectionEvent(null, "BLUE", 684 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 685 mWifiMetrics.endConnectionEvent( 686 WifiMetrics.ConnectionEvent.FAILURE_NONE, 687 WifiMetricsProto.ConnectionEvent.HLF_NONE); 688 mWifiMetrics.startConnectionEvent(null, "RED", 689 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 690 mWifiMetrics.endConnectionEvent( 691 WifiMetrics.ConnectionEvent.FAILURE_NONE, 692 WifiMetricsProto.ConnectionEvent.HLF_NONE); 693 694 //Dump proto and deserialize 695 dumpProtoAndDeserialize(); 696 //Check there are only 2 connection events 697 assertEquals(mDeserializedWifiMetrics.connectionEvent.length, 2); 698 } 699 700 /** 701 * Tests that after setting metrics values they can be serialized and deserialized with the 702 * $ adb shell dumpsys wifi wifiMetricsProto clean 703 */ 704 @Test 705 public void testClearMetricsDump() throws Exception { 706 setAndIncrementMetrics(); 707 startAndEndConnectionEventSucceeds(); 708 cleanDumpProtoAndDeserialize(); 709 assertDeserializedMetricsCorrect(); 710 assertEquals("mDeserializedWifiMetrics.connectionEvent.length", 711 2, mDeserializedWifiMetrics.connectionEvent.length); 712 } 713 714 private static final int NUM_REPEATED_DELTAS = 7; 715 private static final int REPEATED_DELTA = 0; 716 private static final int SINGLE_GOOD_DELTA = 1; 717 private static final int SINGLE_TIMEOUT_DELTA = 2; 718 private static final int NUM_REPEATED_BOUND_DELTAS = 2; 719 private static final int MAX_DELTA_LEVEL = 127; 720 private static final int MIN_DELTA_LEVEL = -127; 721 private static final int ARBITRARY_DELTA_LEVEL = 20; 722 723 /** 724 * Sunny day RSSI delta logging scenario. 725 * Logs one rssi delta value multiple times 726 * Logs a different delta value a single time 727 */ 728 @Test 729 public void testRssiDeltasSuccessfulLogging() throws Exception { 730 // Generate some repeated deltas 731 for (int i = 0; i < NUM_REPEATED_DELTAS; i++) { 732 generateRssiDelta(MIN_RSSI_LEVEL, REPEATED_DELTA, 733 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS); 734 } 735 // Generate a single delta 736 generateRssiDelta(MIN_RSSI_LEVEL, SINGLE_GOOD_DELTA, 737 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS); 738 dumpProtoAndDeserialize(); 739 assertEquals(2, mDeserializedWifiMetrics.rssiPollDeltaCount.length); 740 // Check the repeated deltas 741 assertEquals(NUM_REPEATED_DELTAS, mDeserializedWifiMetrics.rssiPollDeltaCount[0].count); 742 assertEquals(REPEATED_DELTA, mDeserializedWifiMetrics.rssiPollDeltaCount[0].rssi); 743 // Check the single delta 744 assertEquals(1, mDeserializedWifiMetrics.rssiPollDeltaCount[1].count); 745 assertEquals(SINGLE_GOOD_DELTA, mDeserializedWifiMetrics.rssiPollDeltaCount[1].rssi); 746 } 747 748 /** 749 * Tests that Rssi Delta events whose scanResult and Rssi Poll come too far apart, timeout, 750 * and are not logged. 751 */ 752 @Test 753 public void testRssiDeltasTimeout() throws Exception { 754 // Create timed out rssi deltas 755 generateRssiDelta(MIN_RSSI_LEVEL, REPEATED_DELTA, 756 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS + 1); 757 generateRssiDelta(MIN_RSSI_LEVEL, SINGLE_TIMEOUT_DELTA, 758 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS + 1); 759 dumpProtoAndDeserialize(); 760 assertEquals(0, mDeserializedWifiMetrics.rssiPollDeltaCount.length); 761 } 762 763 /** 764 * Tests the exact inclusive boundaries of RSSI delta logging. 765 */ 766 @Test 767 public void testRssiDeltaSuccessfulLoggingExactBounds() throws Exception { 768 generateRssiDelta(MIN_RSSI_LEVEL, MAX_DELTA_LEVEL, 769 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS); 770 generateRssiDelta(MAX_RSSI_LEVEL, MIN_DELTA_LEVEL, 771 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS); 772 dumpProtoAndDeserialize(); 773 assertEquals(2, mDeserializedWifiMetrics.rssiPollDeltaCount.length); 774 assertEquals(MIN_DELTA_LEVEL, mDeserializedWifiMetrics.rssiPollDeltaCount[0].rssi); 775 assertEquals(1, mDeserializedWifiMetrics.rssiPollDeltaCount[0].count); 776 assertEquals(MAX_DELTA_LEVEL, mDeserializedWifiMetrics.rssiPollDeltaCount[1].rssi); 777 assertEquals(1, mDeserializedWifiMetrics.rssiPollDeltaCount[1].count); 778 } 779 780 /** 781 * Tests the exact exclusive boundaries of RSSI delta logging. 782 * This test ensures that too much data is not generated. 783 */ 784 @Test 785 public void testRssiDeltaOutOfBounds() throws Exception { 786 generateRssiDelta(MIN_RSSI_LEVEL, MAX_DELTA_LEVEL + 1, 787 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS); 788 generateRssiDelta(MAX_RSSI_LEVEL, MIN_DELTA_LEVEL - 1, 789 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS); 790 dumpProtoAndDeserialize(); 791 assertEquals(0, mDeserializedWifiMetrics.rssiPollDeltaCount.length); 792 } 793 794 /** 795 * This test ensures no rssi Delta is logged after an unsuccessful ConnectionEvent 796 */ 797 @Test 798 public void testUnsuccesfulConnectionEventRssiDeltaIsNotLogged() throws Exception { 799 generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL, 800 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS, 801 false, // successfulConnectionEvent 802 true, // completeConnectionEvent 803 true, // useValidScanResult 804 true // dontDeserializeBeforePoll 805 ); 806 807 dumpProtoAndDeserialize(); 808 assertEquals(0, mDeserializedWifiMetrics.rssiPollDeltaCount.length); 809 } 810 811 /** 812 * This test ensures rssi Deltas can be logged during a ConnectionEvent 813 */ 814 @Test 815 public void testIncompleteConnectionEventRssiDeltaIsLogged() throws Exception { 816 generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL, 817 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS, 818 true, // successfulConnectionEvent 819 false, // completeConnectionEvent 820 true, // useValidScanResult 821 true // dontDeserializeBeforePoll 822 ); 823 dumpProtoAndDeserialize(); 824 assertEquals(1, mDeserializedWifiMetrics.rssiPollDeltaCount.length); 825 assertEquals(ARBITRARY_DELTA_LEVEL, mDeserializedWifiMetrics.rssiPollDeltaCount[0].rssi); 826 assertEquals(1, mDeserializedWifiMetrics.rssiPollDeltaCount[0].count); 827 } 828 829 /** 830 * This test ensures that no delta is logged for a null ScanResult Candidate 831 */ 832 @Test 833 public void testRssiDeltaNotLoggedForNullCandidateScanResult() throws Exception { 834 generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL, 835 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS, 836 true, // successfulConnectionEvent 837 true, // completeConnectionEvent 838 false, // useValidScanResult 839 true // dontDeserializeBeforePoll 840 ); 841 dumpProtoAndDeserialize(); 842 assertEquals(0, mDeserializedWifiMetrics.rssiPollDeltaCount.length); 843 } 844 845 /** 846 * This test ensures that Rssi Deltas are not logged over a 'clear()' call (Metrics Serialized) 847 */ 848 @Test 849 public void testMetricsSerializedDuringRssiDeltaEventLogsNothing() throws Exception { 850 generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL, 851 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS, 852 true, // successfulConnectionEvent 853 true, // completeConnectionEvent 854 true, // useValidScanResult 855 false // dontDeserializeBeforePoll 856 ); 857 dumpProtoAndDeserialize(); 858 assertEquals(0, mDeserializedWifiMetrics.rssiPollDeltaCount.length); 859 } 860 861 private static final int DEAUTH_REASON = 7; 862 private static final int ASSOC_STATUS = 11; 863 private static final int ASSOC_TIMEOUT = 1; 864 private static final int LOCAL_GEN = 1; 865 private static final int AUTH_FAILURE_REASON = WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD; 866 private static final int NUM_TEST_STA_EVENTS = 14; 867 private static final String sSSID = "\"SomeTestSsid\""; 868 private static final WifiSsid sWifiSsid = WifiSsid.createFromAsciiEncoded(sSSID); 869 private static final String sBSSID = "01:02:03:04:05:06"; 870 871 private final StateChangeResult mStateDisconnected = 872 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED); 873 private final StateChangeResult mStateCompleted = 874 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED); 875 // Test bitmasks of supplicant state changes 876 private final int mSupBm1 = WifiMetrics.supplicantStateToBit(mStateDisconnected.state); 877 private final int mSupBm2 = WifiMetrics.supplicantStateToBit(mStateDisconnected.state) 878 | WifiMetrics.supplicantStateToBit(mStateCompleted.state); 879 // An invalid but interesting wifiConfiguration that exercises the StaEvent.ConfigInfo encoding 880 private final WifiConfiguration mTestWifiConfig = createComplexWifiConfig(); 881 // <msg.what> <msg.arg1> <msg.arg2> 882 private int[][] mTestStaMessageInts = { 883 {WifiMonitor.ASSOCIATION_REJECTION_EVENT, ASSOC_TIMEOUT, ASSOC_STATUS}, 884 {WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 0, AUTH_FAILURE_REASON}, 885 {WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0}, 886 {WifiMonitor.NETWORK_DISCONNECTION_EVENT, LOCAL_GEN, DEAUTH_REASON}, 887 {WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0}, 888 {WifiStateMachine.CMD_ASSOCIATED_BSSID, 0, 0}, 889 {WifiStateMachine.CMD_TARGET_BSSID, 0, 0}, 890 {WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0}, 891 {WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0} 892 }; 893 private Object[] mTestStaMessageObjs = { 894 null, 895 null, 896 null, 897 null, 898 mStateDisconnected, 899 null, 900 null, 901 mStateDisconnected, 902 mStateCompleted 903 }; 904 // Values used to generate the StaEvent log calls from WifiStateMachine 905 // <StaEvent.Type>, <StaEvent.FrameworkDisconnectReason>, <1|0>(testWifiConfiguration, null) 906 private int[][] mTestStaLogInts = { 907 {StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL, 0, 0}, 908 {StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST, 0, 0}, 909 {StaEvent.TYPE_CMD_IP_REACHABILITY_LOST, 0, 0}, 910 {StaEvent.TYPE_CMD_START_CONNECT, 0, 1}, 911 {StaEvent.TYPE_CMD_START_ROAM, 0, 1}, 912 {StaEvent.TYPE_CONNECT_NETWORK, 0, 1}, 913 {StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK, 0, 0}, 914 {StaEvent.TYPE_FRAMEWORK_DISCONNECT, StaEvent.DISCONNECT_API, 0} 915 }; 916 // Values used to generate the StaEvent log calls from WifiMonitor 917 // <type>, <reason>, <status>, <local_gen>, 918 // <auth_fail_reason>, <assoc_timed_out> <supplicantStateChangeBitmask> <1|0>(has ConfigInfo) 919 private int[][] mExpectedValues = { 920 {StaEvent.TYPE_ASSOCIATION_REJECTION_EVENT, -1, ASSOC_STATUS, 0, 921 /**/ 0, ASSOC_TIMEOUT, 0, 0}, /**/ 922 {StaEvent.TYPE_AUTHENTICATION_FAILURE_EVENT, -1, -1, 0, 923 /**/StaEvent.AUTH_FAILURE_WRONG_PSWD, 0, 0, 0}, /**/ 924 {StaEvent.TYPE_NETWORK_CONNECTION_EVENT, -1, -1, 0, 925 /**/ 0, 0, 0, 0}, /**/ 926 {StaEvent.TYPE_NETWORK_DISCONNECTION_EVENT, DEAUTH_REASON, -1, LOCAL_GEN, 927 /**/ 0, 0, 0, 0}, /**/ 928 {StaEvent.TYPE_CMD_ASSOCIATED_BSSID, -1, -1, 0, 929 /**/ 0, 0, mSupBm1, 0}, /**/ 930 {StaEvent.TYPE_CMD_TARGET_BSSID, -1, -1, 0, 931 /**/ 0, 0, 0, 0}, /**/ 932 {StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL, -1, -1, 0, 933 /**/ 0, 0, mSupBm2, 0}, /**/ 934 {StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST, -1, -1, 0, 935 /**/ 0, 0, 0, 0}, /**/ 936 {StaEvent.TYPE_CMD_IP_REACHABILITY_LOST, -1, -1, 0, 937 /**/ 0, 0, 0, 0}, /**/ 938 {StaEvent.TYPE_CMD_START_CONNECT, -1, -1, 0, 939 /**/ 0, 0, 0, 1}, /**/ 940 {StaEvent.TYPE_CMD_START_ROAM, -1, -1, 0, 941 /**/ 0, 0, 0, 1}, /**/ 942 {StaEvent.TYPE_CONNECT_NETWORK, -1, -1, 0, 943 /**/ 0, 0, 0, 1}, /**/ 944 {StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK, -1, -1, 0, 945 /**/ 0, 0, 0, 0}, /**/ 946 {StaEvent.TYPE_FRAMEWORK_DISCONNECT, -1, -1, 0, 947 /**/ 0, 0, 0, 0} /**/ 948 }; 949 950 /** 951 * Generates events from all the rows in mTestStaMessageInts, and then mTestStaLogInts 952 */ 953 private void generateStaEvents(WifiMetrics wifiMetrics) { 954 Handler handler = wifiMetrics.getHandler(); 955 for (int i = 0; i < mTestStaMessageInts.length; i++) { 956 int[] mia = mTestStaMessageInts[i]; 957 handler.sendMessage( 958 handler.obtainMessage(mia[0], mia[1], mia[2], mTestStaMessageObjs[i])); 959 } 960 mTestLooper.dispatchAll(); 961 for (int i = 0; i < mTestStaLogInts.length; i++) { 962 int[] lia = mTestStaLogInts[i]; 963 wifiMetrics.logStaEvent(lia[0], lia[1], lia[2] == 1 ? mTestWifiConfig : null); 964 } 965 } 966 private void verifyDeserializedStaEvents(WifiMetricsProto.WifiLog wifiLog) { 967 assertEquals(NUM_TEST_STA_EVENTS, wifiLog.staEventList.length); 968 int j = 0; // De-serialized event index 969 for (int i = 0; i < mTestStaMessageInts.length; i++) { 970 StaEvent event = wifiLog.staEventList[j]; 971 int[] mia = mTestStaMessageInts[i]; 972 int[] evs = mExpectedValues[j]; 973 if (mia[0] != WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT) { 974 assertEquals(evs[0], event.type); 975 assertEquals(evs[1], event.reason); 976 assertEquals(evs[2], event.status); 977 assertEquals(evs[3] == 1 ? true : false, event.localGen); 978 assertEquals(evs[4], event.authFailureReason); 979 assertEquals(evs[5] == 1 ? true : false, event.associationTimedOut); 980 assertEquals(evs[6], event.supplicantStateChangesBitmask); 981 assertConfigInfoEqualsWifiConfig( 982 evs[7] == 1 ? mTestWifiConfig : null, event.configInfo); 983 j++; 984 } 985 } 986 } 987 988 /** 989 * Generate StaEvents of each type, ensure all the different values are logged correctly, 990 * and that they survive serialization & de-serialization 991 */ 992 @Test 993 public void testStaEventsLogSerializeDeserialize() throws Exception { 994 generateStaEvents(mWifiMetrics); 995 dumpProtoAndDeserialize(); 996 verifyDeserializedStaEvents(mDeserializedWifiMetrics); 997 } 998 999 /** 1000 * Ensure the number of StaEvents does not exceed MAX_STA_EVENTS by generating lots of events 1001 * and checking how many are deserialized 1002 */ 1003 @Test 1004 public void testStaEventBounding() throws Exception { 1005 for (int i = 0; i < (WifiMetrics.MAX_STA_EVENTS + 10); i++) { 1006 mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_CONNECT); 1007 } 1008 dumpProtoAndDeserialize(); 1009 assertEquals(WifiMetrics.MAX_STA_EVENTS, mDeserializedWifiMetrics.staEventList.length); 1010 } 1011 1012 /** 1013 * Ensure WifiMetrics doesn't cause a null pointer exception when called with null args 1014 */ 1015 @Test 1016 public void testDumpNullArg() { 1017 mWifiMetrics.dump(new FileDescriptor(), new PrintWriter(new StringWriter()), null); 1018 } 1019 1020 /** 1021 * Generate an RSSI delta event by creating a connection event and an RSSI poll within 1022 * 'interArrivalTime' milliseconds of each other. 1023 * Event will not be logged if interArrivalTime > mWifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS 1024 * successfulConnectionEvent, completeConnectionEvent, useValidScanResult and 1025 * dontDeserializeBeforePoll 1026 * each create an anomalous condition when set to false. 1027 */ 1028 private void generateRssiDelta(int scanRssi, int rssiDelta, 1029 long interArrivalTime, boolean successfulConnectionEvent, 1030 boolean completeConnectionEvent, boolean useValidScanResult, 1031 boolean dontDeserializeBeforePoll) throws Exception { 1032 when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 0); 1033 ScanResult scanResult = null; 1034 if (useValidScanResult) { 1035 scanResult = mock(ScanResult.class); 1036 scanResult.level = scanRssi; 1037 } 1038 WifiConfiguration config = mock(WifiConfiguration.class); 1039 WifiConfiguration.NetworkSelectionStatus networkSelectionStat = 1040 mock(WifiConfiguration.NetworkSelectionStatus.class); 1041 when(networkSelectionStat.getCandidate()).thenReturn(scanResult); 1042 when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStat); 1043 mWifiMetrics.startConnectionEvent(config, "TestNetwork", 1044 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 1045 if (completeConnectionEvent) { 1046 if (successfulConnectionEvent) { 1047 mWifiMetrics.endConnectionEvent( 1048 WifiMetrics.ConnectionEvent.FAILURE_NONE, 1049 WifiMetricsProto.ConnectionEvent.HLF_NONE); 1050 } else { 1051 mWifiMetrics.endConnectionEvent( 1052 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, 1053 WifiMetricsProto.ConnectionEvent.HLF_NONE); 1054 } 1055 } 1056 when(mClock.getElapsedSinceBootMillis()).thenReturn(interArrivalTime); 1057 if (!dontDeserializeBeforePoll) { 1058 dumpProtoAndDeserialize(); 1059 } 1060 mWifiMetrics.incrementRssiPollRssiCount(scanRssi + rssiDelta); 1061 } 1062 /** 1063 * Generate an RSSI delta event, with all extra conditions set to true. 1064 */ 1065 private void generateRssiDelta(int scanRssi, int rssiDelta, 1066 long interArrivalTime) throws Exception { 1067 generateRssiDelta(scanRssi, rssiDelta, interArrivalTime, true, true, true, true); 1068 } 1069 1070 private void assertStringContains( 1071 String actualString, String expectedSubstring) { 1072 assertTrue("Expected text not found in: " + actualString, 1073 actualString.contains(expectedSubstring)); 1074 } 1075 1076 private String getStateDump() { 1077 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 1078 PrintWriter writer = new PrintWriter(stream); 1079 String[] args = new String[0]; 1080 mWifiMetrics.dump(null, writer, args); 1081 writer.flush(); 1082 return stream.toString(); 1083 } 1084 1085 private static final int TEST_ALLOWED_KEY_MANAGEMENT = 83; 1086 private static final int TEST_ALLOWED_PROTOCOLS = 22; 1087 private static final int TEST_ALLOWED_AUTH_ALGORITHMS = 11; 1088 private static final int TEST_ALLOWED_PAIRWISE_CIPHERS = 67; 1089 private static final int TEST_ALLOWED_GROUP_CIPHERS = 231; 1090 private static final int TEST_CANDIDATE_LEVEL = -80; 1091 private static final int TEST_CANDIDATE_FREQ = 2345; 1092 1093 private WifiConfiguration createComplexWifiConfig() { 1094 WifiConfiguration config = new WifiConfiguration(); 1095 config.allowedKeyManagement = intToBitSet(TEST_ALLOWED_KEY_MANAGEMENT); 1096 config.allowedProtocols = intToBitSet(TEST_ALLOWED_PROTOCOLS); 1097 config.allowedAuthAlgorithms = intToBitSet(TEST_ALLOWED_AUTH_ALGORITHMS); 1098 config.allowedPairwiseCiphers = intToBitSet(TEST_ALLOWED_PAIRWISE_CIPHERS); 1099 config.allowedGroupCiphers = intToBitSet(TEST_ALLOWED_GROUP_CIPHERS); 1100 config.hiddenSSID = true; 1101 config.ephemeral = true; 1102 config.getNetworkSelectionStatus().setHasEverConnected(true); 1103 ScanResult candidate = new ScanResult(); 1104 candidate.level = TEST_CANDIDATE_LEVEL; 1105 candidate.frequency = TEST_CANDIDATE_FREQ; 1106 config.getNetworkSelectionStatus().setCandidate(candidate); 1107 return config; 1108 } 1109 1110 private void assertConfigInfoEqualsWifiConfig(WifiConfiguration config, 1111 StaEvent.ConfigInfo info) { 1112 if (config == null && info == null) return; 1113 assertEquals(config.allowedKeyManagement, intToBitSet(info.allowedKeyManagement)); 1114 assertEquals(config.allowedProtocols, intToBitSet(info.allowedProtocols)); 1115 assertEquals(config.allowedAuthAlgorithms, intToBitSet(info.allowedAuthAlgorithms)); 1116 assertEquals(config.allowedPairwiseCiphers, intToBitSet(info.allowedPairwiseCiphers)); 1117 assertEquals(config.allowedGroupCiphers, intToBitSet(info.allowedGroupCiphers)); 1118 assertEquals(config.hiddenSSID, info.hiddenSsid); 1119 assertEquals(config.ephemeral, info.isEphemeral); 1120 assertEquals(config.getNetworkSelectionStatus().getHasEverConnected(), 1121 info.hasEverConnected); 1122 assertEquals(config.getNetworkSelectionStatus().getCandidate().level, info.scanRssi); 1123 assertEquals(config.getNetworkSelectionStatus().getCandidate().frequency, info.scanFreq); 1124 } 1125 1126 /** 1127 * Sets the values of bitSet to match an int mask 1128 */ 1129 private static BitSet intToBitSet(int mask) { 1130 BitSet bitSet = new BitSet(); 1131 for (int bitIndex = 0; mask > 0; mask >>>= 1, bitIndex++) { 1132 if ((mask & 1) != 0) bitSet.set(bitIndex); 1133 } 1134 return bitSet; 1135 } 1136} 1137