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