WifiMetrics.java revision a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7
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.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback; 20import android.net.NetworkAgent; 21import android.net.wifi.ScanResult; 22import android.net.wifi.SupplicantState; 23import android.net.wifi.WifiConfiguration; 24import android.net.wifi.WifiInfo; 25import android.net.wifi.WifiManager; 26import android.os.Handler; 27import android.os.Looper; 28import android.os.Message; 29import android.util.Base64; 30import android.util.Log; 31import android.util.Pair; 32import android.util.SparseIntArray; 33 34import com.android.server.wifi.aware.WifiAwareMetrics; 35import com.android.server.wifi.hotspot2.NetworkDetail; 36import com.android.server.wifi.hotspot2.PasspointManager; 37import com.android.server.wifi.hotspot2.PasspointMatch; 38import com.android.server.wifi.hotspot2.PasspointProvider; 39import com.android.server.wifi.nano.WifiMetricsProto; 40import com.android.server.wifi.nano.WifiMetricsProto.PnoScanMetrics; 41import com.android.server.wifi.nano.WifiMetricsProto.StaEvent; 42import com.android.server.wifi.nano.WifiMetricsProto.StaEvent.ConfigInfo; 43import com.android.server.wifi.util.InformationElementUtil; 44import com.android.server.wifi.util.ScanResultUtil; 45 46import java.io.FileDescriptor; 47import java.io.PrintWriter; 48import java.util.ArrayList; 49import java.util.BitSet; 50import java.util.Calendar; 51import java.util.HashSet; 52import java.util.LinkedList; 53import java.util.List; 54import java.util.Set; 55 56/** 57 * Provides storage for wireless connectivity metrics, as they are generated. 58 * Metrics logged by this class include: 59 * Aggregated connection stats (num of connections, num of failures, ...) 60 * Discrete connection event stats (time, duration, failure codes, ...) 61 * Router details (technology type, authentication type, ...) 62 * Scan stats 63 */ 64public class WifiMetrics { 65 private static final String TAG = "WifiMetrics"; 66 private static final boolean DBG = false; 67 /** 68 * Clamp the RSSI poll counts to values between [MIN,MAX]_RSSI_POLL 69 */ 70 private static final int MAX_RSSI_POLL = 0; 71 private static final int MIN_RSSI_POLL = -127; 72 public static final int MAX_RSSI_DELTA = 127; 73 public static final int MIN_RSSI_DELTA = -127; 74 /** Maximum time period between ScanResult and RSSI poll to generate rssi delta datapoint */ 75 public static final long TIMEOUT_RSSI_DELTA_MILLIS = 3000; 76 private static final int MIN_WIFI_SCORE = 0; 77 private static final int MAX_WIFI_SCORE = NetworkAgent.WIFI_BASE_SCORE; 78 private final Object mLock = new Object(); 79 private static final int MAX_CONNECTION_EVENTS = 256; 80 // Largest bucket in the NumConnectableNetworkCount histogram, 81 // anything large will be stored in this bucket 82 public static final int MAX_CONNECTABLE_SSID_NETWORK_BUCKET = 20; 83 public static final int MAX_CONNECTABLE_BSSID_NETWORK_BUCKET = 50; 84 public static final int MAX_TOTAL_SCAN_RESULT_SSIDS_BUCKET = 100; 85 public static final int MAX_TOTAL_SCAN_RESULTS_BUCKET = 250; 86 private Clock mClock; 87 private boolean mScreenOn; 88 private int mWifiState; 89 private WifiAwareMetrics mWifiAwareMetrics; 90 private final PnoScanMetrics mPnoScanMetrics = new PnoScanMetrics(); 91 private Handler mHandler; 92 private WifiConfigManager mWifiConfigManager; 93 private WifiNetworkSelector mWifiNetworkSelector; 94 private PasspointManager mPasspointManager; 95 /** 96 * Metrics are stored within an instance of the WifiLog proto during runtime, 97 * The ConnectionEvent, SystemStateEntries & ScanReturnEntries metrics are stored during 98 * runtime in member lists of this WifiMetrics class, with the final WifiLog proto being pieced 99 * together at dump-time 100 */ 101 private final WifiMetricsProto.WifiLog mWifiLogProto = new WifiMetricsProto.WifiLog(); 102 /** 103 * Session information that gets logged for every Wifi connection attempt. 104 */ 105 private final List<ConnectionEvent> mConnectionEventList = new ArrayList<>(); 106 /** 107 * The latest started (but un-ended) connection attempt 108 */ 109 private ConnectionEvent mCurrentConnectionEvent; 110 /** 111 * Count of number of times each scan return code, indexed by WifiLog.ScanReturnCode 112 */ 113 private final SparseIntArray mScanReturnEntries = new SparseIntArray(); 114 /** 115 * Mapping of system state to the counts of scans requested in that wifi state * screenOn 116 * combination. Indexed by WifiLog.WifiState * (1 + screenOn) 117 */ 118 private final SparseIntArray mWifiSystemStateEntries = new SparseIntArray(); 119 /** Mapping of RSSI values to counts. */ 120 private final SparseIntArray mRssiPollCounts = new SparseIntArray(); 121 /** Mapping of RSSI scan-poll delta values to counts. */ 122 private final SparseIntArray mRssiDeltaCounts = new SparseIntArray(); 123 /** RSSI of the scan result for the last connection event*/ 124 private int mScanResultRssi = 0; 125 /** Boot-relative timestamp when the last candidate scanresult was received, used to calculate 126 RSSI deltas. -1 designates no candidate scanResult being tracked */ 127 private long mScanResultRssiTimestampMillis = -1; 128 /** Mapping of alert reason to the respective alert count. */ 129 private final SparseIntArray mWifiAlertReasonCounts = new SparseIntArray(); 130 /** 131 * Records the getElapsedSinceBootMillis (in seconds) that represents the beginning of data 132 * capture for for this WifiMetricsProto 133 */ 134 private long mRecordStartTimeSec; 135 /** Mapping of Wifi Scores to counts */ 136 private final SparseIntArray mWifiScoreCounts = new SparseIntArray(); 137 /** Mapping of SoftApManager start SoftAp return codes to counts */ 138 private final SparseIntArray mSoftApManagerReturnCodeCounts = new SparseIntArray(); 139 140 private final SparseIntArray mTotalSsidsInScanHistogram = new SparseIntArray(); 141 private final SparseIntArray mTotalBssidsInScanHistogram = new SparseIntArray(); 142 private final SparseIntArray mAvailableOpenSsidsInScanHistogram = new SparseIntArray(); 143 private final SparseIntArray mAvailableOpenBssidsInScanHistogram = new SparseIntArray(); 144 private final SparseIntArray mAvailableSavedSsidsInScanHistogram = new SparseIntArray(); 145 private final SparseIntArray mAvailableSavedBssidsInScanHistogram = new SparseIntArray(); 146 private final SparseIntArray mAvailableOpenOrSavedSsidsInScanHistogram = new SparseIntArray(); 147 private final SparseIntArray mAvailableOpenOrSavedBssidsInScanHistogram = new SparseIntArray(); 148 private final SparseIntArray mAvailableSavedPasspointProviderProfilesInScanHistogram = 149 new SparseIntArray(); 150 private final SparseIntArray mAvailableSavedPasspointProviderBssidsInScanHistogram = 151 new SparseIntArray(); 152 153 class RouterFingerPrint { 154 private WifiMetricsProto.RouterFingerPrint mRouterFingerPrintProto; 155 RouterFingerPrint() { 156 mRouterFingerPrintProto = new WifiMetricsProto.RouterFingerPrint(); 157 } 158 159 public String toString() { 160 StringBuilder sb = new StringBuilder(); 161 synchronized (mLock) { 162 sb.append("mConnectionEvent.roamType=" + mRouterFingerPrintProto.roamType); 163 sb.append(", mChannelInfo=" + mRouterFingerPrintProto.channelInfo); 164 sb.append(", mDtim=" + mRouterFingerPrintProto.dtim); 165 sb.append(", mAuthentication=" + mRouterFingerPrintProto.authentication); 166 sb.append(", mHidden=" + mRouterFingerPrintProto.hidden); 167 sb.append(", mRouterTechnology=" + mRouterFingerPrintProto.routerTechnology); 168 sb.append(", mSupportsIpv6=" + mRouterFingerPrintProto.supportsIpv6); 169 } 170 return sb.toString(); 171 } 172 public void updateFromWifiConfiguration(WifiConfiguration config) { 173 synchronized (mLock) { 174 if (config != null) { 175 // Is this a hidden network 176 mRouterFingerPrintProto.hidden = config.hiddenSSID; 177 // Config may not have a valid dtimInterval set yet, in which case dtim will be zero 178 // (These are only populated from beacon frame scan results, which are returned as 179 // scan results from the chip far less frequently than Probe-responses) 180 if (config.dtimInterval > 0) { 181 mRouterFingerPrintProto.dtim = config.dtimInterval; 182 } 183 mCurrentConnectionEvent.mConfigSsid = config.SSID; 184 // Get AuthType information from config (We do this again from ScanResult after 185 // associating with BSSID) 186 if (config.allowedKeyManagement != null 187 && config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)) { 188 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto 189 .authentication = WifiMetricsProto.RouterFingerPrint.AUTH_OPEN; 190 } else if (config.isEnterprise()) { 191 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto 192 .authentication = WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE; 193 } else { 194 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto 195 .authentication = WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL; 196 } 197 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto 198 .passpoint = config.isPasspoint(); 199 // If there's a ScanResult candidate associated with this config already, get it and 200 // log (more accurate) metrics from it 201 ScanResult candidate = config.getNetworkSelectionStatus().getCandidate(); 202 if (candidate != null) { 203 updateMetricsFromScanResult(candidate); 204 } 205 } 206 } 207 } 208 } 209 210 /** 211 * Log event, tracking the start time, end time and result of a wireless connection attempt. 212 */ 213 class ConnectionEvent { 214 WifiMetricsProto.ConnectionEvent mConnectionEvent; 215 //<TODO> Move these constants into a wifi.proto Enum, and create a new Failure Type field 216 //covering more than just l2 failures. see b/27652362 217 /** 218 * Failure codes, used for the 'level_2_failure_code' Connection event field (covers a lot 219 * more failures than just l2 though, since the proto does not have a place to log 220 * framework failures) 221 */ 222 // Failure is unknown 223 public static final int FAILURE_UNKNOWN = 0; 224 // NONE 225 public static final int FAILURE_NONE = 1; 226 // ASSOCIATION_REJECTION_EVENT 227 public static final int FAILURE_ASSOCIATION_REJECTION = 2; 228 // AUTHENTICATION_FAILURE_EVENT 229 public static final int FAILURE_AUTHENTICATION_FAILURE = 3; 230 // SSID_TEMP_DISABLED (Also Auth failure) 231 public static final int FAILURE_SSID_TEMP_DISABLED = 4; 232 // reconnect() or reassociate() call to WifiNative failed 233 public static final int FAILURE_CONNECT_NETWORK_FAILED = 5; 234 // NETWORK_DISCONNECTION_EVENT 235 public static final int FAILURE_NETWORK_DISCONNECTION = 6; 236 // NEW_CONNECTION_ATTEMPT before previous finished 237 public static final int FAILURE_NEW_CONNECTION_ATTEMPT = 7; 238 // New connection attempt to the same network & bssid 239 public static final int FAILURE_REDUNDANT_CONNECTION_ATTEMPT = 8; 240 // Roam Watchdog timer triggered (Roaming timed out) 241 public static final int FAILURE_ROAM_TIMEOUT = 9; 242 // DHCP failure 243 public static final int FAILURE_DHCP = 10; 244 245 RouterFingerPrint mRouterFingerPrint; 246 private long mRealStartTime; 247 private long mRealEndTime; 248 private String mConfigSsid; 249 private String mConfigBssid; 250 private int mWifiState; 251 private boolean mScreenOn; 252 253 private ConnectionEvent() { 254 mConnectionEvent = new WifiMetricsProto.ConnectionEvent(); 255 mRealEndTime = 0; 256 mRealStartTime = 0; 257 mRouterFingerPrint = new RouterFingerPrint(); 258 mConnectionEvent.routerFingerprint = mRouterFingerPrint.mRouterFingerPrintProto; 259 mConfigSsid = "<NULL>"; 260 mConfigBssid = "<NULL>"; 261 mWifiState = WifiMetricsProto.WifiLog.WIFI_UNKNOWN; 262 mScreenOn = false; 263 } 264 265 public String toString() { 266 StringBuilder sb = new StringBuilder(); 267 sb.append("startTime="); 268 Calendar c = Calendar.getInstance(); 269 synchronized (mLock) { 270 c.setTimeInMillis(mConnectionEvent.startTimeMillis); 271 sb.append(mConnectionEvent.startTimeMillis == 0 ? " <null>" : 272 String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c)); 273 sb.append(", SSID="); 274 sb.append(mConfigSsid); 275 sb.append(", BSSID="); 276 sb.append(mConfigBssid); 277 sb.append(", durationMillis="); 278 sb.append(mConnectionEvent.durationTakenToConnectMillis); 279 sb.append(", roamType="); 280 switch(mConnectionEvent.roamType) { 281 case 1: 282 sb.append("ROAM_NONE"); 283 break; 284 case 2: 285 sb.append("ROAM_DBDC"); 286 break; 287 case 3: 288 sb.append("ROAM_ENTERPRISE"); 289 break; 290 case 4: 291 sb.append("ROAM_USER_SELECTED"); 292 break; 293 case 5: 294 sb.append("ROAM_UNRELATED"); 295 break; 296 default: 297 sb.append("ROAM_UNKNOWN"); 298 } 299 sb.append(", connectionResult="); 300 sb.append(mConnectionEvent.connectionResult); 301 sb.append(", level2FailureCode="); 302 switch(mConnectionEvent.level2FailureCode) { 303 case FAILURE_NONE: 304 sb.append("NONE"); 305 break; 306 case FAILURE_ASSOCIATION_REJECTION: 307 sb.append("ASSOCIATION_REJECTION"); 308 break; 309 case FAILURE_AUTHENTICATION_FAILURE: 310 sb.append("AUTHENTICATION_FAILURE"); 311 break; 312 case FAILURE_SSID_TEMP_DISABLED: 313 sb.append("SSID_TEMP_DISABLED"); 314 break; 315 case FAILURE_CONNECT_NETWORK_FAILED: 316 sb.append("CONNECT_NETWORK_FAILED"); 317 break; 318 case FAILURE_NETWORK_DISCONNECTION: 319 sb.append("NETWORK_DISCONNECTION"); 320 break; 321 case FAILURE_NEW_CONNECTION_ATTEMPT: 322 sb.append("NEW_CONNECTION_ATTEMPT"); 323 break; 324 case FAILURE_REDUNDANT_CONNECTION_ATTEMPT: 325 sb.append("REDUNDANT_CONNECTION_ATTEMPT"); 326 break; 327 case FAILURE_ROAM_TIMEOUT: 328 sb.append("ROAM_TIMEOUT"); 329 break; 330 case FAILURE_DHCP: 331 sb.append("DHCP"); 332 default: 333 sb.append("UNKNOWN"); 334 break; 335 } 336 sb.append(", connectivityLevelFailureCode="); 337 switch(mConnectionEvent.connectivityLevelFailureCode) { 338 case WifiMetricsProto.ConnectionEvent.HLF_NONE: 339 sb.append("NONE"); 340 break; 341 case WifiMetricsProto.ConnectionEvent.HLF_DHCP: 342 sb.append("DHCP"); 343 break; 344 case WifiMetricsProto.ConnectionEvent.HLF_NO_INTERNET: 345 sb.append("NO_INTERNET"); 346 break; 347 case WifiMetricsProto.ConnectionEvent.HLF_UNWANTED: 348 sb.append("UNWANTED"); 349 break; 350 default: 351 sb.append("UNKNOWN"); 352 break; 353 } 354 sb.append(", signalStrength="); 355 sb.append(mConnectionEvent.signalStrength); 356 sb.append(", wifiState="); 357 switch(mWifiState) { 358 case WifiMetricsProto.WifiLog.WIFI_DISABLED: 359 sb.append("WIFI_DISABLED"); 360 break; 361 case WifiMetricsProto.WifiLog.WIFI_DISCONNECTED: 362 sb.append("WIFI_DISCONNECTED"); 363 break; 364 case WifiMetricsProto.WifiLog.WIFI_ASSOCIATED: 365 sb.append("WIFI_ASSOCIATED"); 366 break; 367 default: 368 sb.append("WIFI_UNKNOWN"); 369 break; 370 } 371 sb.append(", screenOn="); 372 sb.append(mScreenOn); 373 sb.append(". mRouterFingerprint: "); 374 sb.append(mRouterFingerPrint.toString()); 375 } 376 return sb.toString(); 377 } 378 } 379 380 public WifiMetrics(Clock clock, Looper looper, WifiAwareMetrics awareMetrics) { 381 mClock = clock; 382 mCurrentConnectionEvent = null; 383 mScreenOn = true; 384 mWifiState = WifiMetricsProto.WifiLog.WIFI_DISABLED; 385 mRecordStartTimeSec = mClock.getElapsedSinceBootMillis() / 1000; 386 mWifiAwareMetrics = awareMetrics; 387 388 mHandler = new Handler(looper) { 389 public void handleMessage(Message msg) { 390 synchronized (mLock) { 391 processMessage(msg); 392 } 393 } 394 }; 395 } 396 397 /** Sets internal WifiConfigManager member */ 398 public void setWifiConfigManager(WifiConfigManager wifiConfigManager) { 399 mWifiConfigManager = wifiConfigManager; 400 } 401 402 /** Sets internal WifiNetworkSelector member */ 403 public void setWifiNetworkSelector(WifiNetworkSelector wifiNetworkSelector) { 404 mWifiNetworkSelector = wifiNetworkSelector; 405 } 406 407 /** Sets internal PasspointManager member */ 408 public void setPasspointManager(PasspointManager passpointManager) { 409 mPasspointManager = passpointManager; 410 } 411 412 /** 413 * Increment total number of attempts to start a pno scan 414 */ 415 public void incrementPnoScanStartAttempCount() { 416 synchronized (mLock) { 417 mPnoScanMetrics.numPnoScanAttempts++; 418 } 419 } 420 421 /** 422 * Increment total number of attempts with pno scan failed 423 */ 424 public void incrementPnoScanFailedCount() { 425 synchronized (mLock) { 426 mPnoScanMetrics.numPnoScanFailed++; 427 } 428 } 429 430 /** 431 * Increment number of pno scans started successfully over offload 432 */ 433 public void incrementPnoScanStartedOverOffloadCount() { 434 synchronized (mLock) { 435 mPnoScanMetrics.numPnoScanStartedOverOffload++; 436 } 437 } 438 439 /** 440 * Increment number of pno scans failed over offload 441 */ 442 public void incrementPnoScanFailedOverOffloadCount() { 443 synchronized (mLock) { 444 mPnoScanMetrics.numPnoScanFailedOverOffload++; 445 } 446 } 447 448 /** 449 * Increment number of times pno scan found a result 450 */ 451 public void incrementPnoFoundNetworkEventCount() { 452 synchronized (mLock) { 453 mPnoScanMetrics.numPnoFoundNetworkEvents++; 454 } 455 } 456 457 // Values used for indexing SystemStateEntries 458 private static final int SCREEN_ON = 1; 459 private static final int SCREEN_OFF = 0; 460 461 /** 462 * Create a new connection event. Call when wifi attempts to make a new network connection 463 * If there is a current 'un-ended' connection event, it will be ended with UNKNOWN connectivity 464 * failure code. 465 * Gathers and sets the RouterFingerPrint data as well 466 * 467 * @param config WifiConfiguration of the config used for the current connection attempt 468 * @param roamType Roam type that caused connection attempt, see WifiMetricsProto.WifiLog.ROAM_X 469 */ 470 public void startConnectionEvent(WifiConfiguration config, String targetBSSID, int roamType) { 471 synchronized (mLock) { 472 // Check if this is overlapping another current connection event 473 if (mCurrentConnectionEvent != null) { 474 //Is this new Connection Event the same as the current one 475 if (mCurrentConnectionEvent.mConfigSsid != null 476 && mCurrentConnectionEvent.mConfigBssid != null 477 && config != null 478 && mCurrentConnectionEvent.mConfigSsid.equals(config.SSID) 479 && (mCurrentConnectionEvent.mConfigBssid.equals("any") 480 || mCurrentConnectionEvent.mConfigBssid.equals(targetBSSID))) { 481 mCurrentConnectionEvent.mConfigBssid = targetBSSID; 482 // End Connection Event due to new connection attempt to the same network 483 endConnectionEvent(ConnectionEvent.FAILURE_REDUNDANT_CONNECTION_ATTEMPT, 484 WifiMetricsProto.ConnectionEvent.HLF_NONE); 485 } else { 486 // End Connection Event due to new connection attempt to different network 487 endConnectionEvent(ConnectionEvent.FAILURE_NEW_CONNECTION_ATTEMPT, 488 WifiMetricsProto.ConnectionEvent.HLF_NONE); 489 } 490 } 491 //If past maximum connection events, start removing the oldest 492 while(mConnectionEventList.size() >= MAX_CONNECTION_EVENTS) { 493 mConnectionEventList.remove(0); 494 } 495 mCurrentConnectionEvent = new ConnectionEvent(); 496 mCurrentConnectionEvent.mConnectionEvent.startTimeMillis = 497 mClock.getWallClockMillis(); 498 mCurrentConnectionEvent.mConfigBssid = targetBSSID; 499 mCurrentConnectionEvent.mConnectionEvent.roamType = roamType; 500 mCurrentConnectionEvent.mRouterFingerPrint.updateFromWifiConfiguration(config); 501 mCurrentConnectionEvent.mConfigBssid = "any"; 502 mCurrentConnectionEvent.mRealStartTime = mClock.getElapsedSinceBootMillis(); 503 mCurrentConnectionEvent.mWifiState = mWifiState; 504 mCurrentConnectionEvent.mScreenOn = mScreenOn; 505 mConnectionEventList.add(mCurrentConnectionEvent); 506 mScanResultRssiTimestampMillis = -1; 507 if (config != null) { 508 ScanResult candidate = config.getNetworkSelectionStatus().getCandidate(); 509 if (candidate != null) { 510 // Cache the RSSI of the candidate, as the connection event level is updated 511 // from other sources (polls, bssid_associations) and delta requires the 512 // scanResult rssi 513 mScanResultRssi = candidate.level; 514 mScanResultRssiTimestampMillis = mClock.getElapsedSinceBootMillis(); 515 } 516 } 517 } 518 } 519 520 /** 521 * set the RoamType of the current ConnectionEvent (if any) 522 */ 523 public void setConnectionEventRoamType(int roamType) { 524 synchronized (mLock) { 525 if (mCurrentConnectionEvent != null) { 526 mCurrentConnectionEvent.mConnectionEvent.roamType = roamType; 527 } 528 } 529 } 530 531 /** 532 * Set AP related metrics from ScanDetail 533 */ 534 public void setConnectionScanDetail(ScanDetail scanDetail) { 535 synchronized (mLock) { 536 if (mCurrentConnectionEvent != null && scanDetail != null) { 537 NetworkDetail networkDetail = scanDetail.getNetworkDetail(); 538 ScanResult scanResult = scanDetail.getScanResult(); 539 //Ensure that we have a networkDetail, and that it corresponds to the currently 540 //tracked connection attempt 541 if (networkDetail != null && scanResult != null 542 && mCurrentConnectionEvent.mConfigSsid != null 543 && mCurrentConnectionEvent.mConfigSsid 544 .equals("\"" + networkDetail.getSSID() + "\"")) { 545 updateMetricsFromNetworkDetail(networkDetail); 546 updateMetricsFromScanResult(scanResult); 547 } 548 } 549 } 550 } 551 552 /** 553 * End a Connection event record. Call when wifi connection attempt succeeds or fails. 554 * If a Connection event has not been started and is active when .end is called, a new one is 555 * created with zero duration. 556 * 557 * @param level2FailureCode Level 2 failure code returned by supplicant 558 * @param connectivityFailureCode WifiMetricsProto.ConnectionEvent.HLF_X 559 */ 560 public void endConnectionEvent(int level2FailureCode, int connectivityFailureCode) { 561 synchronized (mLock) { 562 if (mCurrentConnectionEvent != null) { 563 boolean result = (level2FailureCode == 1) 564 && (connectivityFailureCode == WifiMetricsProto.ConnectionEvent.HLF_NONE); 565 mCurrentConnectionEvent.mConnectionEvent.connectionResult = result ? 1 : 0; 566 mCurrentConnectionEvent.mRealEndTime = mClock.getElapsedSinceBootMillis(); 567 mCurrentConnectionEvent.mConnectionEvent.durationTakenToConnectMillis = (int) 568 (mCurrentConnectionEvent.mRealEndTime 569 - mCurrentConnectionEvent.mRealStartTime); 570 mCurrentConnectionEvent.mConnectionEvent.level2FailureCode = level2FailureCode; 571 mCurrentConnectionEvent.mConnectionEvent.connectivityLevelFailureCode = 572 connectivityFailureCode; 573 // ConnectionEvent already added to ConnectionEvents List. Safe to null current here 574 mCurrentConnectionEvent = null; 575 if (!result) { 576 mScanResultRssiTimestampMillis = -1; 577 } 578 } 579 } 580 } 581 582 /** 583 * Set ConnectionEvent DTIM Interval (if set), and 802.11 Connection mode, from NetworkDetail 584 */ 585 private void updateMetricsFromNetworkDetail(NetworkDetail networkDetail) { 586 int dtimInterval = networkDetail.getDtimInterval(); 587 if (dtimInterval > 0) { 588 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.dtim = 589 dtimInterval; 590 } 591 int connectionWifiMode; 592 switch (networkDetail.getWifiMode()) { 593 case InformationElementUtil.WifiMode.MODE_UNDEFINED: 594 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_UNKNOWN; 595 break; 596 case InformationElementUtil.WifiMode.MODE_11A: 597 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_A; 598 break; 599 case InformationElementUtil.WifiMode.MODE_11B: 600 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_B; 601 break; 602 case InformationElementUtil.WifiMode.MODE_11G: 603 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_G; 604 break; 605 case InformationElementUtil.WifiMode.MODE_11N: 606 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_N; 607 break; 608 case InformationElementUtil.WifiMode.MODE_11AC : 609 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_AC; 610 break; 611 default: 612 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_OTHER; 613 break; 614 } 615 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto 616 .routerTechnology = connectionWifiMode; 617 } 618 619 /** 620 * Set ConnectionEvent RSSI and authentication type from ScanResult 621 */ 622 private void updateMetricsFromScanResult(ScanResult scanResult) { 623 mCurrentConnectionEvent.mConnectionEvent.signalStrength = scanResult.level; 624 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication = 625 WifiMetricsProto.RouterFingerPrint.AUTH_OPEN; 626 mCurrentConnectionEvent.mConfigBssid = scanResult.BSSID; 627 if (scanResult.capabilities != null) { 628 if (ScanResultUtil.isScanResultForWepNetwork(scanResult)) { 629 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication = 630 WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL; 631 } else if (ScanResultUtil.isScanResultForPskNetwork(scanResult)) { 632 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication = 633 WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL; 634 } else if (ScanResultUtil.isScanResultForEapNetwork(scanResult)) { 635 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication = 636 WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE; 637 } 638 } 639 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.channelInfo = 640 scanResult.frequency; 641 } 642 643 void setIsLocationEnabled(boolean enabled) { 644 synchronized (mLock) { 645 mWifiLogProto.isLocationEnabled = enabled; 646 } 647 } 648 649 void setIsScanningAlwaysEnabled(boolean enabled) { 650 synchronized (mLock) { 651 mWifiLogProto.isScanningAlwaysEnabled = enabled; 652 } 653 } 654 655 /** 656 * Increment Non Empty Scan Results count 657 */ 658 public void incrementNonEmptyScanResultCount() { 659 if (DBG) Log.v(TAG, "incrementNonEmptyScanResultCount"); 660 synchronized (mLock) { 661 mWifiLogProto.numNonEmptyScanResults++; 662 } 663 } 664 665 /** 666 * Increment Empty Scan Results count 667 */ 668 public void incrementEmptyScanResultCount() { 669 if (DBG) Log.v(TAG, "incrementEmptyScanResultCount"); 670 synchronized (mLock) { 671 mWifiLogProto.numEmptyScanResults++; 672 } 673 } 674 675 /** 676 * Increment background scan count 677 */ 678 public void incrementBackgroundScanCount() { 679 if (DBG) Log.v(TAG, "incrementBackgroundScanCount"); 680 synchronized (mLock) { 681 mWifiLogProto.numBackgroundScans++; 682 } 683 } 684 685 /** 686 * Get Background scan count 687 */ 688 public int getBackgroundScanCount() { 689 synchronized (mLock) { 690 return mWifiLogProto.numBackgroundScans; 691 } 692 } 693 694 /** 695 * Increment oneshot scan count, and the associated WifiSystemScanStateCount entry 696 */ 697 public void incrementOneshotScanCount() { 698 synchronized (mLock) { 699 mWifiLogProto.numOneshotScans++; 700 } 701 incrementWifiSystemScanStateCount(mWifiState, mScreenOn); 702 } 703 704 /** 705 * Get oneshot scan count 706 */ 707 public int getOneshotScanCount() { 708 synchronized (mLock) { 709 return mWifiLogProto.numOneshotScans; 710 } 711 } 712 713 private String returnCodeToString(int scanReturnCode) { 714 switch(scanReturnCode){ 715 case WifiMetricsProto.WifiLog.SCAN_UNKNOWN: 716 return "SCAN_UNKNOWN"; 717 case WifiMetricsProto.WifiLog.SCAN_SUCCESS: 718 return "SCAN_SUCCESS"; 719 case WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED: 720 return "SCAN_FAILURE_INTERRUPTED"; 721 case WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION: 722 return "SCAN_FAILURE_INVALID_CONFIGURATION"; 723 case WifiMetricsProto.WifiLog.FAILURE_WIFI_DISABLED: 724 return "FAILURE_WIFI_DISABLED"; 725 default: 726 return "<UNKNOWN>"; 727 } 728 } 729 730 /** 731 * Increment count of scan return code occurrence 732 * 733 * @param scanReturnCode Return code from scan attempt WifiMetricsProto.WifiLog.SCAN_X 734 */ 735 public void incrementScanReturnEntry(int scanReturnCode, int countToAdd) { 736 synchronized (mLock) { 737 if (DBG) Log.v(TAG, "incrementScanReturnEntry " + returnCodeToString(scanReturnCode)); 738 int entry = mScanReturnEntries.get(scanReturnCode); 739 entry += countToAdd; 740 mScanReturnEntries.put(scanReturnCode, entry); 741 } 742 } 743 /** 744 * Get the count of this scanReturnCode 745 * @param scanReturnCode that we are getting the count for 746 */ 747 public int getScanReturnEntry(int scanReturnCode) { 748 synchronized (mLock) { 749 return mScanReturnEntries.get(scanReturnCode); 750 } 751 } 752 753 private String wifiSystemStateToString(int state) { 754 switch(state){ 755 case WifiMetricsProto.WifiLog.WIFI_UNKNOWN: 756 return "WIFI_UNKNOWN"; 757 case WifiMetricsProto.WifiLog.WIFI_DISABLED: 758 return "WIFI_DISABLED"; 759 case WifiMetricsProto.WifiLog.WIFI_DISCONNECTED: 760 return "WIFI_DISCONNECTED"; 761 case WifiMetricsProto.WifiLog.WIFI_ASSOCIATED: 762 return "WIFI_ASSOCIATED"; 763 default: 764 return "default"; 765 } 766 } 767 768 /** 769 * Increments the count of scans initiated by each wifi state, accounts for screenOn/Off 770 * 771 * @param state State of the system when scan was initiated, see WifiMetricsProto.WifiLog.WIFI_X 772 * @param screenOn Is the screen on 773 */ 774 public void incrementWifiSystemScanStateCount(int state, boolean screenOn) { 775 synchronized (mLock) { 776 if (DBG) { 777 Log.v(TAG, "incrementWifiSystemScanStateCount " + wifiSystemStateToString(state) 778 + " " + screenOn); 779 } 780 int index = (state * 2) + (screenOn ? SCREEN_ON : SCREEN_OFF); 781 int entry = mWifiSystemStateEntries.get(index); 782 entry++; 783 mWifiSystemStateEntries.put(index, entry); 784 } 785 } 786 787 /** 788 * Get the count of this system State Entry 789 */ 790 public int getSystemStateCount(int state, boolean screenOn) { 791 synchronized (mLock) { 792 int index = state * 2 + (screenOn ? SCREEN_ON : SCREEN_OFF); 793 return mWifiSystemStateEntries.get(index); 794 } 795 } 796 797 /** 798 * Increment number of times the Watchdog of Last Resort triggered, resetting the wifi stack 799 */ 800 public void incrementNumLastResortWatchdogTriggers() { 801 synchronized (mLock) { 802 mWifiLogProto.numLastResortWatchdogTriggers++; 803 } 804 } 805 /** 806 * @param count number of networks over bad association threshold when watchdog triggered 807 */ 808 public void addCountToNumLastResortWatchdogBadAssociationNetworksTotal(int count) { 809 synchronized (mLock) { 810 mWifiLogProto.numLastResortWatchdogBadAssociationNetworksTotal += count; 811 } 812 } 813 /** 814 * @param count number of networks over bad authentication threshold when watchdog triggered 815 */ 816 public void addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal(int count) { 817 synchronized (mLock) { 818 mWifiLogProto.numLastResortWatchdogBadAuthenticationNetworksTotal += count; 819 } 820 } 821 /** 822 * @param count number of networks over bad dhcp threshold when watchdog triggered 823 */ 824 public void addCountToNumLastResortWatchdogBadDhcpNetworksTotal(int count) { 825 synchronized (mLock) { 826 mWifiLogProto.numLastResortWatchdogBadDhcpNetworksTotal += count; 827 } 828 } 829 /** 830 * @param count number of networks over bad other threshold when watchdog triggered 831 */ 832 public void addCountToNumLastResortWatchdogBadOtherNetworksTotal(int count) { 833 synchronized (mLock) { 834 mWifiLogProto.numLastResortWatchdogBadOtherNetworksTotal += count; 835 } 836 } 837 /** 838 * @param count number of networks seen when watchdog triggered 839 */ 840 public void addCountToNumLastResortWatchdogAvailableNetworksTotal(int count) { 841 synchronized (mLock) { 842 mWifiLogProto.numLastResortWatchdogAvailableNetworksTotal += count; 843 } 844 } 845 /** 846 * Increment count of triggers with atleast one bad association network 847 */ 848 public void incrementNumLastResortWatchdogTriggersWithBadAssociation() { 849 synchronized (mLock) { 850 mWifiLogProto.numLastResortWatchdogTriggersWithBadAssociation++; 851 } 852 } 853 /** 854 * Increment count of triggers with atleast one bad authentication network 855 */ 856 public void incrementNumLastResortWatchdogTriggersWithBadAuthentication() { 857 synchronized (mLock) { 858 mWifiLogProto.numLastResortWatchdogTriggersWithBadAuthentication++; 859 } 860 } 861 /** 862 * Increment count of triggers with atleast one bad dhcp network 863 */ 864 public void incrementNumLastResortWatchdogTriggersWithBadDhcp() { 865 synchronized (mLock) { 866 mWifiLogProto.numLastResortWatchdogTriggersWithBadDhcp++; 867 } 868 } 869 /** 870 * Increment count of triggers with atleast one bad other network 871 */ 872 public void incrementNumLastResortWatchdogTriggersWithBadOther() { 873 synchronized (mLock) { 874 mWifiLogProto.numLastResortWatchdogTriggersWithBadOther++; 875 } 876 } 877 878 /** 879 * Increment number of times connectivity watchdog confirmed pno is working 880 */ 881 public void incrementNumConnectivityWatchdogPnoGood() { 882 synchronized (mLock) { 883 mWifiLogProto.numConnectivityWatchdogPnoGood++; 884 } 885 } 886 /** 887 * Increment number of times connectivity watchdog found pno not working 888 */ 889 public void incrementNumConnectivityWatchdogPnoBad() { 890 synchronized (mLock) { 891 mWifiLogProto.numConnectivityWatchdogPnoBad++; 892 } 893 } 894 /** 895 * Increment number of times connectivity watchdog confirmed background scan is working 896 */ 897 public void incrementNumConnectivityWatchdogBackgroundGood() { 898 synchronized (mLock) { 899 mWifiLogProto.numConnectivityWatchdogBackgroundGood++; 900 } 901 } 902 /** 903 * Increment number of times connectivity watchdog found background scan not working 904 */ 905 public void incrementNumConnectivityWatchdogBackgroundBad() { 906 synchronized (mLock) { 907 mWifiLogProto.numConnectivityWatchdogBackgroundBad++; 908 } 909 } 910 911 /** 912 * Increment various poll related metrics, and cache performance data for StaEvent logging 913 */ 914 public void handlePollResult(WifiInfo wifiInfo) { 915 mLastPollRssi = wifiInfo.getRssi(); 916 mLastPollLinkSpeed = wifiInfo.getLinkSpeed(); 917 mLastPollFreq = wifiInfo.getFrequency(); 918 incrementRssiPollRssiCount(mLastPollRssi); 919 } 920 921 /** 922 * Increment occurence count of RSSI level from RSSI poll. 923 * Ignores rssi values outside the bounds of [MIN_RSSI_POLL, MAX_RSSI_POLL] 924 */ 925 public void incrementRssiPollRssiCount(int rssi) { 926 if (!(rssi >= MIN_RSSI_POLL && rssi <= MAX_RSSI_POLL)) { 927 return; 928 } 929 synchronized (mLock) { 930 int count = mRssiPollCounts.get(rssi); 931 mRssiPollCounts.put(rssi, count + 1); 932 maybeIncrementRssiDeltaCount(rssi - mScanResultRssi); 933 } 934 } 935 936 /** 937 * Increment occurence count of difference between scan result RSSI and the first RSSI poll. 938 * Ignores rssi values outside the bounds of [MIN_RSSI_DELTA, MAX_RSSI_DELTA] 939 * mLock must be held when calling this method. 940 */ 941 private void maybeIncrementRssiDeltaCount(int rssi) { 942 // Check if this RSSI poll is close enough to a scan result RSSI to log a delta value 943 if (mScanResultRssiTimestampMillis >= 0) { 944 long timeDelta = mClock.getElapsedSinceBootMillis() - mScanResultRssiTimestampMillis; 945 if (timeDelta <= TIMEOUT_RSSI_DELTA_MILLIS) { 946 if (rssi >= MIN_RSSI_DELTA && rssi <= MAX_RSSI_DELTA) { 947 int count = mRssiDeltaCounts.get(rssi); 948 mRssiDeltaCounts.put(rssi, count + 1); 949 } 950 } 951 mScanResultRssiTimestampMillis = -1; 952 } 953 } 954 955 /** 956 * Increment count of Watchdog successes. 957 */ 958 public void incrementNumLastResortWatchdogSuccesses() { 959 synchronized (mLock) { 960 mWifiLogProto.numLastResortWatchdogSuccesses++; 961 } 962 } 963 964 /** 965 * Increments the count of alerts by alert reason. 966 * 967 * @param reason The cause of the alert. The reason values are driver-specific. 968 */ 969 public void incrementAlertReasonCount(int reason) { 970 if (reason > WifiLoggerHal.WIFI_ALERT_REASON_MAX 971 || reason < WifiLoggerHal.WIFI_ALERT_REASON_MIN) { 972 reason = WifiLoggerHal.WIFI_ALERT_REASON_RESERVED; 973 } 974 synchronized (mLock) { 975 int alertCount = mWifiAlertReasonCounts.get(reason); 976 mWifiAlertReasonCounts.put(reason, alertCount + 1); 977 } 978 } 979 980 /** 981 * Counts all the different types of networks seen in a set of scan results 982 */ 983 public void countScanResults(List<ScanDetail> scanDetails) { 984 if (scanDetails == null) { 985 return; 986 } 987 int totalResults = 0; 988 int openNetworks = 0; 989 int personalNetworks = 0; 990 int enterpriseNetworks = 0; 991 int hiddenNetworks = 0; 992 int hotspot2r1Networks = 0; 993 int hotspot2r2Networks = 0; 994 for (ScanDetail scanDetail : scanDetails) { 995 NetworkDetail networkDetail = scanDetail.getNetworkDetail(); 996 ScanResult scanResult = scanDetail.getScanResult(); 997 totalResults++; 998 if (networkDetail != null) { 999 if (networkDetail.isHiddenBeaconFrame()) { 1000 hiddenNetworks++; 1001 } 1002 if (networkDetail.getHSRelease() != null) { 1003 if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R1) { 1004 hotspot2r1Networks++; 1005 } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R2) { 1006 hotspot2r2Networks++; 1007 } 1008 } 1009 } 1010 if (scanResult != null && scanResult.capabilities != null) { 1011 if (ScanResultUtil.isScanResultForEapNetwork(scanResult)) { 1012 enterpriseNetworks++; 1013 } else if (ScanResultUtil.isScanResultForPskNetwork(scanResult) 1014 || ScanResultUtil.isScanResultForWepNetwork(scanResult)) { 1015 personalNetworks++; 1016 } else { 1017 openNetworks++; 1018 } 1019 } 1020 } 1021 synchronized (mLock) { 1022 mWifiLogProto.numTotalScanResults += totalResults; 1023 mWifiLogProto.numOpenNetworkScanResults += openNetworks; 1024 mWifiLogProto.numPersonalNetworkScanResults += personalNetworks; 1025 mWifiLogProto.numEnterpriseNetworkScanResults += enterpriseNetworks; 1026 mWifiLogProto.numHiddenNetworkScanResults += hiddenNetworks; 1027 mWifiLogProto.numHotspot2R1NetworkScanResults += hotspot2r1Networks; 1028 mWifiLogProto.numHotspot2R2NetworkScanResults += hotspot2r2Networks; 1029 mWifiLogProto.numScans++; 1030 } 1031 } 1032 1033 /** 1034 * Increments occurence of a particular wifi score calculated 1035 * in WifiScoreReport by current connected network. Scores are bounded 1036 * within [MIN_WIFI_SCORE, MAX_WIFI_SCORE] to limit size of SparseArray 1037 */ 1038 public void incrementWifiScoreCount(int score) { 1039 if (score < MIN_WIFI_SCORE || score > MAX_WIFI_SCORE) { 1040 return; 1041 } 1042 synchronized (mLock) { 1043 int count = mWifiScoreCounts.get(score); 1044 mWifiScoreCounts.put(score, count + 1); 1045 } 1046 } 1047 1048 /** 1049 * Increments occurence of the results from attempting to start SoftAp. 1050 * Maps the |result| and WifiManager |failureCode| constant to proto defined SoftApStartResult 1051 * codes. 1052 */ 1053 public void incrementSoftApStartResult(boolean result, int failureCode) { 1054 synchronized (mLock) { 1055 if (result) { 1056 int count = mSoftApManagerReturnCodeCounts.get( 1057 WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY); 1058 mSoftApManagerReturnCodeCounts.put( 1059 WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY, 1060 count + 1); 1061 return; 1062 } 1063 1064 // now increment failure modes - if not explicitly handled, dump into the general 1065 // error bucket. 1066 if (failureCode == WifiManager.SAP_START_FAILURE_NO_CHANNEL) { 1067 int count = mSoftApManagerReturnCodeCounts.get( 1068 WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL); 1069 mSoftApManagerReturnCodeCounts.put( 1070 WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL, 1071 count + 1); 1072 } else { 1073 // failure mode not tracked at this time... count as a general error for now. 1074 int count = mSoftApManagerReturnCodeCounts.get( 1075 WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR); 1076 mSoftApManagerReturnCodeCounts.put( 1077 WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR, 1078 count + 1); 1079 } 1080 } 1081 } 1082 1083 /** 1084 * Increment number of times the HAL crashed. 1085 */ 1086 public void incrementNumHalCrashes() { 1087 synchronized (mLock) { 1088 mWifiLogProto.numHalCrashes++; 1089 } 1090 } 1091 1092 /** 1093 * Increment number of times the Wificond crashed. 1094 */ 1095 public void incrementNumWificondCrashes() { 1096 synchronized (mLock) { 1097 mWifiLogProto.numWificondCrashes++; 1098 } 1099 } 1100 1101 /** 1102 * Increment number of times the wifi on failed due to an error in HAL. 1103 */ 1104 public void incrementNumWifiOnFailureDueToHal() { 1105 synchronized (mLock) { 1106 mWifiLogProto.numWifiOnFailureDueToHal++; 1107 } 1108 } 1109 1110 /** 1111 * Increment number of times the wifi on failed due to an error in wificond. 1112 */ 1113 public void incrementNumWifiOnFailureDueToWificond() { 1114 synchronized (mLock) { 1115 mWifiLogProto.numWifiOnFailureDueToWificond++; 1116 } 1117 } 1118 1119 /** 1120 * Increment number of times Passpoint provider being installed. 1121 */ 1122 public void incrementNumPasspointProviderInstallation() { 1123 synchronized (mLock) { 1124 mWifiLogProto.numPasspointProviderInstallation++; 1125 } 1126 } 1127 1128 /** 1129 * Increment number of times Passpoint provider is installed successfully. 1130 */ 1131 public void incrementNumPasspointProviderInstallSuccess() { 1132 synchronized (mLock) { 1133 mWifiLogProto.numPasspointProviderInstallSuccess++; 1134 } 1135 } 1136 1137 /** 1138 * Increment number of times Passpoint provider being uninstalled. 1139 */ 1140 public void incrementNumPasspointProviderUninstallation() { 1141 synchronized (mLock) { 1142 mWifiLogProto.numPasspointProviderUninstallation++; 1143 } 1144 } 1145 1146 /** 1147 * Increment number of times Passpoint provider is uninstalled successfully. 1148 */ 1149 public void incrementNumPasspointProviderUninstallSuccess() { 1150 synchronized (mLock) { 1151 mWifiLogProto.numPasspointProviderUninstallSuccess++; 1152 } 1153 } 1154 1155 /** 1156 * Increment N-Way network selection decision histograms: 1157 * Counts the size of various sets of scanDetails within a scan, and increment the occurrence 1158 * of that size for the associated histogram. There are ten histograms generated for each 1159 * combination of: {SSID, BSSID} *{Total, Saved, Open, Saved_or_Open, Passpoint} 1160 * Only performs this count if isFullBand is true, otherwise, increments the partial scan count 1161 */ 1162 public void incrementAvailableNetworksHistograms(List<ScanDetail> scanDetails, 1163 boolean isFullBand) { 1164 synchronized (mLock) { 1165 if (mWifiConfigManager == null || mWifiNetworkSelector == null 1166 || mPasspointManager == null) { 1167 return; 1168 } 1169 if (!isFullBand) { 1170 mWifiLogProto.partialAllSingleScanListenerResults++; 1171 return; 1172 } 1173 Set<ScanResultMatchInfo> ssids = new HashSet<ScanResultMatchInfo>(); 1174 int bssids = 0; 1175 Set<ScanResultMatchInfo> openSsids = new HashSet<ScanResultMatchInfo>(); 1176 int openBssids = 0; 1177 Set<ScanResultMatchInfo> savedSsids = new HashSet<ScanResultMatchInfo>(); 1178 int savedBssids = 0; 1179 // openOrSavedSsids calculated from union of savedSsids & openSsids 1180 int openOrSavedBssids = 0; 1181 Set<PasspointProvider> savedPasspointProviderProfiles = 1182 new HashSet<PasspointProvider>(); 1183 int savedPasspointProviderBssids = 0; 1184 for (ScanDetail scanDetail : scanDetails) { 1185 NetworkDetail networkDetail = scanDetail.getNetworkDetail(); 1186 ScanResult scanResult = scanDetail.getScanResult(); 1187 if (mWifiNetworkSelector.isSignalTooWeak(scanResult)) { 1188 continue; 1189 } 1190 ScanResultMatchInfo matchInfo = ScanResultMatchInfo.fromScanResult(scanResult); 1191 Pair<PasspointProvider, PasspointMatch> providerMatch = null; 1192 PasspointProvider passpointProvider = null; 1193 if (networkDetail.isInterworking()) { 1194 providerMatch = 1195 mPasspointManager.matchProvider(scanResult); 1196 passpointProvider = providerMatch != null ? providerMatch.first : null; 1197 } 1198 ssids.add(matchInfo); 1199 bssids++; 1200 boolean isOpen = matchInfo.networkType == ScanResultMatchInfo.NETWORK_TYPE_OPEN; 1201 WifiConfiguration config = 1202 mWifiConfigManager.getConfiguredNetworkForScanDetail(scanDetail); 1203 boolean isSaved = (config != null) && !config.isEphemeral() 1204 && !config.isPasspoint(); 1205 boolean isSavedPasspoint = passpointProvider != null; 1206 if (isOpen) { 1207 openSsids.add(matchInfo); 1208 openBssids++; 1209 } 1210 if (isSaved) { 1211 savedSsids.add(matchInfo); 1212 savedBssids++; 1213 } 1214 if (isOpen || isSaved) { 1215 openOrSavedBssids++; 1216 // Calculate openOrSavedSsids union later 1217 } 1218 if (isSavedPasspoint) { 1219 savedPasspointProviderProfiles.add(passpointProvider); 1220 savedPasspointProviderBssids++; 1221 } 1222 } 1223 mWifiLogProto.fullBandAllSingleScanListenerResults++; 1224 incrementTotalScanSsids(mTotalSsidsInScanHistogram, ssids.size()); 1225 incrementTotalScanResults(mTotalBssidsInScanHistogram, bssids); 1226 incrementSsid(mAvailableOpenSsidsInScanHistogram, openSsids.size()); 1227 incrementBssid(mAvailableOpenBssidsInScanHistogram, openBssids); 1228 incrementSsid(mAvailableSavedSsidsInScanHistogram, savedSsids.size()); 1229 incrementBssid(mAvailableSavedBssidsInScanHistogram, savedBssids); 1230 openSsids.addAll(savedSsids); // openSsids = Union(openSsids, savedSsids) 1231 incrementSsid(mAvailableOpenOrSavedSsidsInScanHistogram, openSsids.size()); 1232 incrementBssid(mAvailableOpenOrSavedBssidsInScanHistogram, openOrSavedBssids); 1233 incrementSsid(mAvailableSavedPasspointProviderProfilesInScanHistogram, 1234 savedPasspointProviderProfiles.size()); 1235 incrementBssid(mAvailableSavedPasspointProviderBssidsInScanHistogram, 1236 savedPasspointProviderBssids); 1237 } 1238 } 1239 1240 public static final String PROTO_DUMP_ARG = "wifiMetricsProto"; 1241 public static final String CLEAN_DUMP_ARG = "clean"; 1242 1243 /** 1244 * Dump all WifiMetrics. Collects some metrics from ConfigStore, Settings and WifiManager 1245 * at this time. 1246 * 1247 * @param fd unused 1248 * @param pw PrintWriter for writing dump to 1249 * @param args unused 1250 */ 1251 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1252 synchronized (mLock) { 1253 if (args != null && args.length > 0 && PROTO_DUMP_ARG.equals(args[0])) { 1254 // Dump serialized WifiLog proto 1255 consolidateProto(true); 1256 for (ConnectionEvent event : mConnectionEventList) { 1257 if (mCurrentConnectionEvent != event) { 1258 //indicate that automatic bug report has been taken for all valid 1259 //connection events 1260 event.mConnectionEvent.automaticBugReportTaken = true; 1261 } 1262 } 1263 byte[] wifiMetricsProto = WifiMetricsProto.WifiLog.toByteArray(mWifiLogProto); 1264 String metricsProtoDump = Base64.encodeToString(wifiMetricsProto, Base64.DEFAULT); 1265 if (args.length > 1 && CLEAN_DUMP_ARG.equals(args[1])) { 1266 // Output metrics proto bytes (base64) and nothing else 1267 pw.print(metricsProtoDump); 1268 } else { 1269 // Tag the start and end of the metrics proto bytes 1270 pw.println("WifiMetrics:"); 1271 pw.println(metricsProtoDump); 1272 pw.println("EndWifiMetrics"); 1273 } 1274 clear(); 1275 } else { 1276 pw.println("WifiMetrics:"); 1277 pw.println("mConnectionEvents:"); 1278 for (ConnectionEvent event : mConnectionEventList) { 1279 String eventLine = event.toString(); 1280 if (event == mCurrentConnectionEvent) { 1281 eventLine += "CURRENTLY OPEN EVENT"; 1282 } 1283 pw.println(eventLine); 1284 } 1285 pw.println("mWifiLogProto.numSavedNetworks=" + mWifiLogProto.numSavedNetworks); 1286 pw.println("mWifiLogProto.numOpenNetworks=" + mWifiLogProto.numOpenNetworks); 1287 pw.println("mWifiLogProto.numPersonalNetworks=" 1288 + mWifiLogProto.numPersonalNetworks); 1289 pw.println("mWifiLogProto.numEnterpriseNetworks=" 1290 + mWifiLogProto.numEnterpriseNetworks); 1291 pw.println("mWifiLogProto.numHiddenNetworks=" + mWifiLogProto.numHiddenNetworks); 1292 pw.println("mWifiLogProto.numPasspointNetworks=" 1293 + mWifiLogProto.numPasspointNetworks); 1294 pw.println("mWifiLogProto.isLocationEnabled=" + mWifiLogProto.isLocationEnabled); 1295 pw.println("mWifiLogProto.isScanningAlwaysEnabled=" 1296 + mWifiLogProto.isScanningAlwaysEnabled); 1297 pw.println("mWifiLogProto.numNetworksAddedByUser=" 1298 + mWifiLogProto.numNetworksAddedByUser); 1299 pw.println("mWifiLogProto.numNetworksAddedByApps=" 1300 + mWifiLogProto.numNetworksAddedByApps); 1301 pw.println("mWifiLogProto.numNonEmptyScanResults=" 1302 + mWifiLogProto.numNonEmptyScanResults); 1303 pw.println("mWifiLogProto.numEmptyScanResults=" 1304 + mWifiLogProto.numEmptyScanResults); 1305 pw.println("mWifiLogProto.numOneshotScans=" 1306 + mWifiLogProto.numOneshotScans); 1307 pw.println("mWifiLogProto.numBackgroundScans=" 1308 + mWifiLogProto.numBackgroundScans); 1309 1310 pw.println("mScanReturnEntries:"); 1311 pw.println(" SCAN_UNKNOWN: " + getScanReturnEntry( 1312 WifiMetricsProto.WifiLog.SCAN_UNKNOWN)); 1313 pw.println(" SCAN_SUCCESS: " + getScanReturnEntry( 1314 WifiMetricsProto.WifiLog.SCAN_SUCCESS)); 1315 pw.println(" SCAN_FAILURE_INTERRUPTED: " + getScanReturnEntry( 1316 WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED)); 1317 pw.println(" SCAN_FAILURE_INVALID_CONFIGURATION: " + getScanReturnEntry( 1318 WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION)); 1319 pw.println(" FAILURE_WIFI_DISABLED: " + getScanReturnEntry( 1320 WifiMetricsProto.WifiLog.FAILURE_WIFI_DISABLED)); 1321 1322 pw.println("mSystemStateEntries: <state><screenOn> : <scansInitiated>"); 1323 pw.println(" WIFI_UNKNOWN ON: " 1324 + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, true)); 1325 pw.println(" WIFI_DISABLED ON: " 1326 + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISABLED, true)); 1327 pw.println(" WIFI_DISCONNECTED ON: " 1328 + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED, true)); 1329 pw.println(" WIFI_ASSOCIATED ON: " 1330 + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, true)); 1331 pw.println(" WIFI_UNKNOWN OFF: " 1332 + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, false)); 1333 pw.println(" WIFI_DISABLED OFF: " 1334 + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISABLED, false)); 1335 pw.println(" WIFI_DISCONNECTED OFF: " 1336 + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED, false)); 1337 pw.println(" WIFI_ASSOCIATED OFF: " 1338 + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, false)); 1339 pw.println("mWifiLogProto.numConnectivityWatchdogPnoGood=" 1340 + mWifiLogProto.numConnectivityWatchdogPnoGood); 1341 pw.println("mWifiLogProto.numConnectivityWatchdogPnoBad=" 1342 + mWifiLogProto.numConnectivityWatchdogPnoBad); 1343 pw.println("mWifiLogProto.numConnectivityWatchdogBackgroundGood=" 1344 + mWifiLogProto.numConnectivityWatchdogBackgroundGood); 1345 pw.println("mWifiLogProto.numConnectivityWatchdogBackgroundBad=" 1346 + mWifiLogProto.numConnectivityWatchdogBackgroundBad); 1347 pw.println("mWifiLogProto.numLastResortWatchdogTriggers=" 1348 + mWifiLogProto.numLastResortWatchdogTriggers); 1349 pw.println("mWifiLogProto.numLastResortWatchdogBadAssociationNetworksTotal=" 1350 + mWifiLogProto.numLastResortWatchdogBadAssociationNetworksTotal); 1351 pw.println("mWifiLogProto.numLastResortWatchdogBadAuthenticationNetworksTotal=" 1352 + mWifiLogProto.numLastResortWatchdogBadAuthenticationNetworksTotal); 1353 pw.println("mWifiLogProto.numLastResortWatchdogBadDhcpNetworksTotal=" 1354 + mWifiLogProto.numLastResortWatchdogBadDhcpNetworksTotal); 1355 pw.println("mWifiLogProto.numLastResortWatchdogBadOtherNetworksTotal=" 1356 + mWifiLogProto.numLastResortWatchdogBadOtherNetworksTotal); 1357 pw.println("mWifiLogProto.numLastResortWatchdogAvailableNetworksTotal=" 1358 + mWifiLogProto.numLastResortWatchdogAvailableNetworksTotal); 1359 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadAssociation=" 1360 + mWifiLogProto.numLastResortWatchdogTriggersWithBadAssociation); 1361 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadAuthentication=" 1362 + mWifiLogProto.numLastResortWatchdogTriggersWithBadAuthentication); 1363 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadDhcp=" 1364 + mWifiLogProto.numLastResortWatchdogTriggersWithBadDhcp); 1365 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadOther=" 1366 + mWifiLogProto.numLastResortWatchdogTriggersWithBadOther); 1367 pw.println("mWifiLogProto.numLastResortWatchdogSuccesses=" 1368 + mWifiLogProto.numLastResortWatchdogSuccesses); 1369 pw.println("mWifiLogProto.recordDurationSec=" 1370 + ((mClock.getElapsedSinceBootMillis() / 1000) - mRecordStartTimeSec)); 1371 pw.println("mWifiLogProto.rssiPollRssiCount: Printing counts for [" + MIN_RSSI_POLL 1372 + ", " + MAX_RSSI_POLL + "]"); 1373 StringBuilder sb = new StringBuilder(); 1374 for (int i = MIN_RSSI_POLL; i <= MAX_RSSI_POLL; i++) { 1375 sb.append(mRssiPollCounts.get(i) + " "); 1376 } 1377 pw.println(" " + sb.toString()); 1378 pw.println("mWifiLogProto.rssiPollDeltaCount: Printing counts for [" 1379 + MIN_RSSI_DELTA + ", " + MAX_RSSI_DELTA + "]"); 1380 sb.setLength(0); 1381 for (int i = MIN_RSSI_DELTA; i <= MAX_RSSI_DELTA; i++) { 1382 sb.append(mRssiDeltaCounts.get(i) + " "); 1383 } 1384 pw.println(" " + sb.toString()); 1385 pw.print("mWifiLogProto.alertReasonCounts="); 1386 sb.setLength(0); 1387 for (int i = WifiLoggerHal.WIFI_ALERT_REASON_MIN; 1388 i <= WifiLoggerHal.WIFI_ALERT_REASON_MAX; i++) { 1389 int count = mWifiAlertReasonCounts.get(i); 1390 if (count > 0) { 1391 sb.append("(" + i + "," + count + "),"); 1392 } 1393 } 1394 if (sb.length() > 1) { 1395 sb.setLength(sb.length() - 1); // strip trailing comma 1396 pw.println(sb.toString()); 1397 } else { 1398 pw.println("()"); 1399 } 1400 pw.println("mWifiLogProto.numTotalScanResults=" 1401 + mWifiLogProto.numTotalScanResults); 1402 pw.println("mWifiLogProto.numOpenNetworkScanResults=" 1403 + mWifiLogProto.numOpenNetworkScanResults); 1404 pw.println("mWifiLogProto.numPersonalNetworkScanResults=" 1405 + mWifiLogProto.numPersonalNetworkScanResults); 1406 pw.println("mWifiLogProto.numEnterpriseNetworkScanResults=" 1407 + mWifiLogProto.numEnterpriseNetworkScanResults); 1408 pw.println("mWifiLogProto.numHiddenNetworkScanResults=" 1409 + mWifiLogProto.numHiddenNetworkScanResults); 1410 pw.println("mWifiLogProto.numHotspot2R1NetworkScanResults=" 1411 + mWifiLogProto.numHotspot2R1NetworkScanResults); 1412 pw.println("mWifiLogProto.numHotspot2R2NetworkScanResults=" 1413 + mWifiLogProto.numHotspot2R2NetworkScanResults); 1414 pw.println("mWifiLogProto.numScans=" + mWifiLogProto.numScans); 1415 pw.println("mWifiLogProto.WifiScoreCount: [" + MIN_WIFI_SCORE + ", " 1416 + MAX_WIFI_SCORE + "]"); 1417 for (int i = 0; i <= MAX_WIFI_SCORE; i++) { 1418 pw.print(mWifiScoreCounts.get(i) + " "); 1419 } 1420 pw.println(); // add a line after wifi scores 1421 pw.println("mWifiLogProto.SoftApManagerReturnCodeCounts:"); 1422 pw.println(" SUCCESS: " + mSoftApManagerReturnCodeCounts.get( 1423 WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY)); 1424 pw.println(" FAILED_GENERAL_ERROR: " + mSoftApManagerReturnCodeCounts.get( 1425 WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR)); 1426 pw.println(" FAILED_NO_CHANNEL: " + mSoftApManagerReturnCodeCounts.get( 1427 WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL)); 1428 pw.print("\n"); 1429 pw.println("mWifiLogProto.numHalCrashes=" 1430 + mWifiLogProto.numHalCrashes); 1431 pw.println("mWifiLogProto.numWificondCrashes=" 1432 + mWifiLogProto.numWificondCrashes); 1433 pw.println("mWifiLogProto.numWifiOnFailureDueToHal=" 1434 + mWifiLogProto.numWifiOnFailureDueToHal); 1435 pw.println("mWifiLogProto.numWifiOnFailureDueToWificond=" 1436 + mWifiLogProto.numWifiOnFailureDueToWificond); 1437 pw.println("StaEventList:"); 1438 for (StaEvent event : mStaEventList) { 1439 pw.println(staEventToString(event)); 1440 } 1441 1442 pw.println("mWifiLogProto.numPasspointProviders=" 1443 + mWifiLogProto.numPasspointProviders); 1444 pw.println("mWifiLogProto.numPasspointProviderInstallation=" 1445 + mWifiLogProto.numPasspointProviderInstallation); 1446 pw.println("mWifiLogProto.numPasspointProviderInstallSuccess=" 1447 + mWifiLogProto.numPasspointProviderInstallSuccess); 1448 pw.println("mWifiLogProto.numPasspointProviderUninstallation=" 1449 + mWifiLogProto.numPasspointProviderUninstallation); 1450 pw.println("mWifiLogProto.numPasspointProviderUninstallSuccess=" 1451 + mWifiLogProto.numPasspointProviderUninstallSuccess); 1452 pw.println("mWifiLogProto.numPasspointProvidersSuccessfullyConnected=" 1453 + mWifiLogProto.numPasspointProvidersSuccessfullyConnected); 1454 pw.println("mTotalSsidsInScanHistogram:" 1455 + mTotalSsidsInScanHistogram.toString()); 1456 pw.println("mTotalBssidsInScanHistogram:" 1457 + mTotalBssidsInScanHistogram.toString()); 1458 pw.println("mAvailableOpenSsidsInScanHistogram:" 1459 + mAvailableOpenSsidsInScanHistogram.toString()); 1460 pw.println("mAvailableOpenBssidsInScanHistogram:" 1461 + mAvailableOpenBssidsInScanHistogram.toString()); 1462 pw.println("mAvailableSavedSsidsInScanHistogram:" 1463 + mAvailableSavedSsidsInScanHistogram.toString()); 1464 pw.println("mAvailableSavedBssidsInScanHistogram:" 1465 + mAvailableSavedBssidsInScanHistogram.toString()); 1466 pw.println("mAvailableOpenOrSavedSsidsInScanHistogram:" 1467 + mAvailableOpenOrSavedSsidsInScanHistogram.toString()); 1468 pw.println("mAvailableOpenOrSavedBssidsInScanHistogram:" 1469 + mAvailableOpenOrSavedBssidsInScanHistogram.toString()); 1470 pw.println("mAvailableSavedPasspointProviderProfilesInScanHistogram:" 1471 + mAvailableSavedPasspointProviderProfilesInScanHistogram.toString()); 1472 pw.println("mAvailableSavedPasspointProviderBssidsInScanHistogram:" 1473 + mAvailableSavedPasspointProviderBssidsInScanHistogram.toString()); 1474 pw.println("mWifiLogProto.partialAllSingleScanListenerResults=" 1475 + mWifiLogProto.partialAllSingleScanListenerResults); 1476 pw.println("mWifiLogProto.fullBandAllSingleScanListenerResults=" 1477 + mWifiLogProto.fullBandAllSingleScanListenerResults); 1478 pw.println("mWifiAwareMetrics:"); 1479 mWifiAwareMetrics.dump(fd, pw, args); 1480 1481 pw.println("mPnoScanMetrics.numPnoScanAttempts=" 1482 + mPnoScanMetrics.numPnoScanAttempts); 1483 pw.println("mPnoScanMetrics.numPnoScanFailed=" 1484 + mPnoScanMetrics.numPnoScanFailed); 1485 pw.println("mPnoScanMetrics.numPnoScanStartedOverOffload=" 1486 + mPnoScanMetrics.numPnoScanStartedOverOffload); 1487 pw.println("mPnoScanMetrics.numPnoScanFailedOverOffload=" 1488 + mPnoScanMetrics.numPnoScanFailedOverOffload); 1489 pw.println("mPnoScanMetrics.numPnoFoundNetworkEvents=" 1490 + mPnoScanMetrics.numPnoFoundNetworkEvents); 1491 } 1492 } 1493 } 1494 1495 /** 1496 * Update various counts of saved network types 1497 * @param networks List of WifiConfigurations representing all saved networks, must not be null 1498 */ 1499 public void updateSavedNetworks(List<WifiConfiguration> networks) { 1500 synchronized (mLock) { 1501 mWifiLogProto.numSavedNetworks = networks.size(); 1502 mWifiLogProto.numOpenNetworks = 0; 1503 mWifiLogProto.numPersonalNetworks = 0; 1504 mWifiLogProto.numEnterpriseNetworks = 0; 1505 mWifiLogProto.numNetworksAddedByUser = 0; 1506 mWifiLogProto.numNetworksAddedByApps = 0; 1507 mWifiLogProto.numHiddenNetworks = 0; 1508 mWifiLogProto.numPasspointNetworks = 0; 1509 for (WifiConfiguration config : networks) { 1510 if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)) { 1511 mWifiLogProto.numOpenNetworks++; 1512 } else if (config.isEnterprise()) { 1513 mWifiLogProto.numEnterpriseNetworks++; 1514 } else { 1515 mWifiLogProto.numPersonalNetworks++; 1516 } 1517 if (config.selfAdded) { 1518 mWifiLogProto.numNetworksAddedByUser++; 1519 } else { 1520 mWifiLogProto.numNetworksAddedByApps++; 1521 } 1522 if (config.hiddenSSID) { 1523 mWifiLogProto.numHiddenNetworks++; 1524 } 1525 if (config.isPasspoint()) { 1526 mWifiLogProto.numPasspointNetworks++; 1527 } 1528 } 1529 } 1530 } 1531 1532 /** 1533 * Update metrics for saved Passpoint profiles. 1534 * 1535 * @param numSavedProfiles The number of saved Passpoint profiles 1536 * @param numConnectedProfiles The number of saved Passpoint profiles that have ever resulted 1537 * in a successful network connection 1538 */ 1539 public void updateSavedPasspointProfiles(int numSavedProfiles, int numConnectedProfiles) { 1540 synchronized (mLock) { 1541 mWifiLogProto.numPasspointProviders = numSavedProfiles; 1542 mWifiLogProto.numPasspointProvidersSuccessfullyConnected = numConnectedProfiles; 1543 } 1544 } 1545 1546 /** 1547 * append the separate ConnectionEvent, SystemStateEntry and ScanReturnCode collections to their 1548 * respective lists within mWifiLogProto 1549 * 1550 * @param incremental Only include ConnectionEvents created since last automatic bug report 1551 */ 1552 private void consolidateProto(boolean incremental) { 1553 List<WifiMetricsProto.ConnectionEvent> events = new ArrayList<>(); 1554 List<WifiMetricsProto.RssiPollCount> rssis = new ArrayList<>(); 1555 List<WifiMetricsProto.RssiPollCount> rssiDeltas = new ArrayList<>(); 1556 List<WifiMetricsProto.AlertReasonCount> alertReasons = new ArrayList<>(); 1557 List<WifiMetricsProto.WifiScoreCount> scores = new ArrayList<>(); 1558 synchronized (mLock) { 1559 for (ConnectionEvent event : mConnectionEventList) { 1560 // If this is not incremental, dump full ConnectionEvent list 1561 // Else Dump all un-dumped events except for the current one 1562 if (!incremental || ((mCurrentConnectionEvent != event) 1563 && !event.mConnectionEvent.automaticBugReportTaken)) { 1564 //Get all ConnectionEvents that haven not been dumped as a proto, also exclude 1565 //the current active un-ended connection event 1566 events.add(event.mConnectionEvent); 1567 if (incremental) { 1568 event.mConnectionEvent.automaticBugReportTaken = true; 1569 } 1570 } 1571 } 1572 if (events.size() > 0) { 1573 mWifiLogProto.connectionEvent = events.toArray(mWifiLogProto.connectionEvent); 1574 } 1575 1576 //Convert the SparseIntArray of scanReturnEntry integers into ScanReturnEntry proto list 1577 mWifiLogProto.scanReturnEntries = 1578 new WifiMetricsProto.WifiLog.ScanReturnEntry[mScanReturnEntries.size()]; 1579 for (int i = 0; i < mScanReturnEntries.size(); i++) { 1580 mWifiLogProto.scanReturnEntries[i] = new WifiMetricsProto.WifiLog.ScanReturnEntry(); 1581 mWifiLogProto.scanReturnEntries[i].scanReturnCode = mScanReturnEntries.keyAt(i); 1582 mWifiLogProto.scanReturnEntries[i].scanResultsCount = mScanReturnEntries.valueAt(i); 1583 } 1584 1585 // Convert the SparseIntArray of systemStateEntry into WifiSystemStateEntry proto list 1586 // This one is slightly more complex, as the Sparse are indexed with: 1587 // key: wifiState * 2 + isScreenOn, value: wifiStateCount 1588 mWifiLogProto.wifiSystemStateEntries = 1589 new WifiMetricsProto.WifiLog 1590 .WifiSystemStateEntry[mWifiSystemStateEntries.size()]; 1591 for (int i = 0; i < mWifiSystemStateEntries.size(); i++) { 1592 mWifiLogProto.wifiSystemStateEntries[i] = 1593 new WifiMetricsProto.WifiLog.WifiSystemStateEntry(); 1594 mWifiLogProto.wifiSystemStateEntries[i].wifiState = 1595 mWifiSystemStateEntries.keyAt(i) / 2; 1596 mWifiLogProto.wifiSystemStateEntries[i].wifiStateCount = 1597 mWifiSystemStateEntries.valueAt(i); 1598 mWifiLogProto.wifiSystemStateEntries[i].isScreenOn = 1599 (mWifiSystemStateEntries.keyAt(i) % 2) > 0; 1600 } 1601 mWifiLogProto.recordDurationSec = (int) ((mClock.getElapsedSinceBootMillis() / 1000) 1602 - mRecordStartTimeSec); 1603 1604 /** 1605 * Convert the SparseIntArray of RSSI poll rssi's and counts to the proto's repeated 1606 * IntKeyVal array. 1607 */ 1608 for (int i = 0; i < mRssiPollCounts.size(); i++) { 1609 WifiMetricsProto.RssiPollCount keyVal = new WifiMetricsProto.RssiPollCount(); 1610 keyVal.rssi = mRssiPollCounts.keyAt(i); 1611 keyVal.count = mRssiPollCounts.valueAt(i); 1612 rssis.add(keyVal); 1613 } 1614 mWifiLogProto.rssiPollRssiCount = rssis.toArray(mWifiLogProto.rssiPollRssiCount); 1615 1616 /** 1617 * Convert the SparseIntArray of RSSI delta rssi's and counts to the proto's repeated 1618 * IntKeyVal array. 1619 */ 1620 for (int i = 0; i < mRssiDeltaCounts.size(); i++) { 1621 WifiMetricsProto.RssiPollCount keyVal = new WifiMetricsProto.RssiPollCount(); 1622 keyVal.rssi = mRssiDeltaCounts.keyAt(i); 1623 keyVal.count = mRssiDeltaCounts.valueAt(i); 1624 rssiDeltas.add(keyVal); 1625 } 1626 mWifiLogProto.rssiPollDeltaCount = rssiDeltas.toArray(mWifiLogProto.rssiPollDeltaCount); 1627 1628 /** 1629 * Convert the SparseIntArray of alert reasons and counts to the proto's repeated 1630 * IntKeyVal array. 1631 */ 1632 for (int i = 0; i < mWifiAlertReasonCounts.size(); i++) { 1633 WifiMetricsProto.AlertReasonCount keyVal = new WifiMetricsProto.AlertReasonCount(); 1634 keyVal.reason = mWifiAlertReasonCounts.keyAt(i); 1635 keyVal.count = mWifiAlertReasonCounts.valueAt(i); 1636 alertReasons.add(keyVal); 1637 } 1638 mWifiLogProto.alertReasonCount = alertReasons.toArray(mWifiLogProto.alertReasonCount); 1639 1640 /** 1641 * Convert the SparseIntArray of Wifi Score and counts to proto's repeated 1642 * IntKeyVal array. 1643 */ 1644 for (int score = 0; score < mWifiScoreCounts.size(); score++) { 1645 WifiMetricsProto.WifiScoreCount keyVal = new WifiMetricsProto.WifiScoreCount(); 1646 keyVal.score = mWifiScoreCounts.keyAt(score); 1647 keyVal.count = mWifiScoreCounts.valueAt(score); 1648 scores.add(keyVal); 1649 } 1650 mWifiLogProto.wifiScoreCount = scores.toArray(mWifiLogProto.wifiScoreCount); 1651 1652 /** 1653 * Convert the SparseIntArray of SoftAp Return codes and counts to proto's repeated 1654 * IntKeyVal array. 1655 */ 1656 int codeCounts = mSoftApManagerReturnCodeCounts.size(); 1657 mWifiLogProto.softApReturnCode = new WifiMetricsProto.SoftApReturnCodeCount[codeCounts]; 1658 for (int sapCode = 0; sapCode < codeCounts; sapCode++) { 1659 mWifiLogProto.softApReturnCode[sapCode] = 1660 new WifiMetricsProto.SoftApReturnCodeCount(); 1661 mWifiLogProto.softApReturnCode[sapCode].startResult = 1662 mSoftApManagerReturnCodeCounts.keyAt(sapCode); 1663 mWifiLogProto.softApReturnCode[sapCode].count = 1664 mSoftApManagerReturnCodeCounts.valueAt(sapCode); 1665 } 1666 mWifiLogProto.totalSsidsInScanHistogram = 1667 makeNumConnectableNetworksBucketArray(mTotalSsidsInScanHistogram); 1668 mWifiLogProto.totalBssidsInScanHistogram = 1669 makeNumConnectableNetworksBucketArray(mTotalBssidsInScanHistogram); 1670 mWifiLogProto.availableOpenSsidsInScanHistogram = 1671 makeNumConnectableNetworksBucketArray(mAvailableOpenSsidsInScanHistogram); 1672 mWifiLogProto.availableOpenBssidsInScanHistogram = 1673 makeNumConnectableNetworksBucketArray(mAvailableOpenBssidsInScanHistogram); 1674 mWifiLogProto.availableSavedSsidsInScanHistogram = 1675 makeNumConnectableNetworksBucketArray(mAvailableSavedSsidsInScanHistogram); 1676 mWifiLogProto.availableSavedBssidsInScanHistogram = 1677 makeNumConnectableNetworksBucketArray(mAvailableSavedBssidsInScanHistogram); 1678 mWifiLogProto.availableOpenOrSavedSsidsInScanHistogram = 1679 makeNumConnectableNetworksBucketArray( 1680 mAvailableOpenOrSavedSsidsInScanHistogram); 1681 mWifiLogProto.availableOpenOrSavedBssidsInScanHistogram = 1682 makeNumConnectableNetworksBucketArray( 1683 mAvailableOpenOrSavedBssidsInScanHistogram); 1684 mWifiLogProto.availableSavedPasspointProviderProfilesInScanHistogram = 1685 makeNumConnectableNetworksBucketArray( 1686 mAvailableSavedPasspointProviderProfilesInScanHistogram); 1687 mWifiLogProto.availableSavedPasspointProviderBssidsInScanHistogram = 1688 makeNumConnectableNetworksBucketArray( 1689 mAvailableSavedPasspointProviderBssidsInScanHistogram); 1690 mWifiLogProto.staEventList = mStaEventList.toArray(mWifiLogProto.staEventList); 1691 mWifiLogProto.wifiAwareLog = mWifiAwareMetrics.consolidateProto(); 1692 1693 mWifiLogProto.pnoScanMetrics = mPnoScanMetrics; 1694 } 1695 } 1696 1697 private WifiMetricsProto.NumConnectableNetworksBucket[] makeNumConnectableNetworksBucketArray( 1698 SparseIntArray sia) { 1699 WifiMetricsProto.NumConnectableNetworksBucket[] array = 1700 new WifiMetricsProto.NumConnectableNetworksBucket[sia.size()]; 1701 for (int i = 0; i < sia.size(); i++) { 1702 WifiMetricsProto.NumConnectableNetworksBucket keyVal = 1703 new WifiMetricsProto.NumConnectableNetworksBucket(); 1704 keyVal.numConnectableNetworks = sia.keyAt(i); 1705 keyVal.count = sia.valueAt(i); 1706 array[i] = keyVal; 1707 } 1708 return array; 1709 } 1710 1711 /** 1712 * Clear all WifiMetrics, except for currentConnectionEvent. 1713 */ 1714 private void clear() { 1715 synchronized (mLock) { 1716 mConnectionEventList.clear(); 1717 if (mCurrentConnectionEvent != null) { 1718 mConnectionEventList.add(mCurrentConnectionEvent); 1719 } 1720 mScanReturnEntries.clear(); 1721 mWifiSystemStateEntries.clear(); 1722 mRecordStartTimeSec = mClock.getElapsedSinceBootMillis() / 1000; 1723 mRssiPollCounts.clear(); 1724 mRssiDeltaCounts.clear(); 1725 mWifiAlertReasonCounts.clear(); 1726 mWifiScoreCounts.clear(); 1727 mWifiLogProto.clear(); 1728 mScanResultRssiTimestampMillis = -1; 1729 mSoftApManagerReturnCodeCounts.clear(); 1730 mStaEventList.clear(); 1731 mWifiAwareMetrics.clear(); 1732 mTotalSsidsInScanHistogram.clear(); 1733 mTotalBssidsInScanHistogram.clear(); 1734 mAvailableOpenSsidsInScanHistogram.clear(); 1735 mAvailableOpenBssidsInScanHistogram.clear(); 1736 mAvailableSavedSsidsInScanHistogram.clear(); 1737 mAvailableSavedBssidsInScanHistogram.clear(); 1738 mAvailableOpenOrSavedSsidsInScanHistogram.clear(); 1739 mAvailableOpenOrSavedBssidsInScanHistogram.clear(); 1740 mAvailableSavedPasspointProviderProfilesInScanHistogram.clear(); 1741 mAvailableSavedPasspointProviderBssidsInScanHistogram.clear(); 1742 mPnoScanMetrics.clear(); 1743 } 1744 } 1745 1746 /** 1747 * Set screen state (On/Off) 1748 */ 1749 public void setScreenState(boolean screenOn) { 1750 synchronized (mLock) { 1751 mScreenOn = screenOn; 1752 } 1753 } 1754 1755 /** 1756 * Set wifi state (WIFI_UNKNOWN, WIFI_DISABLED, WIFI_DISCONNECTED, WIFI_ASSOCIATED) 1757 */ 1758 public void setWifiState(int wifiState) { 1759 synchronized (mLock) { 1760 mWifiState = wifiState; 1761 } 1762 } 1763 1764 /** 1765 * Message handler for interesting WifiMonitor messages. Generates StaEvents 1766 */ 1767 private void processMessage(Message msg) { 1768 StaEvent event = new StaEvent(); 1769 boolean logEvent = true; 1770 switch (msg.what) { 1771 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 1772 event.type = StaEvent.TYPE_ASSOCIATION_REJECTION_EVENT; 1773 event.associationTimedOut = msg.arg1 > 0 ? true : false; 1774 event.status = msg.arg2; 1775 break; 1776 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 1777 event.type = StaEvent.TYPE_AUTHENTICATION_FAILURE_EVENT; 1778 switch (msg.arg2) { 1779 case WifiManager.ERROR_AUTH_FAILURE_NONE: 1780 event.authFailureReason = StaEvent.AUTH_FAILURE_NONE; 1781 break; 1782 case WifiManager.ERROR_AUTH_FAILURE_TIMEOUT: 1783 event.authFailureReason = StaEvent.AUTH_FAILURE_TIMEOUT; 1784 break; 1785 case WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD: 1786 event.authFailureReason = StaEvent.AUTH_FAILURE_WRONG_PSWD; 1787 break; 1788 case WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE: 1789 event.authFailureReason = StaEvent.AUTH_FAILURE_EAP_FAILURE; 1790 break; 1791 default: 1792 break; 1793 } 1794 break; 1795 case WifiMonitor.NETWORK_CONNECTION_EVENT: 1796 event.type = StaEvent.TYPE_NETWORK_CONNECTION_EVENT; 1797 break; 1798 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 1799 event.type = StaEvent.TYPE_NETWORK_DISCONNECTION_EVENT; 1800 event.reason = msg.arg2; 1801 event.localGen = msg.arg1 == 0 ? false : true; 1802 break; 1803 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 1804 logEvent = false; 1805 StateChangeResult stateChangeResult = (StateChangeResult) msg.obj; 1806 mSupplicantStateChangeBitmask |= supplicantStateToBit(stateChangeResult.state); 1807 break; 1808 case WifiStateMachine.CMD_ASSOCIATED_BSSID: 1809 event.type = StaEvent.TYPE_CMD_ASSOCIATED_BSSID; 1810 break; 1811 case WifiStateMachine.CMD_TARGET_BSSID: 1812 event.type = StaEvent.TYPE_CMD_TARGET_BSSID; 1813 break; 1814 default: 1815 return; 1816 } 1817 if (logEvent) { 1818 addStaEvent(event); 1819 } 1820 } 1821 /** 1822 * Log a StaEvent from WifiStateMachine. The StaEvent must not be one of the supplicant 1823 * generated event types, which are logged through 'sendMessage' 1824 * @param type StaEvent.EventType describing the event 1825 */ 1826 public void logStaEvent(int type) { 1827 logStaEvent(type, StaEvent.DISCONNECT_UNKNOWN, null); 1828 } 1829 /** 1830 * Log a StaEvent from WifiStateMachine. The StaEvent must not be one of the supplicant 1831 * generated event types, which are logged through 'sendMessage' 1832 * @param type StaEvent.EventType describing the event 1833 * @param config WifiConfiguration for a framework initiated connection attempt 1834 */ 1835 public void logStaEvent(int type, WifiConfiguration config) { 1836 logStaEvent(type, StaEvent.DISCONNECT_UNKNOWN, config); 1837 } 1838 /** 1839 * Log a StaEvent from WifiStateMachine. The StaEvent must not be one of the supplicant 1840 * generated event types, which are logged through 'sendMessage' 1841 * @param type StaEvent.EventType describing the event 1842 * @param frameworkDisconnectReason StaEvent.FrameworkDisconnectReason explaining why framework 1843 * initiated a FRAMEWORK_DISCONNECT 1844 */ 1845 public void logStaEvent(int type, int frameworkDisconnectReason) { 1846 logStaEvent(type, frameworkDisconnectReason, null); 1847 } 1848 /** 1849 * Log a StaEvent from WifiStateMachine. The StaEvent must not be one of the supplicant 1850 * generated event types, which are logged through 'sendMessage' 1851 * @param type StaEvent.EventType describing the event 1852 * @param frameworkDisconnectReason StaEvent.FrameworkDisconnectReason explaining why framework 1853 * initiated a FRAMEWORK_DISCONNECT 1854 * @param config WifiConfiguration for a framework initiated connection attempt 1855 */ 1856 public void logStaEvent(int type, int frameworkDisconnectReason, WifiConfiguration config) { 1857 switch (type) { 1858 case StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL: 1859 case StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST: 1860 case StaEvent.TYPE_CMD_IP_REACHABILITY_LOST: 1861 case StaEvent.TYPE_CMD_START_CONNECT: 1862 case StaEvent.TYPE_CMD_START_ROAM: 1863 case StaEvent.TYPE_CONNECT_NETWORK: 1864 case StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK: 1865 case StaEvent.TYPE_FRAMEWORK_DISCONNECT: 1866 break; 1867 default: 1868 Log.e(TAG, "Unknown StaEvent:" + type); 1869 return; 1870 } 1871 StaEvent event = new StaEvent(); 1872 event.type = type; 1873 if (frameworkDisconnectReason != StaEvent.DISCONNECT_UNKNOWN) { 1874 event.frameworkDisconnectReason = frameworkDisconnectReason; 1875 } 1876 event.configInfo = createConfigInfo(config); 1877 addStaEvent(event); 1878 } 1879 1880 private void addStaEvent(StaEvent staEvent) { 1881 staEvent.startTimeMillis = mClock.getElapsedSinceBootMillis(); 1882 staEvent.lastRssi = mLastPollRssi; 1883 staEvent.lastFreq = mLastPollFreq; 1884 staEvent.lastLinkSpeed = mLastPollLinkSpeed; 1885 staEvent.supplicantStateChangesBitmask = mSupplicantStateChangeBitmask; 1886 mSupplicantStateChangeBitmask = 0; 1887 mLastPollRssi = -127; 1888 mLastPollFreq = -1; 1889 mLastPollLinkSpeed = -1; 1890 mStaEventList.add(staEvent); 1891 // Prune StaEventList if it gets too long 1892 if (mStaEventList.size() > MAX_STA_EVENTS) mStaEventList.remove(); 1893 } 1894 1895 private ConfigInfo createConfigInfo(WifiConfiguration config) { 1896 if (config == null) return null; 1897 ConfigInfo info = new ConfigInfo(); 1898 info.allowedKeyManagement = bitSetToInt(config.allowedKeyManagement); 1899 info.allowedProtocols = bitSetToInt(config.allowedProtocols); 1900 info.allowedAuthAlgorithms = bitSetToInt(config.allowedAuthAlgorithms); 1901 info.allowedPairwiseCiphers = bitSetToInt(config.allowedPairwiseCiphers); 1902 info.allowedGroupCiphers = bitSetToInt(config.allowedGroupCiphers); 1903 info.hiddenSsid = config.hiddenSSID; 1904 info.isPasspoint = config.isPasspoint(); 1905 info.isEphemeral = config.isEphemeral(); 1906 info.hasEverConnected = config.getNetworkSelectionStatus().getHasEverConnected(); 1907 ScanResult candidate = config.getNetworkSelectionStatus().getCandidate(); 1908 if (candidate != null) { 1909 info.scanRssi = candidate.level; 1910 info.scanFreq = candidate.frequency; 1911 } 1912 return info; 1913 } 1914 1915 public Handler getHandler() { 1916 return mHandler; 1917 } 1918 1919 public WifiAwareMetrics getWifiAwareMetrics() { 1920 return mWifiAwareMetrics; 1921 } 1922 1923 // Rather than generate a StaEvent for each SUPPLICANT_STATE_CHANGE, cache these in a bitmask 1924 // and attach it to the next event which is generated. 1925 private int mSupplicantStateChangeBitmask = 0; 1926 1927 /** 1928 * Converts a SupplicantState value to a single bit, with position defined by 1929 * {@code StaEvent.SupplicantState} 1930 */ 1931 public static int supplicantStateToBit(SupplicantState state) { 1932 switch(state) { 1933 case DISCONNECTED: 1934 return 1 << StaEvent.STATE_DISCONNECTED; 1935 case INTERFACE_DISABLED: 1936 return 1 << StaEvent.STATE_INTERFACE_DISABLED; 1937 case INACTIVE: 1938 return 1 << StaEvent.STATE_INACTIVE; 1939 case SCANNING: 1940 return 1 << StaEvent.STATE_SCANNING; 1941 case AUTHENTICATING: 1942 return 1 << StaEvent.STATE_AUTHENTICATING; 1943 case ASSOCIATING: 1944 return 1 << StaEvent.STATE_ASSOCIATING; 1945 case ASSOCIATED: 1946 return 1 << StaEvent.STATE_ASSOCIATED; 1947 case FOUR_WAY_HANDSHAKE: 1948 return 1 << StaEvent.STATE_FOUR_WAY_HANDSHAKE; 1949 case GROUP_HANDSHAKE: 1950 return 1 << StaEvent.STATE_GROUP_HANDSHAKE; 1951 case COMPLETED: 1952 return 1 << StaEvent.STATE_COMPLETED; 1953 case DORMANT: 1954 return 1 << StaEvent.STATE_DORMANT; 1955 case UNINITIALIZED: 1956 return 1 << StaEvent.STATE_UNINITIALIZED; 1957 case INVALID: 1958 return 1 << StaEvent.STATE_INVALID; 1959 default: 1960 Log.wtf(TAG, "Got unknown supplicant state: " + state.ordinal()); 1961 return 0; 1962 } 1963 } 1964 1965 private static String supplicantStateChangesBitmaskToString(int mask) { 1966 StringBuilder sb = new StringBuilder(); 1967 sb.append("SUPPLICANT_STATE_CHANGE_EVENTS: {"); 1968 if ((mask & (1 << StaEvent.STATE_DISCONNECTED)) > 0) sb.append(" DISCONNECTED"); 1969 if ((mask & (1 << StaEvent.STATE_INTERFACE_DISABLED)) > 0) sb.append(" INTERFACE_DISABLED"); 1970 if ((mask & (1 << StaEvent.STATE_INACTIVE)) > 0) sb.append(" INACTIVE"); 1971 if ((mask & (1 << StaEvent.STATE_SCANNING)) > 0) sb.append(" SCANNING"); 1972 if ((mask & (1 << StaEvent.STATE_AUTHENTICATING)) > 0) sb.append(" AUTHENTICATING"); 1973 if ((mask & (1 << StaEvent.STATE_ASSOCIATING)) > 0) sb.append(" ASSOCIATING"); 1974 if ((mask & (1 << StaEvent.STATE_ASSOCIATED)) > 0) sb.append(" ASSOCIATED"); 1975 if ((mask & (1 << StaEvent.STATE_FOUR_WAY_HANDSHAKE)) > 0) sb.append(" FOUR_WAY_HANDSHAKE"); 1976 if ((mask & (1 << StaEvent.STATE_GROUP_HANDSHAKE)) > 0) sb.append(" GROUP_HANDSHAKE"); 1977 if ((mask & (1 << StaEvent.STATE_COMPLETED)) > 0) sb.append(" COMPLETED"); 1978 if ((mask & (1 << StaEvent.STATE_DORMANT)) > 0) sb.append(" DORMANT"); 1979 if ((mask & (1 << StaEvent.STATE_UNINITIALIZED)) > 0) sb.append(" UNINITIALIZED"); 1980 if ((mask & (1 << StaEvent.STATE_INVALID)) > 0) sb.append(" INVALID"); 1981 sb.append("}"); 1982 return sb.toString(); 1983 } 1984 1985 /** 1986 * Returns a human readable string from a Sta Event. Only adds information relevant to the event 1987 * type. 1988 */ 1989 public static String staEventToString(StaEvent event) { 1990 if (event == null) return "<NULL>"; 1991 StringBuilder sb = new StringBuilder(); 1992 Long time = event.startTimeMillis; 1993 sb.append(String.format("%9d ", time.longValue())).append(" "); 1994 switch (event.type) { 1995 case StaEvent.TYPE_ASSOCIATION_REJECTION_EVENT: 1996 sb.append("ASSOCIATION_REJECTION_EVENT:") 1997 .append(" timedOut=").append(event.associationTimedOut) 1998 .append(" status=").append(event.status).append(":") 1999 .append(ISupplicantStaIfaceCallback.StatusCode.toString(event.status)); 2000 break; 2001 case StaEvent.TYPE_AUTHENTICATION_FAILURE_EVENT: 2002 sb.append("AUTHENTICATION_FAILURE_EVENT: reason=").append(event.authFailureReason) 2003 .append(":").append(authFailureReasonToString(event.authFailureReason)); 2004 break; 2005 case StaEvent.TYPE_NETWORK_CONNECTION_EVENT: 2006 sb.append("NETWORK_CONNECTION_EVENT:"); 2007 break; 2008 case StaEvent.TYPE_NETWORK_DISCONNECTION_EVENT: 2009 sb.append("NETWORK_DISCONNECTION_EVENT:") 2010 .append(" local_gen=").append(event.localGen) 2011 .append(" reason=").append(event.reason).append(":") 2012 .append(ISupplicantStaIfaceCallback.ReasonCode.toString( 2013 (event.reason >= 0 ? event.reason : -1 * event.reason))); 2014 break; 2015 case StaEvent.TYPE_CMD_ASSOCIATED_BSSID: 2016 sb.append("CMD_ASSOCIATED_BSSID:"); 2017 break; 2018 case StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL: 2019 sb.append("CMD_IP_CONFIGURATION_SUCCESSFUL:"); 2020 break; 2021 case StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST: 2022 sb.append("CMD_IP_CONFIGURATION_LOST:"); 2023 break; 2024 case StaEvent.TYPE_CMD_IP_REACHABILITY_LOST: 2025 sb.append("CMD_IP_REACHABILITY_LOST:"); 2026 break; 2027 case StaEvent.TYPE_CMD_TARGET_BSSID: 2028 sb.append("CMD_TARGET_BSSID:"); 2029 break; 2030 case StaEvent.TYPE_CMD_START_CONNECT: 2031 sb.append("CMD_START_CONNECT:"); 2032 break; 2033 case StaEvent.TYPE_CMD_START_ROAM: 2034 sb.append("CMD_START_ROAM:"); 2035 break; 2036 case StaEvent.TYPE_CONNECT_NETWORK: 2037 sb.append("CONNECT_NETWORK:"); 2038 break; 2039 case StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK: 2040 sb.append("NETWORK_AGENT_VALID_NETWORK:"); 2041 break; 2042 case StaEvent.TYPE_FRAMEWORK_DISCONNECT: 2043 sb.append("FRAMEWORK_DISCONNECT:") 2044 .append(" reason=") 2045 .append(frameworkDisconnectReasonToString(event.frameworkDisconnectReason)); 2046 break; 2047 default: 2048 sb.append("UNKNOWN " + event.type + ":"); 2049 break; 2050 } 2051 if (event.lastRssi != -127) sb.append(" lastRssi=").append(event.lastRssi); 2052 if (event.lastFreq != -1) sb.append(" lastFreq=").append(event.lastFreq); 2053 if (event.lastLinkSpeed != -1) sb.append(" lastLinkSpeed=").append(event.lastLinkSpeed); 2054 if (event.supplicantStateChangesBitmask != 0) { 2055 sb.append("\n ").append(supplicantStateChangesBitmaskToString( 2056 event.supplicantStateChangesBitmask)); 2057 } 2058 if (event.configInfo != null) { 2059 sb.append("\n ").append(configInfoToString(event.configInfo)); 2060 } 2061 2062 return sb.toString(); 2063 } 2064 2065 private static String authFailureReasonToString(int authFailureReason) { 2066 switch (authFailureReason) { 2067 case StaEvent.AUTH_FAILURE_NONE: 2068 return "ERROR_AUTH_FAILURE_NONE"; 2069 case StaEvent.AUTH_FAILURE_TIMEOUT: 2070 return "ERROR_AUTH_FAILURE_TIMEOUT"; 2071 case StaEvent.AUTH_FAILURE_WRONG_PSWD: 2072 return "ERROR_AUTH_FAILURE_WRONG_PSWD"; 2073 case StaEvent.AUTH_FAILURE_EAP_FAILURE: 2074 return "ERROR_AUTH_FAILURE_EAP_FAILURE"; 2075 default: 2076 return ""; 2077 } 2078 } 2079 2080 private static String frameworkDisconnectReasonToString(int frameworkDisconnectReason) { 2081 switch (frameworkDisconnectReason) { 2082 case StaEvent.DISCONNECT_API: 2083 return "DISCONNECT_API"; 2084 case StaEvent.DISCONNECT_GENERIC: 2085 return "DISCONNECT_GENERIC"; 2086 case StaEvent.DISCONNECT_UNWANTED: 2087 return "DISCONNECT_UNWANTED"; 2088 case StaEvent.DISCONNECT_ROAM_WATCHDOG_TIMER: 2089 return "DISCONNECT_ROAM_WATCHDOG_TIMER"; 2090 case StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST: 2091 return "DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST"; 2092 case StaEvent.DISCONNECT_RESET_SIM_NETWORKS: 2093 return "DISCONNECT_RESET_SIM_NETWORKS"; 2094 default: 2095 return "DISCONNECT_UNKNOWN=" + frameworkDisconnectReason; 2096 } 2097 } 2098 2099 private static String configInfoToString(ConfigInfo info) { 2100 StringBuilder sb = new StringBuilder(); 2101 sb.append("ConfigInfo:") 2102 .append(" allowed_key_management=").append(info.allowedKeyManagement) 2103 .append(" allowed_protocols=").append(info.allowedProtocols) 2104 .append(" allowed_auth_algorithms=").append(info.allowedAuthAlgorithms) 2105 .append(" allowed_pairwise_ciphers=").append(info.allowedPairwiseCiphers) 2106 .append(" allowed_group_ciphers=").append(info.allowedGroupCiphers) 2107 .append(" hidden_ssid=").append(info.hiddenSsid) 2108 .append(" is_passpoint=").append(info.isPasspoint) 2109 .append(" is_ephemeral=").append(info.isEphemeral) 2110 .append(" has_ever_connected=").append(info.hasEverConnected) 2111 .append(" scan_rssi=").append(info.scanRssi) 2112 .append(" scan_freq=").append(info.scanFreq); 2113 return sb.toString(); 2114 } 2115 2116 public static final int MAX_STA_EVENTS = 512; 2117 private LinkedList<StaEvent> mStaEventList = new LinkedList<StaEvent>(); 2118 private int mLastPollRssi = -127; 2119 private int mLastPollLinkSpeed = -1; 2120 private int mLastPollFreq = -1; 2121 2122 /** 2123 * Converts the first 31 bits of a BitSet to a little endian int 2124 */ 2125 private static int bitSetToInt(BitSet bits) { 2126 int value = 0; 2127 int nBits = bits.length() < 31 ? bits.length() : 31; 2128 for (int i = 0; i < nBits; i++) { 2129 value += bits.get(i) ? (1 << i) : 0; 2130 } 2131 return value; 2132 } 2133 private void incrementSsid(SparseIntArray sia, int element) { 2134 increment(sia, Math.min(element, MAX_CONNECTABLE_SSID_NETWORK_BUCKET)); 2135 } 2136 private void incrementBssid(SparseIntArray sia, int element) { 2137 increment(sia, Math.min(element, MAX_CONNECTABLE_BSSID_NETWORK_BUCKET)); 2138 } 2139 private void incrementTotalScanResults(SparseIntArray sia, int element) { 2140 increment(sia, Math.min(element, MAX_TOTAL_SCAN_RESULTS_BUCKET)); 2141 } 2142 private void incrementTotalScanSsids(SparseIntArray sia, int element) { 2143 increment(sia, Math.min(element, MAX_TOTAL_SCAN_RESULT_SSIDS_BUCKET)); 2144 } 2145 private void increment(SparseIntArray sia, int element) { 2146 int count = sia.get(element); 2147 sia.put(element, count + 1); 2148 } 2149} 2150