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