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