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