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