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