WifiMetrics.java revision 44ce135519e22d8c4746abac21c14111f1ce8667
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wifi; 18 19import android.net.NetworkAgent; 20import android.net.wifi.ScanResult; 21import android.net.wifi.WifiConfiguration; 22import android.net.wifi.WifiManager; 23import android.util.Base64; 24import android.util.Log; 25import android.util.SparseIntArray; 26 27import com.android.server.wifi.hotspot2.NetworkDetail; 28import com.android.server.wifi.util.InformationElementUtil; 29import com.android.server.wifi.util.ScanResultUtil; 30 31import java.io.FileDescriptor; 32import java.io.PrintWriter; 33import java.util.ArrayList; 34import java.util.Calendar; 35import java.util.List; 36 37/** 38 * Provides storage for wireless connectivity metrics, as they are generated. 39 * Metrics logged by this class include: 40 * Aggregated connection stats (num of connections, num of failures, ...) 41 * Discrete connection event stats (time, duration, failure codes, ...) 42 * Router details (technology type, authentication type, ...) 43 * Scan stats 44 */ 45public class WifiMetrics { 46 private static final String TAG = "WifiMetrics"; 47 private static final boolean DBG = false; 48 /** 49 * Clamp the RSSI poll counts to values between [MIN,MAX]_RSSI_POLL 50 */ 51 private static final int MAX_RSSI_POLL = 0; 52 private static final int MIN_RSSI_POLL = -127; 53 public static final int MAX_RSSI_DELTA = 127; 54 public static final int MIN_RSSI_DELTA = -127; 55 /** Maximum time period between ScanResult and RSSI poll to generate rssi delta datapoint */ 56 public static final long TIMEOUT_RSSI_DELTA_MILLIS = 3000; 57 private static final int MIN_WIFI_SCORE = 0; 58 private static final int MAX_WIFI_SCORE = NetworkAgent.WIFI_BASE_SCORE; 59 private final Object mLock = new Object(); 60 private static final int MAX_CONNECTION_EVENTS = 256; 61 private Clock mClock; 62 private boolean mScreenOn; 63 private int mWifiState; 64 /** 65 * Metrics are stored within an instance of the WifiLog proto during runtime, 66 * The ConnectionEvent, SystemStateEntries & ScanReturnEntries metrics are stored during 67 * runtime in member lists of this WifiMetrics class, with the final WifiLog proto being pieced 68 * together at dump-time 69 */ 70 private final WifiMetricsProto.WifiLog mWifiLogProto = new WifiMetricsProto.WifiLog(); 71 /** 72 * Session information that gets logged for every Wifi connection attempt. 73 */ 74 private final List<ConnectionEvent> mConnectionEventList = new ArrayList<>(); 75 /** 76 * The latest started (but un-ended) connection attempt 77 */ 78 private ConnectionEvent mCurrentConnectionEvent; 79 /** 80 * Count of number of times each scan return code, indexed by WifiLog.ScanReturnCode 81 */ 82 private final SparseIntArray mScanReturnEntries = new SparseIntArray(); 83 /** 84 * Mapping of system state to the counts of scans requested in that wifi state * screenOn 85 * combination. Indexed by WifiLog.WifiState * (1 + screenOn) 86 */ 87 private final SparseIntArray mWifiSystemStateEntries = new SparseIntArray(); 88 /** Mapping of RSSI values to counts. */ 89 private final SparseIntArray mRssiPollCounts = new SparseIntArray(); 90 /** Mapping of RSSI scan-poll delta values to counts. */ 91 private final SparseIntArray mRssiDeltaCounts = new SparseIntArray(); 92 /** RSSI of the scan result for the last connection event*/ 93 private int mScanResultRssi = 0; 94 /** Boot-relative timestamp when the last candidate scanresult was received, used to calculate 95 RSSI deltas. -1 designates no candidate scanResult being tracked */ 96 private long mScanResultRssiTimestampMillis = -1; 97 /** Mapping of alert reason to the respective alert count. */ 98 private final SparseIntArray mWifiAlertReasonCounts = new SparseIntArray(); 99 /** 100 * Records the getElapsedSinceBootMillis (in seconds) that represents the beginning of data 101 * capture for for this WifiMetricsProto 102 */ 103 private long mRecordStartTimeSec; 104 /** Mapping of Wifi Scores to counts */ 105 private final SparseIntArray mWifiScoreCounts = new SparseIntArray(); 106 /** Mapping of SoftApManager start SoftAp return codes to counts */ 107 private final SparseIntArray mSoftApManagerReturnCodeCounts = new SparseIntArray(); 108 class RouterFingerPrint { 109 private WifiMetricsProto.RouterFingerPrint mRouterFingerPrintProto; 110 RouterFingerPrint() { 111 mRouterFingerPrintProto = new WifiMetricsProto.RouterFingerPrint(); 112 } 113 114 public String toString() { 115 StringBuilder sb = new StringBuilder(); 116 synchronized (mLock) { 117 sb.append("mConnectionEvent.roamType=" + mRouterFingerPrintProto.roamType); 118 sb.append(", mChannelInfo=" + mRouterFingerPrintProto.channelInfo); 119 sb.append(", mDtim=" + mRouterFingerPrintProto.dtim); 120 sb.append(", mAuthentication=" + mRouterFingerPrintProto.authentication); 121 sb.append(", mHidden=" + mRouterFingerPrintProto.hidden); 122 sb.append(", mRouterTechnology=" + mRouterFingerPrintProto.routerTechnology); 123 sb.append(", mSupportsIpv6=" + mRouterFingerPrintProto.supportsIpv6); 124 } 125 return sb.toString(); 126 } 127 public void updateFromWifiConfiguration(WifiConfiguration config) { 128 synchronized (mLock) { 129 if (config != null) { 130 // Is this a hidden network 131 mRouterFingerPrintProto.hidden = config.hiddenSSID; 132 // Config may not have a valid dtimInterval set yet, in which case dtim will be zero 133 // (These are only populated from beacon frame scan results, which are returned as 134 // scan results from the chip far less frequently than Probe-responses) 135 if (config.dtimInterval > 0) { 136 mRouterFingerPrintProto.dtim = config.dtimInterval; 137 } 138 mCurrentConnectionEvent.mConfigSsid = config.SSID; 139 // Get AuthType information from config (We do this again from ScanResult after 140 // associating with BSSID) 141 if (config.allowedKeyManagement != null 142 && config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)) { 143 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto 144 .authentication = WifiMetricsProto.RouterFingerPrint.AUTH_OPEN; 145 } else if (config.isEnterprise()) { 146 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto 147 .authentication = WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE; 148 } else { 149 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto 150 .authentication = WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL; 151 } 152 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto 153 .passpoint = config.isPasspoint(); 154 // If there's a ScanResult candidate associated with this config already, get it and 155 // log (more accurate) metrics from it 156 ScanResult candidate = config.getNetworkSelectionStatus().getCandidate(); 157 if (candidate != null) { 158 updateMetricsFromScanResult(candidate); 159 } 160 } 161 } 162 } 163 } 164 165 /** 166 * Log event, tracking the start time, end time and result of a wireless connection attempt. 167 */ 168 class ConnectionEvent { 169 WifiMetricsProto.ConnectionEvent mConnectionEvent; 170 //<TODO> Move these constants into a wifi.proto Enum, and create a new Failure Type field 171 //covering more than just l2 failures. see b/27652362 172 /** 173 * Failure codes, used for the 'level_2_failure_code' Connection event field (covers a lot 174 * more failures than just l2 though, since the proto does not have a place to log 175 * framework failures) 176 */ 177 // Failure is unknown 178 public static final int FAILURE_UNKNOWN = 0; 179 // NONE 180 public static final int FAILURE_NONE = 1; 181 // ASSOCIATION_REJECTION_EVENT 182 public static final int FAILURE_ASSOCIATION_REJECTION = 2; 183 // AUTHENTICATION_FAILURE_EVENT 184 public static final int FAILURE_AUTHENTICATION_FAILURE = 3; 185 // SSID_TEMP_DISABLED (Also Auth failure) 186 public static final int FAILURE_SSID_TEMP_DISABLED = 4; 187 // reconnect() or reassociate() call to WifiNative failed 188 public static final int FAILURE_CONNECT_NETWORK_FAILED = 5; 189 // NETWORK_DISCONNECTION_EVENT 190 public static final int FAILURE_NETWORK_DISCONNECTION = 6; 191 // NEW_CONNECTION_ATTEMPT before previous finished 192 public static final int FAILURE_NEW_CONNECTION_ATTEMPT = 7; 193 // New connection attempt to the same network & bssid 194 public static final int FAILURE_REDUNDANT_CONNECTION_ATTEMPT = 8; 195 // Roam Watchdog timer triggered (Roaming timed out) 196 public static final int FAILURE_ROAM_TIMEOUT = 9; 197 // DHCP failure 198 public static final int FAILURE_DHCP = 10; 199 200 RouterFingerPrint mRouterFingerPrint; 201 private long mRealStartTime; 202 private long mRealEndTime; 203 private String mConfigSsid; 204 private String mConfigBssid; 205 private int mWifiState; 206 private boolean mScreenOn; 207 208 private ConnectionEvent() { 209 mConnectionEvent = new WifiMetricsProto.ConnectionEvent(); 210 mRealEndTime = 0; 211 mRealStartTime = 0; 212 mRouterFingerPrint = new RouterFingerPrint(); 213 mConnectionEvent.routerFingerprint = mRouterFingerPrint.mRouterFingerPrintProto; 214 mConfigSsid = "<NULL>"; 215 mConfigBssid = "<NULL>"; 216 mWifiState = WifiMetricsProto.WifiLog.WIFI_UNKNOWN; 217 mScreenOn = false; 218 } 219 220 public String toString() { 221 StringBuilder sb = new StringBuilder(); 222 sb.append("startTime="); 223 Calendar c = Calendar.getInstance(); 224 synchronized (mLock) { 225 c.setTimeInMillis(mConnectionEvent.startTimeMillis); 226 sb.append(mConnectionEvent.startTimeMillis == 0 ? " <null>" : 227 String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c)); 228 sb.append(", SSID="); 229 sb.append(mConfigSsid); 230 sb.append(", BSSID="); 231 sb.append(mConfigBssid); 232 sb.append(", durationMillis="); 233 sb.append(mConnectionEvent.durationTakenToConnectMillis); 234 sb.append(", roamType="); 235 switch(mConnectionEvent.roamType) { 236 case 1: 237 sb.append("ROAM_NONE"); 238 break; 239 case 2: 240 sb.append("ROAM_DBDC"); 241 break; 242 case 3: 243 sb.append("ROAM_ENTERPRISE"); 244 break; 245 case 4: 246 sb.append("ROAM_USER_SELECTED"); 247 break; 248 case 5: 249 sb.append("ROAM_UNRELATED"); 250 break; 251 default: 252 sb.append("ROAM_UNKNOWN"); 253 } 254 sb.append(", connectionResult="); 255 sb.append(mConnectionEvent.connectionResult); 256 sb.append(", level2FailureCode="); 257 switch(mConnectionEvent.level2FailureCode) { 258 case FAILURE_NONE: 259 sb.append("NONE"); 260 break; 261 case FAILURE_ASSOCIATION_REJECTION: 262 sb.append("ASSOCIATION_REJECTION"); 263 break; 264 case FAILURE_AUTHENTICATION_FAILURE: 265 sb.append("AUTHENTICATION_FAILURE"); 266 break; 267 case FAILURE_SSID_TEMP_DISABLED: 268 sb.append("SSID_TEMP_DISABLED"); 269 break; 270 case FAILURE_CONNECT_NETWORK_FAILED: 271 sb.append("CONNECT_NETWORK_FAILED"); 272 break; 273 case FAILURE_NETWORK_DISCONNECTION: 274 sb.append("NETWORK_DISCONNECTION"); 275 break; 276 case FAILURE_NEW_CONNECTION_ATTEMPT: 277 sb.append("NEW_CONNECTION_ATTEMPT"); 278 break; 279 case FAILURE_REDUNDANT_CONNECTION_ATTEMPT: 280 sb.append("REDUNDANT_CONNECTION_ATTEMPT"); 281 break; 282 case FAILURE_ROAM_TIMEOUT: 283 sb.append("ROAM_TIMEOUT"); 284 break; 285 case FAILURE_DHCP: 286 sb.append("DHCP"); 287 default: 288 sb.append("UNKNOWN"); 289 break; 290 } 291 sb.append(", connectivityLevelFailureCode="); 292 switch(mConnectionEvent.connectivityLevelFailureCode) { 293 case WifiMetricsProto.ConnectionEvent.HLF_NONE: 294 sb.append("NONE"); 295 break; 296 case WifiMetricsProto.ConnectionEvent.HLF_DHCP: 297 sb.append("DHCP"); 298 break; 299 case WifiMetricsProto.ConnectionEvent.HLF_NO_INTERNET: 300 sb.append("NO_INTERNET"); 301 break; 302 case WifiMetricsProto.ConnectionEvent.HLF_UNWANTED: 303 sb.append("UNWANTED"); 304 break; 305 default: 306 sb.append("UNKNOWN"); 307 break; 308 } 309 sb.append(", signalStrength="); 310 sb.append(mConnectionEvent.signalStrength); 311 sb.append(", wifiState="); 312 switch(mWifiState) { 313 case WifiMetricsProto.WifiLog.WIFI_DISABLED: 314 sb.append("WIFI_DISABLED"); 315 break; 316 case WifiMetricsProto.WifiLog.WIFI_DISCONNECTED: 317 sb.append("WIFI_DISCONNECTED"); 318 break; 319 case WifiMetricsProto.WifiLog.WIFI_ASSOCIATED: 320 sb.append("WIFI_ASSOCIATED"); 321 break; 322 default: 323 sb.append("WIFI_UNKNOWN"); 324 break; 325 } 326 sb.append(", screenOn="); 327 sb.append(mScreenOn); 328 sb.append(". mRouterFingerprint: "); 329 sb.append(mRouterFingerPrint.toString()); 330 } 331 return sb.toString(); 332 } 333 } 334 335 public WifiMetrics(Clock clock) { 336 mClock = clock; 337 mCurrentConnectionEvent = null; 338 mScreenOn = true; 339 mWifiState = WifiMetricsProto.WifiLog.WIFI_DISABLED; 340 mRecordStartTimeSec = mClock.getElapsedSinceBootMillis() / 1000; 341 } 342 343 // Values used for indexing SystemStateEntries 344 private static final int SCREEN_ON = 1; 345 private static final int SCREEN_OFF = 0; 346 347 /** 348 * Create a new connection event. Call when wifi attempts to make a new network connection 349 * If there is a current 'un-ended' connection event, it will be ended with UNKNOWN connectivity 350 * failure code. 351 * Gathers and sets the RouterFingerPrint data as well 352 * 353 * @param config WifiConfiguration of the config used for the current connection attempt 354 * @param roamType Roam type that caused connection attempt, see WifiMetricsProto.WifiLog.ROAM_X 355 */ 356 public void startConnectionEvent(WifiConfiguration config, String targetBSSID, int roamType) { 357 synchronized (mLock) { 358 // Check if this is overlapping another current connection event 359 if (mCurrentConnectionEvent != null) { 360 //Is this new Connection Event the same as the current one 361 if (mCurrentConnectionEvent.mConfigSsid != null 362 && mCurrentConnectionEvent.mConfigBssid != null 363 && config != null 364 && mCurrentConnectionEvent.mConfigSsid.equals(config.SSID) 365 && (mCurrentConnectionEvent.mConfigBssid.equals("any") 366 || mCurrentConnectionEvent.mConfigBssid.equals(targetBSSID))) { 367 mCurrentConnectionEvent.mConfigBssid = targetBSSID; 368 // End Connection Event due to new connection attempt to the same network 369 endConnectionEvent(ConnectionEvent.FAILURE_REDUNDANT_CONNECTION_ATTEMPT, 370 WifiMetricsProto.ConnectionEvent.HLF_NONE); 371 } else { 372 // End Connection Event due to new connection attempt to different network 373 endConnectionEvent(ConnectionEvent.FAILURE_NEW_CONNECTION_ATTEMPT, 374 WifiMetricsProto.ConnectionEvent.HLF_NONE); 375 } 376 } 377 //If past maximum connection events, start removing the oldest 378 while(mConnectionEventList.size() >= MAX_CONNECTION_EVENTS) { 379 mConnectionEventList.remove(0); 380 } 381 mCurrentConnectionEvent = new ConnectionEvent(); 382 mCurrentConnectionEvent.mConnectionEvent.startTimeMillis = 383 mClock.getWallClockMillis(); 384 mCurrentConnectionEvent.mConfigBssid = targetBSSID; 385 mCurrentConnectionEvent.mConnectionEvent.roamType = roamType; 386 mCurrentConnectionEvent.mRouterFingerPrint.updateFromWifiConfiguration(config); 387 mCurrentConnectionEvent.mConfigBssid = "any"; 388 mCurrentConnectionEvent.mRealStartTime = mClock.getElapsedSinceBootMillis(); 389 mCurrentConnectionEvent.mWifiState = mWifiState; 390 mCurrentConnectionEvent.mScreenOn = mScreenOn; 391 mConnectionEventList.add(mCurrentConnectionEvent); 392 mScanResultRssiTimestampMillis = -1; 393 if (config != null) { 394 ScanResult candidate = config.getNetworkSelectionStatus().getCandidate(); 395 if (candidate != null) { 396 // Cache the RSSI of the candidate, as the connection event level is updated 397 // from other sources (polls, bssid_associations) and delta requires the 398 // scanResult rssi 399 mScanResultRssi = candidate.level; 400 mScanResultRssiTimestampMillis = mClock.getElapsedSinceBootMillis(); 401 } 402 } 403 } 404 } 405 406 /** 407 * set the RoamType of the current ConnectionEvent (if any) 408 */ 409 public void setConnectionEventRoamType(int roamType) { 410 synchronized (mLock) { 411 if (mCurrentConnectionEvent != null) { 412 mCurrentConnectionEvent.mConnectionEvent.roamType = roamType; 413 } 414 } 415 } 416 417 /** 418 * Set AP related metrics from ScanDetail 419 */ 420 public void setConnectionScanDetail(ScanDetail scanDetail) { 421 synchronized (mLock) { 422 if (mCurrentConnectionEvent != null && scanDetail != null) { 423 NetworkDetail networkDetail = scanDetail.getNetworkDetail(); 424 ScanResult scanResult = scanDetail.getScanResult(); 425 //Ensure that we have a networkDetail, and that it corresponds to the currently 426 //tracked connection attempt 427 if (networkDetail != null && scanResult != null 428 && mCurrentConnectionEvent.mConfigSsid != null 429 && mCurrentConnectionEvent.mConfigSsid 430 .equals("\"" + networkDetail.getSSID() + "\"")) { 431 updateMetricsFromNetworkDetail(networkDetail); 432 updateMetricsFromScanResult(scanResult); 433 } 434 } 435 } 436 } 437 438 /** 439 * End a Connection event record. Call when wifi connection attempt succeeds or fails. 440 * If a Connection event has not been started and is active when .end is called, a new one is 441 * created with zero duration. 442 * 443 * @param level2FailureCode Level 2 failure code returned by supplicant 444 * @param connectivityFailureCode WifiMetricsProto.ConnectionEvent.HLF_X 445 */ 446 public void endConnectionEvent(int level2FailureCode, int connectivityFailureCode) { 447 synchronized (mLock) { 448 if (mCurrentConnectionEvent != null) { 449 boolean result = (level2FailureCode == 1) 450 && (connectivityFailureCode == WifiMetricsProto.ConnectionEvent.HLF_NONE); 451 mCurrentConnectionEvent.mConnectionEvent.connectionResult = result ? 1 : 0; 452 mCurrentConnectionEvent.mRealEndTime = mClock.getElapsedSinceBootMillis(); 453 mCurrentConnectionEvent.mConnectionEvent.durationTakenToConnectMillis = (int) 454 (mCurrentConnectionEvent.mRealEndTime 455 - mCurrentConnectionEvent.mRealStartTime); 456 mCurrentConnectionEvent.mConnectionEvent.level2FailureCode = level2FailureCode; 457 mCurrentConnectionEvent.mConnectionEvent.connectivityLevelFailureCode = 458 connectivityFailureCode; 459 // ConnectionEvent already added to ConnectionEvents List. Safe to null current here 460 mCurrentConnectionEvent = null; 461 if (!result) { 462 mScanResultRssiTimestampMillis = -1; 463 } 464 } 465 } 466 } 467 468 /** 469 * Set ConnectionEvent DTIM Interval (if set), and 802.11 Connection mode, from NetworkDetail 470 */ 471 private void updateMetricsFromNetworkDetail(NetworkDetail networkDetail) { 472 int dtimInterval = networkDetail.getDtimInterval(); 473 if (dtimInterval > 0) { 474 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.dtim = 475 dtimInterval; 476 } 477 int connectionWifiMode; 478 switch (networkDetail.getWifiMode()) { 479 case InformationElementUtil.WifiMode.MODE_UNDEFINED: 480 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_UNKNOWN; 481 break; 482 case InformationElementUtil.WifiMode.MODE_11A: 483 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_A; 484 break; 485 case InformationElementUtil.WifiMode.MODE_11B: 486 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_B; 487 break; 488 case InformationElementUtil.WifiMode.MODE_11G: 489 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_G; 490 break; 491 case InformationElementUtil.WifiMode.MODE_11N: 492 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_N; 493 break; 494 case InformationElementUtil.WifiMode.MODE_11AC : 495 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_AC; 496 break; 497 default: 498 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_OTHER; 499 break; 500 } 501 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto 502 .routerTechnology = connectionWifiMode; 503 } 504 505 /** 506 * Set ConnectionEvent RSSI and authentication type from ScanResult 507 */ 508 private void updateMetricsFromScanResult(ScanResult scanResult) { 509 mCurrentConnectionEvent.mConnectionEvent.signalStrength = scanResult.level; 510 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication = 511 WifiMetricsProto.RouterFingerPrint.AUTH_OPEN; 512 mCurrentConnectionEvent.mConfigBssid = scanResult.BSSID; 513 if (scanResult.capabilities != null) { 514 if (ScanResultUtil.isScanResultForWepNetwork(scanResult)) { 515 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication = 516 WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL; 517 } else if (ScanResultUtil.isScanResultForPskNetwork(scanResult)) { 518 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication = 519 WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL; 520 } else if (ScanResultUtil.isScanResultForEapNetwork(scanResult)) { 521 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication = 522 WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE; 523 } 524 } 525 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.channelInfo = 526 scanResult.frequency; 527 } 528 529 void setIsLocationEnabled(boolean enabled) { 530 synchronized (mLock) { 531 mWifiLogProto.isLocationEnabled = enabled; 532 } 533 } 534 535 void setIsScanningAlwaysEnabled(boolean enabled) { 536 synchronized (mLock) { 537 mWifiLogProto.isScanningAlwaysEnabled = enabled; 538 } 539 } 540 541 /** 542 * Increment Non Empty Scan Results count 543 */ 544 public void incrementNonEmptyScanResultCount() { 545 if (DBG) Log.v(TAG, "incrementNonEmptyScanResultCount"); 546 synchronized (mLock) { 547 mWifiLogProto.numNonEmptyScanResults++; 548 } 549 } 550 551 /** 552 * Increment Empty Scan Results count 553 */ 554 public void incrementEmptyScanResultCount() { 555 if (DBG) Log.v(TAG, "incrementEmptyScanResultCount"); 556 synchronized (mLock) { 557 mWifiLogProto.numEmptyScanResults++; 558 } 559 } 560 561 /** 562 * Increment background scan count 563 */ 564 public void incrementBackgroundScanCount() { 565 if (DBG) Log.v(TAG, "incrementBackgroundScanCount"); 566 synchronized (mLock) { 567 mWifiLogProto.numBackgroundScans++; 568 } 569 } 570 571 /** 572 * Get Background scan count 573 */ 574 public int getBackgroundScanCount() { 575 synchronized (mLock) { 576 return mWifiLogProto.numBackgroundScans; 577 } 578 } 579 580 /** 581 * Increment oneshot scan count, and the associated WifiSystemScanStateCount entry 582 */ 583 public void incrementOneshotScanCount() { 584 synchronized (mLock) { 585 mWifiLogProto.numOneshotScans++; 586 } 587 incrementWifiSystemScanStateCount(mWifiState, mScreenOn); 588 } 589 590 /** 591 * Get oneshot scan count 592 */ 593 public int getOneshotScanCount() { 594 synchronized (mLock) { 595 return mWifiLogProto.numOneshotScans; 596 } 597 } 598 599 private String returnCodeToString(int scanReturnCode) { 600 switch(scanReturnCode){ 601 case WifiMetricsProto.WifiLog.SCAN_UNKNOWN: 602 return "SCAN_UNKNOWN"; 603 case WifiMetricsProto.WifiLog.SCAN_SUCCESS: 604 return "SCAN_SUCCESS"; 605 case WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED: 606 return "SCAN_FAILURE_INTERRUPTED"; 607 case WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION: 608 return "SCAN_FAILURE_INVALID_CONFIGURATION"; 609 case WifiMetricsProto.WifiLog.FAILURE_WIFI_DISABLED: 610 return "FAILURE_WIFI_DISABLED"; 611 default: 612 return "<UNKNOWN>"; 613 } 614 } 615 616 /** 617 * Increment count of scan return code occurrence 618 * 619 * @param scanReturnCode Return code from scan attempt WifiMetricsProto.WifiLog.SCAN_X 620 */ 621 public void incrementScanReturnEntry(int scanReturnCode, int countToAdd) { 622 synchronized (mLock) { 623 if (DBG) Log.v(TAG, "incrementScanReturnEntry " + returnCodeToString(scanReturnCode)); 624 int entry = mScanReturnEntries.get(scanReturnCode); 625 entry += countToAdd; 626 mScanReturnEntries.put(scanReturnCode, entry); 627 } 628 } 629 /** 630 * Get the count of this scanReturnCode 631 * @param scanReturnCode that we are getting the count for 632 */ 633 public int getScanReturnEntry(int scanReturnCode) { 634 synchronized (mLock) { 635 return mScanReturnEntries.get(scanReturnCode); 636 } 637 } 638 639 private String wifiSystemStateToString(int state) { 640 switch(state){ 641 case WifiMetricsProto.WifiLog.WIFI_UNKNOWN: 642 return "WIFI_UNKNOWN"; 643 case WifiMetricsProto.WifiLog.WIFI_DISABLED: 644 return "WIFI_DISABLED"; 645 case WifiMetricsProto.WifiLog.WIFI_DISCONNECTED: 646 return "WIFI_DISCONNECTED"; 647 case WifiMetricsProto.WifiLog.WIFI_ASSOCIATED: 648 return "WIFI_ASSOCIATED"; 649 default: 650 return "default"; 651 } 652 } 653 654 /** 655 * Increments the count of scans initiated by each wifi state, accounts for screenOn/Off 656 * 657 * @param state State of the system when scan was initiated, see WifiMetricsProto.WifiLog.WIFI_X 658 * @param screenOn Is the screen on 659 */ 660 public void incrementWifiSystemScanStateCount(int state, boolean screenOn) { 661 synchronized (mLock) { 662 if (DBG) { 663 Log.v(TAG, "incrementWifiSystemScanStateCount " + wifiSystemStateToString(state) 664 + " " + screenOn); 665 } 666 int index = (state * 2) + (screenOn ? SCREEN_ON : SCREEN_OFF); 667 int entry = mWifiSystemStateEntries.get(index); 668 entry++; 669 mWifiSystemStateEntries.put(index, entry); 670 } 671 } 672 673 /** 674 * Get the count of this system State Entry 675 */ 676 public int getSystemStateCount(int state, boolean screenOn) { 677 synchronized (mLock) { 678 int index = state * 2 + (screenOn ? SCREEN_ON : SCREEN_OFF); 679 return mWifiSystemStateEntries.get(index); 680 } 681 } 682 683 /** 684 * Increment number of times the Watchdog of Last Resort triggered, resetting the wifi stack 685 */ 686 public void incrementNumLastResortWatchdogTriggers() { 687 synchronized (mLock) { 688 mWifiLogProto.numLastResortWatchdogTriggers++; 689 } 690 } 691 /** 692 * @param count number of networks over bad association threshold when watchdog triggered 693 */ 694 public void addCountToNumLastResortWatchdogBadAssociationNetworksTotal(int count) { 695 synchronized (mLock) { 696 mWifiLogProto.numLastResortWatchdogBadAssociationNetworksTotal += count; 697 } 698 } 699 /** 700 * @param count number of networks over bad authentication threshold when watchdog triggered 701 */ 702 public void addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal(int count) { 703 synchronized (mLock) { 704 mWifiLogProto.numLastResortWatchdogBadAuthenticationNetworksTotal += count; 705 } 706 } 707 /** 708 * @param count number of networks over bad dhcp threshold when watchdog triggered 709 */ 710 public void addCountToNumLastResortWatchdogBadDhcpNetworksTotal(int count) { 711 synchronized (mLock) { 712 mWifiLogProto.numLastResortWatchdogBadDhcpNetworksTotal += count; 713 } 714 } 715 /** 716 * @param count number of networks over bad other threshold when watchdog triggered 717 */ 718 public void addCountToNumLastResortWatchdogBadOtherNetworksTotal(int count) { 719 synchronized (mLock) { 720 mWifiLogProto.numLastResortWatchdogBadOtherNetworksTotal += count; 721 } 722 } 723 /** 724 * @param count number of networks seen when watchdog triggered 725 */ 726 public void addCountToNumLastResortWatchdogAvailableNetworksTotal(int count) { 727 synchronized (mLock) { 728 mWifiLogProto.numLastResortWatchdogAvailableNetworksTotal += count; 729 } 730 } 731 /** 732 * Increment count of triggers with atleast one bad association network 733 */ 734 public void incrementNumLastResortWatchdogTriggersWithBadAssociation() { 735 synchronized (mLock) { 736 mWifiLogProto.numLastResortWatchdogTriggersWithBadAssociation++; 737 } 738 } 739 /** 740 * Increment count of triggers with atleast one bad authentication network 741 */ 742 public void incrementNumLastResortWatchdogTriggersWithBadAuthentication() { 743 synchronized (mLock) { 744 mWifiLogProto.numLastResortWatchdogTriggersWithBadAuthentication++; 745 } 746 } 747 /** 748 * Increment count of triggers with atleast one bad dhcp network 749 */ 750 public void incrementNumLastResortWatchdogTriggersWithBadDhcp() { 751 synchronized (mLock) { 752 mWifiLogProto.numLastResortWatchdogTriggersWithBadDhcp++; 753 } 754 } 755 /** 756 * Increment count of triggers with atleast one bad other network 757 */ 758 public void incrementNumLastResortWatchdogTriggersWithBadOther() { 759 synchronized (mLock) { 760 mWifiLogProto.numLastResortWatchdogTriggersWithBadOther++; 761 } 762 } 763 764 /** 765 * Increment number of times connectivity watchdog confirmed pno is working 766 */ 767 public void incrementNumConnectivityWatchdogPnoGood() { 768 synchronized (mLock) { 769 mWifiLogProto.numConnectivityWatchdogPnoGood++; 770 } 771 } 772 /** 773 * Increment number of times connectivity watchdog found pno not working 774 */ 775 public void incrementNumConnectivityWatchdogPnoBad() { 776 synchronized (mLock) { 777 mWifiLogProto.numConnectivityWatchdogPnoBad++; 778 } 779 } 780 /** 781 * Increment number of times connectivity watchdog confirmed background scan is working 782 */ 783 public void incrementNumConnectivityWatchdogBackgroundGood() { 784 synchronized (mLock) { 785 mWifiLogProto.numConnectivityWatchdogBackgroundGood++; 786 } 787 } 788 /** 789 * Increment number of times connectivity watchdog found background scan not working 790 */ 791 public void incrementNumConnectivityWatchdogBackgroundBad() { 792 synchronized (mLock) { 793 mWifiLogProto.numConnectivityWatchdogBackgroundBad++; 794 } 795 } 796 797 /** 798 * Increment occurence count of RSSI level from RSSI poll. 799 * Ignores rssi values outside the bounds of [MIN_RSSI_POLL, MAX_RSSI_POLL] 800 */ 801 public void incrementRssiPollRssiCount(int rssi) { 802 if (!(rssi >= MIN_RSSI_POLL && rssi <= MAX_RSSI_POLL)) { 803 return; 804 } 805 synchronized (mLock) { 806 int count = mRssiPollCounts.get(rssi); 807 mRssiPollCounts.put(rssi, count + 1); 808 maybeIncrementRssiDeltaCount(rssi - mScanResultRssi); 809 } 810 } 811 812 /** 813 * Increment occurence count of difference between scan result RSSI and the first RSSI poll. 814 * Ignores rssi values outside the bounds of [MIN_RSSI_DELTA, MAX_RSSI_DELTA] 815 * mLock must be held when calling this method. 816 */ 817 private void maybeIncrementRssiDeltaCount(int rssi) { 818 // Check if this RSSI poll is close enough to a scan result RSSI to log a delta value 819 if (mScanResultRssiTimestampMillis >= 0) { 820 long timeDelta = mClock.getElapsedSinceBootMillis() - mScanResultRssiTimestampMillis; 821 if (timeDelta <= TIMEOUT_RSSI_DELTA_MILLIS) { 822 if (rssi >= MIN_RSSI_DELTA && rssi <= MAX_RSSI_DELTA) { 823 int count = mRssiDeltaCounts.get(rssi); 824 mRssiDeltaCounts.put(rssi, count + 1); 825 } 826 } 827 mScanResultRssiTimestampMillis = -1; 828 } 829 } 830 831 /** 832 * Increment count of Watchdog successes. 833 */ 834 public void incrementNumLastResortWatchdogSuccesses() { 835 synchronized (mLock) { 836 mWifiLogProto.numLastResortWatchdogSuccesses++; 837 } 838 } 839 840 /** 841 * Increments the count of alerts by alert reason. 842 * 843 * @param reason The cause of the alert. The reason values are driver-specific. 844 */ 845 public void incrementAlertReasonCount(int reason) { 846 if (reason > WifiLoggerHal.WIFI_ALERT_REASON_MAX 847 || reason < WifiLoggerHal.WIFI_ALERT_REASON_MIN) { 848 reason = WifiLoggerHal.WIFI_ALERT_REASON_RESERVED; 849 } 850 synchronized (mLock) { 851 int alertCount = mWifiAlertReasonCounts.get(reason); 852 mWifiAlertReasonCounts.put(reason, alertCount + 1); 853 } 854 } 855 856 /** 857 * Counts all the different types of networks seen in a set of scan results 858 */ 859 public void countScanResults(List<ScanDetail> scanDetails) { 860 if (scanDetails == null) { 861 return; 862 } 863 int totalResults = 0; 864 int openNetworks = 0; 865 int personalNetworks = 0; 866 int enterpriseNetworks = 0; 867 int hiddenNetworks = 0; 868 int hotspot2r1Networks = 0; 869 int hotspot2r2Networks = 0; 870 for (ScanDetail scanDetail : scanDetails) { 871 NetworkDetail networkDetail = scanDetail.getNetworkDetail(); 872 ScanResult scanResult = scanDetail.getScanResult(); 873 totalResults++; 874 if (networkDetail != null) { 875 if (networkDetail.isHiddenBeaconFrame()) { 876 hiddenNetworks++; 877 } 878 if (networkDetail.getHSRelease() != null) { 879 if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R1) { 880 hotspot2r1Networks++; 881 } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R2) { 882 hotspot2r2Networks++; 883 } 884 } 885 } 886 if (scanResult != null && scanResult.capabilities != null) { 887 if (ScanResultUtil.isScanResultForEapNetwork(scanResult)) { 888 enterpriseNetworks++; 889 } else if (ScanResultUtil.isScanResultForPskNetwork(scanResult) 890 || ScanResultUtil.isScanResultForWepNetwork(scanResult)) { 891 personalNetworks++; 892 } else { 893 openNetworks++; 894 } 895 } 896 } 897 synchronized (mLock) { 898 mWifiLogProto.numTotalScanResults += totalResults; 899 mWifiLogProto.numOpenNetworkScanResults += openNetworks; 900 mWifiLogProto.numPersonalNetworkScanResults += personalNetworks; 901 mWifiLogProto.numEnterpriseNetworkScanResults += enterpriseNetworks; 902 mWifiLogProto.numHiddenNetworkScanResults += hiddenNetworks; 903 mWifiLogProto.numHotspot2R1NetworkScanResults += hotspot2r1Networks; 904 mWifiLogProto.numHotspot2R2NetworkScanResults += hotspot2r2Networks; 905 mWifiLogProto.numScans++; 906 } 907 } 908 909 /** 910 * Increments occurence of a particular wifi score calculated 911 * in WifiScoreReport by current connected network. Scores are bounded 912 * within [MIN_WIFI_SCORE, MAX_WIFI_SCORE] to limit size of SparseArray 913 */ 914 public void incrementWifiScoreCount(int score) { 915 if (score < MIN_WIFI_SCORE || score > MAX_WIFI_SCORE) { 916 return; 917 } 918 synchronized (mLock) { 919 int count = mWifiScoreCounts.get(score); 920 mWifiScoreCounts.put(score, count + 1); 921 } 922 } 923 924 /** 925 * Increments occurence of the results from attempting to start SoftAp. 926 * Maps the |result| and WifiManager |failureCode| constant to proto defined SoftApStartResult 927 * codes. 928 */ 929 public void incrementSoftApStartResult(boolean result, int failureCode) { 930 synchronized (mLock) { 931 if (result) { 932 int count = mSoftApManagerReturnCodeCounts.get( 933 WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY); 934 mSoftApManagerReturnCodeCounts.put( 935 WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY, 936 count + 1); 937 return; 938 } 939 940 // now increment failure modes - if not explicitly handled, dump into the general 941 // error bucket. 942 if (failureCode == WifiManager.SAP_START_FAILURE_NO_CHANNEL) { 943 int count = mSoftApManagerReturnCodeCounts.get( 944 WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL); 945 mSoftApManagerReturnCodeCounts.put( 946 WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL, 947 count + 1); 948 } else { 949 // failure mode not tracked at this time... count as a general error for now. 950 int count = mSoftApManagerReturnCodeCounts.get( 951 WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR); 952 mSoftApManagerReturnCodeCounts.put( 953 WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR, 954 count + 1); 955 } 956 } 957 } 958 959 public static final String PROTO_DUMP_ARG = "wifiMetricsProto"; 960 public static final String CLEAN_DUMP_ARG = "clean"; 961 962 /** 963 * Dump all WifiMetrics. Collects some metrics from ConfigStore, Settings and WifiManager 964 * at this time. 965 * 966 * @param fd unused 967 * @param pw PrintWriter for writing dump to 968 * @param args unused 969 */ 970 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 971 synchronized (mLock) { 972 if (args.length > 0 && PROTO_DUMP_ARG.equals(args[0])) { 973 // Dump serialized WifiLog proto 974 consolidateProto(true); 975 for (ConnectionEvent event : mConnectionEventList) { 976 if (mCurrentConnectionEvent != event) { 977 //indicate that automatic bug report has been taken for all valid 978 //connection events 979 event.mConnectionEvent.automaticBugReportTaken = true; 980 } 981 } 982 byte[] wifiMetricsProto = WifiMetricsProto.WifiLog.toByteArray(mWifiLogProto); 983 String metricsProtoDump = Base64.encodeToString(wifiMetricsProto, Base64.DEFAULT); 984 if (args.length > 1 && CLEAN_DUMP_ARG.equals(args[1])) { 985 // Output metrics proto bytes (base64) and nothing else 986 pw.print(metricsProtoDump); 987 } else { 988 // Tag the start and end of the metrics proto bytes 989 pw.println("WifiMetrics:"); 990 pw.println(metricsProtoDump); 991 pw.println("EndWifiMetrics"); 992 } 993 clear(); 994 } else { 995 pw.println("WifiMetrics:"); 996 pw.println("mConnectionEvents:"); 997 for (ConnectionEvent event : mConnectionEventList) { 998 String eventLine = event.toString(); 999 if (event == mCurrentConnectionEvent) { 1000 eventLine += "CURRENTLY OPEN EVENT"; 1001 } 1002 pw.println(eventLine); 1003 } 1004 pw.println("mWifiLogProto.numSavedNetworks=" + mWifiLogProto.numSavedNetworks); 1005 pw.println("mWifiLogProto.numOpenNetworks=" + mWifiLogProto.numOpenNetworks); 1006 pw.println("mWifiLogProto.numPersonalNetworks=" 1007 + mWifiLogProto.numPersonalNetworks); 1008 pw.println("mWifiLogProto.numEnterpriseNetworks=" 1009 + mWifiLogProto.numEnterpriseNetworks); 1010 pw.println("mWifiLogProto.numHiddenNetworks=" + mWifiLogProto.numHiddenNetworks); 1011 pw.println("mWifiLogProto.numPasspointNetworks=" 1012 + mWifiLogProto.numPasspointNetworks); 1013 pw.println("mWifiLogProto.isLocationEnabled=" + mWifiLogProto.isLocationEnabled); 1014 pw.println("mWifiLogProto.isScanningAlwaysEnabled=" 1015 + mWifiLogProto.isScanningAlwaysEnabled); 1016 pw.println("mWifiLogProto.numNetworksAddedByUser=" 1017 + mWifiLogProto.numNetworksAddedByUser); 1018 pw.println("mWifiLogProto.numNetworksAddedByApps=" 1019 + mWifiLogProto.numNetworksAddedByApps); 1020 pw.println("mWifiLogProto.numNonEmptyScanResults=" 1021 + mWifiLogProto.numNonEmptyScanResults); 1022 pw.println("mWifiLogProto.numEmptyScanResults=" 1023 + mWifiLogProto.numEmptyScanResults); 1024 pw.println("mWifiLogProto.numOneshotScans=" 1025 + mWifiLogProto.numOneshotScans); 1026 pw.println("mWifiLogProto.numBackgroundScans=" 1027 + mWifiLogProto.numBackgroundScans); 1028 1029 pw.println("mScanReturnEntries:"); 1030 pw.println(" SCAN_UNKNOWN: " + getScanReturnEntry( 1031 WifiMetricsProto.WifiLog.SCAN_UNKNOWN)); 1032 pw.println(" SCAN_SUCCESS: " + getScanReturnEntry( 1033 WifiMetricsProto.WifiLog.SCAN_SUCCESS)); 1034 pw.println(" SCAN_FAILURE_INTERRUPTED: " + getScanReturnEntry( 1035 WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED)); 1036 pw.println(" SCAN_FAILURE_INVALID_CONFIGURATION: " + getScanReturnEntry( 1037 WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION)); 1038 pw.println(" FAILURE_WIFI_DISABLED: " + getScanReturnEntry( 1039 WifiMetricsProto.WifiLog.FAILURE_WIFI_DISABLED)); 1040 1041 pw.println("mSystemStateEntries: <state><screenOn> : <scansInitiated>"); 1042 pw.println(" WIFI_UNKNOWN ON: " 1043 + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, true)); 1044 pw.println(" WIFI_DISABLED ON: " 1045 + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISABLED, true)); 1046 pw.println(" WIFI_DISCONNECTED ON: " 1047 + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED, true)); 1048 pw.println(" WIFI_ASSOCIATED ON: " 1049 + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, true)); 1050 pw.println(" WIFI_UNKNOWN OFF: " 1051 + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, false)); 1052 pw.println(" WIFI_DISABLED OFF: " 1053 + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISABLED, false)); 1054 pw.println(" WIFI_DISCONNECTED OFF: " 1055 + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED, false)); 1056 pw.println(" WIFI_ASSOCIATED OFF: " 1057 + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, false)); 1058 pw.println("mWifiLogProto.numConnectivityWatchdogPnoGood=" 1059 + mWifiLogProto.numConnectivityWatchdogPnoGood); 1060 pw.println("mWifiLogProto.numConnectivityWatchdogPnoBad=" 1061 + mWifiLogProto.numConnectivityWatchdogPnoBad); 1062 pw.println("mWifiLogProto.numConnectivityWatchdogBackgroundGood=" 1063 + mWifiLogProto.numConnectivityWatchdogBackgroundGood); 1064 pw.println("mWifiLogProto.numConnectivityWatchdogBackgroundBad=" 1065 + mWifiLogProto.numConnectivityWatchdogBackgroundBad); 1066 pw.println("mWifiLogProto.numLastResortWatchdogTriggers=" 1067 + mWifiLogProto.numLastResortWatchdogTriggers); 1068 pw.println("mWifiLogProto.numLastResortWatchdogBadAssociationNetworksTotal=" 1069 + mWifiLogProto.numLastResortWatchdogBadAssociationNetworksTotal); 1070 pw.println("mWifiLogProto.numLastResortWatchdogBadAuthenticationNetworksTotal=" 1071 + mWifiLogProto.numLastResortWatchdogBadAuthenticationNetworksTotal); 1072 pw.println("mWifiLogProto.numLastResortWatchdogBadDhcpNetworksTotal=" 1073 + mWifiLogProto.numLastResortWatchdogBadDhcpNetworksTotal); 1074 pw.println("mWifiLogProto.numLastResortWatchdogBadOtherNetworksTotal=" 1075 + mWifiLogProto.numLastResortWatchdogBadOtherNetworksTotal); 1076 pw.println("mWifiLogProto.numLastResortWatchdogAvailableNetworksTotal=" 1077 + mWifiLogProto.numLastResortWatchdogAvailableNetworksTotal); 1078 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadAssociation=" 1079 + mWifiLogProto.numLastResortWatchdogTriggersWithBadAssociation); 1080 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadAuthentication=" 1081 + mWifiLogProto.numLastResortWatchdogTriggersWithBadAuthentication); 1082 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadDhcp=" 1083 + mWifiLogProto.numLastResortWatchdogTriggersWithBadDhcp); 1084 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadOther=" 1085 + mWifiLogProto.numLastResortWatchdogTriggersWithBadOther); 1086 pw.println("mWifiLogProto.numLastResortWatchdogSuccesses=" 1087 + mWifiLogProto.numLastResortWatchdogSuccesses); 1088 pw.println("mWifiLogProto.recordDurationSec=" 1089 + ((mClock.getElapsedSinceBootMillis() / 1000) - mRecordStartTimeSec)); 1090 pw.println("mWifiLogProto.rssiPollRssiCount: Printing counts for [" + MIN_RSSI_POLL 1091 + ", " + MAX_RSSI_POLL + "]"); 1092 StringBuilder sb = new StringBuilder(); 1093 for (int i = MIN_RSSI_POLL; i <= MAX_RSSI_POLL; i++) { 1094 sb.append(mRssiPollCounts.get(i) + " "); 1095 } 1096 pw.println(" " + sb.toString()); 1097 pw.println("mWifiLogProto.rssiPollDeltaCount: Printing counts for [" 1098 + MIN_RSSI_DELTA + ", " + MAX_RSSI_DELTA + "]"); 1099 sb.setLength(0); 1100 for (int i = MIN_RSSI_DELTA; i <= MAX_RSSI_DELTA; i++) { 1101 sb.append(mRssiDeltaCounts.get(i) + " "); 1102 } 1103 pw.println(" " + sb.toString()); 1104 pw.print("mWifiLogProto.alertReasonCounts="); 1105 sb.setLength(0); 1106 for (int i = WifiLoggerHal.WIFI_ALERT_REASON_MIN; 1107 i <= WifiLoggerHal.WIFI_ALERT_REASON_MAX; i++) { 1108 int count = mWifiAlertReasonCounts.get(i); 1109 if (count > 0) { 1110 sb.append("(" + i + "," + count + "),"); 1111 } 1112 } 1113 if (sb.length() > 1) { 1114 sb.setLength(sb.length() - 1); // strip trailing comma 1115 pw.println(sb.toString()); 1116 } else { 1117 pw.println("()"); 1118 } 1119 pw.println("mWifiLogProto.numTotalScanResults=" 1120 + mWifiLogProto.numTotalScanResults); 1121 pw.println("mWifiLogProto.numOpenNetworkScanResults=" 1122 + mWifiLogProto.numOpenNetworkScanResults); 1123 pw.println("mWifiLogProto.numPersonalNetworkScanResults=" 1124 + mWifiLogProto.numPersonalNetworkScanResults); 1125 pw.println("mWifiLogProto.numEnterpriseNetworkScanResults=" 1126 + mWifiLogProto.numEnterpriseNetworkScanResults); 1127 pw.println("mWifiLogProto.numHiddenNetworkScanResults=" 1128 + mWifiLogProto.numHiddenNetworkScanResults); 1129 pw.println("mWifiLogProto.numHotspot2R1NetworkScanResults=" 1130 + mWifiLogProto.numHotspot2R1NetworkScanResults); 1131 pw.println("mWifiLogProto.numHotspot2R2NetworkScanResults=" 1132 + mWifiLogProto.numHotspot2R2NetworkScanResults); 1133 pw.println("mWifiLogProto.numScans=" + mWifiLogProto.numScans); 1134 pw.println("mWifiLogProto.WifiScoreCount: [" + MIN_WIFI_SCORE + ", " 1135 + MAX_WIFI_SCORE + "]"); 1136 for (int i = 0; i <= MAX_WIFI_SCORE; i++) { 1137 pw.print(mWifiScoreCounts.get(i) + " "); 1138 } 1139 pw.println(); // add a line after wifi scores 1140 pw.println("mWifiLogProto.SoftApManagerReturnCodeCounts:"); 1141 pw.println(" SUCCESS: " + mSoftApManagerReturnCodeCounts.get( 1142 WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY)); 1143 pw.println(" FAILED_GENERAL_ERROR: " + mSoftApManagerReturnCodeCounts.get( 1144 WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR)); 1145 pw.println(" FAILED_NO_CHANNEL: " + mSoftApManagerReturnCodeCounts.get( 1146 WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL)); 1147 pw.print("\n"); 1148 } 1149 } 1150 } 1151 1152 1153 /** 1154 * Update various counts of saved network types 1155 * @param networks List of WifiConfigurations representing all saved networks, must not be null 1156 */ 1157 public void updateSavedNetworks(List<WifiConfiguration> networks) { 1158 synchronized (mLock) { 1159 mWifiLogProto.numSavedNetworks = networks.size(); 1160 mWifiLogProto.numOpenNetworks = 0; 1161 mWifiLogProto.numPersonalNetworks = 0; 1162 mWifiLogProto.numEnterpriseNetworks = 0; 1163 mWifiLogProto.numNetworksAddedByUser = 0; 1164 mWifiLogProto.numNetworksAddedByApps = 0; 1165 mWifiLogProto.numHiddenNetworks = 0; 1166 mWifiLogProto.numPasspointNetworks = 0; 1167 for (WifiConfiguration config : networks) { 1168 if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)) { 1169 mWifiLogProto.numOpenNetworks++; 1170 } else if (config.isEnterprise()) { 1171 mWifiLogProto.numEnterpriseNetworks++; 1172 } else { 1173 mWifiLogProto.numPersonalNetworks++; 1174 } 1175 if (config.selfAdded) { 1176 mWifiLogProto.numNetworksAddedByUser++; 1177 } else { 1178 mWifiLogProto.numNetworksAddedByApps++; 1179 } 1180 if (config.hiddenSSID) { 1181 mWifiLogProto.numHiddenNetworks++; 1182 } 1183 if (config.isPasspoint()) { 1184 mWifiLogProto.numPasspointNetworks++; 1185 } 1186 } 1187 } 1188 } 1189 1190 /** 1191 * append the separate ConnectionEvent, SystemStateEntry and ScanReturnCode collections to their 1192 * respective lists within mWifiLogProto 1193 * 1194 * @param incremental Only include ConnectionEvents created since last automatic bug report 1195 */ 1196 private void consolidateProto(boolean incremental) { 1197 List<WifiMetricsProto.ConnectionEvent> events = new ArrayList<>(); 1198 List<WifiMetricsProto.RssiPollCount> rssis = new ArrayList<>(); 1199 List<WifiMetricsProto.RssiPollCount> rssiDeltas = new ArrayList<>(); 1200 List<WifiMetricsProto.AlertReasonCount> alertReasons = new ArrayList<>(); 1201 List<WifiMetricsProto.WifiScoreCount> scores = new ArrayList<>(); 1202 synchronized (mLock) { 1203 for (ConnectionEvent event : mConnectionEventList) { 1204 // If this is not incremental, dump full ConnectionEvent list 1205 // Else Dump all un-dumped events except for the current one 1206 if (!incremental || ((mCurrentConnectionEvent != event) 1207 && !event.mConnectionEvent.automaticBugReportTaken)) { 1208 //Get all ConnectionEvents that haven not been dumped as a proto, also exclude 1209 //the current active un-ended connection event 1210 events.add(event.mConnectionEvent); 1211 if (incremental) { 1212 event.mConnectionEvent.automaticBugReportTaken = true; 1213 } 1214 } 1215 } 1216 if (events.size() > 0) { 1217 mWifiLogProto.connectionEvent = events.toArray(mWifiLogProto.connectionEvent); 1218 } 1219 1220 //Convert the SparseIntArray of scanReturnEntry integers into ScanReturnEntry proto list 1221 mWifiLogProto.scanReturnEntries = 1222 new WifiMetricsProto.WifiLog.ScanReturnEntry[mScanReturnEntries.size()]; 1223 for (int i = 0; i < mScanReturnEntries.size(); i++) { 1224 mWifiLogProto.scanReturnEntries[i] = new WifiMetricsProto.WifiLog.ScanReturnEntry(); 1225 mWifiLogProto.scanReturnEntries[i].scanReturnCode = mScanReturnEntries.keyAt(i); 1226 mWifiLogProto.scanReturnEntries[i].scanResultsCount = mScanReturnEntries.valueAt(i); 1227 } 1228 1229 // Convert the SparseIntArray of systemStateEntry into WifiSystemStateEntry proto list 1230 // This one is slightly more complex, as the Sparse are indexed with: 1231 // key: wifiState * 2 + isScreenOn, value: wifiStateCount 1232 mWifiLogProto.wifiSystemStateEntries = 1233 new WifiMetricsProto.WifiLog 1234 .WifiSystemStateEntry[mWifiSystemStateEntries.size()]; 1235 for (int i = 0; i < mWifiSystemStateEntries.size(); i++) { 1236 mWifiLogProto.wifiSystemStateEntries[i] = 1237 new WifiMetricsProto.WifiLog.WifiSystemStateEntry(); 1238 mWifiLogProto.wifiSystemStateEntries[i].wifiState = 1239 mWifiSystemStateEntries.keyAt(i) / 2; 1240 mWifiLogProto.wifiSystemStateEntries[i].wifiStateCount = 1241 mWifiSystemStateEntries.valueAt(i); 1242 mWifiLogProto.wifiSystemStateEntries[i].isScreenOn = 1243 (mWifiSystemStateEntries.keyAt(i) % 2) > 0; 1244 } 1245 mWifiLogProto.recordDurationSec = (int) ((mClock.getElapsedSinceBootMillis() / 1000) 1246 - mRecordStartTimeSec); 1247 1248 /** 1249 * Convert the SparseIntArray of RSSI poll rssi's and counts to the proto's repeated 1250 * IntKeyVal array. 1251 */ 1252 for (int i = 0; i < mRssiPollCounts.size(); i++) { 1253 WifiMetricsProto.RssiPollCount keyVal = new WifiMetricsProto.RssiPollCount(); 1254 keyVal.rssi = mRssiPollCounts.keyAt(i); 1255 keyVal.count = mRssiPollCounts.valueAt(i); 1256 rssis.add(keyVal); 1257 } 1258 mWifiLogProto.rssiPollRssiCount = rssis.toArray(mWifiLogProto.rssiPollRssiCount); 1259 1260 /** 1261 * Convert the SparseIntArray of RSSI delta rssi's and counts to the proto's repeated 1262 * IntKeyVal array. 1263 */ 1264 for (int i = 0; i < mRssiDeltaCounts.size(); i++) { 1265 WifiMetricsProto.RssiPollCount keyVal = new WifiMetricsProto.RssiPollCount(); 1266 keyVal.rssi = mRssiDeltaCounts.keyAt(i); 1267 keyVal.count = mRssiDeltaCounts.valueAt(i); 1268 rssiDeltas.add(keyVal); 1269 } 1270 mWifiLogProto.rssiPollDeltaCount = rssiDeltas.toArray(mWifiLogProto.rssiPollDeltaCount); 1271 1272 /** 1273 * Convert the SparseIntArray of alert reasons and counts to the proto's repeated 1274 * IntKeyVal array. 1275 */ 1276 for (int i = 0; i < mWifiAlertReasonCounts.size(); i++) { 1277 WifiMetricsProto.AlertReasonCount keyVal = new WifiMetricsProto.AlertReasonCount(); 1278 keyVal.reason = mWifiAlertReasonCounts.keyAt(i); 1279 keyVal.count = mWifiAlertReasonCounts.valueAt(i); 1280 alertReasons.add(keyVal); 1281 } 1282 mWifiLogProto.alertReasonCount = alertReasons.toArray(mWifiLogProto.alertReasonCount); 1283 /** 1284 * Convert the SparseIntArray of Wifi Score and counts to proto's repeated 1285 * IntKeyVal array. 1286 */ 1287 for (int score = 0; score < mWifiScoreCounts.size(); score++) { 1288 WifiMetricsProto.WifiScoreCount keyVal = new WifiMetricsProto.WifiScoreCount(); 1289 keyVal.score = mWifiScoreCounts.keyAt(score); 1290 keyVal.count = mWifiScoreCounts.valueAt(score); 1291 scores.add(keyVal); 1292 } 1293 mWifiLogProto.wifiScoreCount = scores.toArray(mWifiLogProto.wifiScoreCount); 1294 1295 /** 1296 * Convert the SparseIntArray of SoftAp Return codes and counts to proto's repeated 1297 * IntKeyVal array. 1298 */ 1299 int codeCounts = mSoftApManagerReturnCodeCounts.size(); 1300 mWifiLogProto.softApReturnCode = new WifiMetricsProto.SoftApReturnCodeCount[codeCounts]; 1301 for (int sapCode = 0; sapCode < codeCounts; sapCode++) { 1302 mWifiLogProto.softApReturnCode[sapCode] = 1303 new WifiMetricsProto.SoftApReturnCodeCount(); 1304 mWifiLogProto.softApReturnCode[sapCode].startResult = 1305 mSoftApManagerReturnCodeCounts.keyAt(sapCode); 1306 mWifiLogProto.softApReturnCode[sapCode].count = 1307 mSoftApManagerReturnCodeCounts.valueAt(sapCode); 1308 } 1309 } 1310 } 1311 1312 /** 1313 * Clear all WifiMetrics, except for currentConnectionEvent. 1314 */ 1315 private void clear() { 1316 synchronized (mLock) { 1317 mConnectionEventList.clear(); 1318 if (mCurrentConnectionEvent != null) { 1319 mConnectionEventList.add(mCurrentConnectionEvent); 1320 } 1321 mScanReturnEntries.clear(); 1322 mWifiSystemStateEntries.clear(); 1323 mRecordStartTimeSec = mClock.getElapsedSinceBootMillis() / 1000; 1324 mRssiPollCounts.clear(); 1325 mRssiDeltaCounts.clear(); 1326 mWifiAlertReasonCounts.clear(); 1327 mWifiScoreCounts.clear(); 1328 mWifiLogProto.clear(); 1329 mScanResultRssiTimestampMillis = -1; 1330 mSoftApManagerReturnCodeCounts.clear(); 1331 } 1332 } 1333 1334 /** 1335 * Set screen state (On/Off) 1336 */ 1337 public void setScreenState(boolean screenOn) { 1338 synchronized (mLock) { 1339 mScreenOn = screenOn; 1340 } 1341 } 1342 1343 /** 1344 * Set wifi state (WIFI_UNKNOWN, WIFI_DISABLED, WIFI_DISCONNECTED, WIFI_ASSOCIATED) 1345 */ 1346 public void setWifiState(int wifiState) { 1347 synchronized (mLock) { 1348 mWifiState = wifiState; 1349 } 1350 } 1351} 1352