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