Home | History | Annotate | Download | only in wifi
      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.net.wifi.ScanResult;
     20 import android.net.wifi.WifiConfiguration;
     21 import android.util.Base64;
     22 import android.util.Log;
     23 import android.util.SparseIntArray;
     24 
     25 import com.android.server.wifi.hotspot2.NetworkDetail;
     26 import com.android.server.wifi.util.InformationElementUtil;
     27 
     28 import java.io.FileDescriptor;
     29 import java.io.PrintWriter;
     30 import java.util.ArrayList;
     31 import java.util.Calendar;
     32 import java.util.List;
     33 
     34 /**
     35  * Provides storage for wireless connectivity metrics, as they are generated.
     36  * Metrics logged by this class include:
     37  *   Aggregated connection stats (num of connections, num of failures, ...)
     38  *   Discrete connection event stats (time, duration, failure codes, ...)
     39  *   Router details (technology type, authentication type, ...)
     40  *   Scan stats
     41  */
     42 public class WifiMetrics {
     43     private static final String TAG = "WifiMetrics";
     44     private static final boolean DBG = false;
     45     /**
     46      * Clamp the RSSI poll counts to values between [MIN,MAX]_RSSI_POLL
     47      */
     48     private static final int MAX_RSSI_POLL = 0;
     49     private static final int MIN_RSSI_POLL = -127;
     50     private final Object mLock = new Object();
     51     private static final int MAX_CONNECTION_EVENTS = 256;
     52     private Clock mClock;
     53     private boolean mScreenOn;
     54     private int mWifiState;
     55     /**
     56      * Metrics are stored within an instance of the WifiLog proto during runtime,
     57      * The ConnectionEvent, SystemStateEntries & ScanReturnEntries metrics are stored during
     58      * runtime in member lists of this WifiMetrics class, with the final WifiLog proto being pieced
     59      * together at dump-time
     60      */
     61     private final WifiMetricsProto.WifiLog mWifiLogProto = new WifiMetricsProto.WifiLog();
     62     /**
     63      * Session information that gets logged for every Wifi connection attempt.
     64      */
     65     private final List<ConnectionEvent> mConnectionEventList = new ArrayList<>();
     66     /**
     67      * The latest started (but un-ended) connection attempt
     68      */
     69     private ConnectionEvent mCurrentConnectionEvent;
     70     /**
     71      * Count of number of times each scan return code, indexed by WifiLog.ScanReturnCode
     72      */
     73     private final SparseIntArray mScanReturnEntries = new SparseIntArray();
     74     /**
     75      * Mapping of system state to the counts of scans requested in that wifi state * screenOn
     76      * combination. Indexed by WifiLog.WifiState * (1 + screenOn)
     77      */
     78     private final SparseIntArray mWifiSystemStateEntries = new SparseIntArray();
     79     /**
     80      * Records the elapsedRealtime (in seconds) that represents the beginning of data
     81      * capture for for this WifiMetricsProto
     82      */
     83     private final SparseIntArray mRssiPollCounts = new SparseIntArray();
     84     private long mRecordStartTimeSec;
     85 
     86     class RouterFingerPrint {
     87         private WifiMetricsProto.RouterFingerPrint mRouterFingerPrintProto;
     88         RouterFingerPrint() {
     89             mRouterFingerPrintProto = new WifiMetricsProto.RouterFingerPrint();
     90         }
     91 
     92         public String toString() {
     93             StringBuilder sb = new StringBuilder();
     94             synchronized (mLock) {
     95                 sb.append("mConnectionEvent.roamType=" + mRouterFingerPrintProto.roamType);
     96                 sb.append(", mChannelInfo=" + mRouterFingerPrintProto.channelInfo);
     97                 sb.append(", mDtim=" + mRouterFingerPrintProto.dtim);
     98                 sb.append(", mAuthentication=" + mRouterFingerPrintProto.authentication);
     99                 sb.append(", mHidden=" + mRouterFingerPrintProto.hidden);
    100                 sb.append(", mRouterTechnology=" + mRouterFingerPrintProto.routerTechnology);
    101                 sb.append(", mSupportsIpv6=" + mRouterFingerPrintProto.supportsIpv6);
    102             }
    103             return sb.toString();
    104         }
    105         public void updateFromWifiConfiguration(WifiConfiguration config) {
    106             synchronized (mLock) {
    107                 if (config != null) {
    108                     // Is this a hidden network
    109                     mRouterFingerPrintProto.hidden = config.hiddenSSID;
    110                     // Config may not have a valid dtimInterval set yet, in which case dtim will be zero
    111                     // (These are only populated from beacon frame scan results, which are returned as
    112                     // scan results from the chip far less frequently than Probe-responses)
    113                     if (config.dtimInterval > 0) {
    114                         mRouterFingerPrintProto.dtim = config.dtimInterval;
    115                     }
    116                     mCurrentConnectionEvent.mConfigSsid = config.SSID;
    117                     // Get AuthType information from config (We do this again from ScanResult after
    118                     // associating with BSSID)
    119                     if (config.allowedKeyManagement != null
    120                             && config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)) {
    121                         mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto
    122                                 .authentication = WifiMetricsProto.RouterFingerPrint.AUTH_OPEN;
    123                     } else if (config.isEnterprise()) {
    124                         mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto
    125                                 .authentication = WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE;
    126                     } else {
    127                         mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto
    128                                 .authentication = WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL;
    129                     }
    130                     // If there's a ScanResult candidate associated with this config already, get it and
    131                     // log (more accurate) metrics from it
    132                     ScanResult candidate = config.getNetworkSelectionStatus().getCandidate();
    133                     if (candidate != null) {
    134                         updateMetricsFromScanResult(candidate);
    135                     }
    136                 }
    137             }
    138         }
    139     }
    140 
    141     /**
    142      * Log event, tracking the start time, end time and result of a wireless connection attempt.
    143      */
    144     class ConnectionEvent {
    145         WifiMetricsProto.ConnectionEvent mConnectionEvent;
    146         //<TODO> Move these constants into a wifi.proto Enum, and create a new Failure Type field
    147         //covering more than just l2 failures. see b/27652362
    148         /**
    149          * Failure codes, used for the 'level_2_failure_code' Connection event field (covers a lot
    150          * more failures than just l2 though, since the proto does not have a place to log
    151          * framework failures)
    152          */
    153         // Failure is unknown
    154         public static final int FAILURE_UNKNOWN = 0;
    155         // NONE
    156         public static final int FAILURE_NONE = 1;
    157         // ASSOCIATION_REJECTION_EVENT
    158         public static final int FAILURE_ASSOCIATION_REJECTION = 2;
    159         // AUTHENTICATION_FAILURE_EVENT
    160         public static final int FAILURE_AUTHENTICATION_FAILURE = 3;
    161         // SSID_TEMP_DISABLED (Also Auth failure)
    162         public static final int FAILURE_SSID_TEMP_DISABLED = 4;
    163         // reconnect() or reassociate() call to WifiNative failed
    164         public static final int FAILURE_CONNECT_NETWORK_FAILED = 5;
    165         // NETWORK_DISCONNECTION_EVENT
    166         public static final int FAILURE_NETWORK_DISCONNECTION = 6;
    167         // NEW_CONNECTION_ATTEMPT before previous finished
    168         public static final int FAILURE_NEW_CONNECTION_ATTEMPT = 7;
    169         // New connection attempt to the same network & bssid
    170         public static final int FAILURE_REDUNDANT_CONNECTION_ATTEMPT = 8;
    171         // Roam Watchdog timer triggered (Roaming timed out)
    172         public static final int FAILURE_ROAM_TIMEOUT = 9;
    173         // DHCP failure
    174         public static final int FAILURE_DHCP = 10;
    175 
    176         RouterFingerPrint mRouterFingerPrint;
    177         private long mRealStartTime;
    178         private long mRealEndTime;
    179         private String mConfigSsid;
    180         private String mConfigBssid;
    181         private int mWifiState;
    182         private boolean mScreenOn;
    183 
    184         private ConnectionEvent() {
    185             mConnectionEvent = new WifiMetricsProto.ConnectionEvent();
    186             mRealEndTime = 0;
    187             mRealStartTime = 0;
    188             mRouterFingerPrint = new RouterFingerPrint();
    189             mConnectionEvent.routerFingerprint = mRouterFingerPrint.mRouterFingerPrintProto;
    190             mConfigSsid = "<NULL>";
    191             mConfigBssid = "<NULL>";
    192             mWifiState = WifiMetricsProto.WifiLog.WIFI_UNKNOWN;
    193             mScreenOn = false;
    194         }
    195 
    196         public String toString() {
    197             StringBuilder sb = new StringBuilder();
    198             sb.append("startTime=");
    199             Calendar c = Calendar.getInstance();
    200             synchronized (mLock) {
    201                 c.setTimeInMillis(mConnectionEvent.startTimeMillis);
    202                 sb.append(mConnectionEvent.startTimeMillis == 0 ? "            <null>" :
    203                         String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c));
    204                 sb.append(", SSID=");
    205                 sb.append(mConfigSsid);
    206                 sb.append(", BSSID=");
    207                 sb.append(mConfigBssid);
    208                 sb.append(", durationMillis=");
    209                 sb.append(mConnectionEvent.durationTakenToConnectMillis);
    210                 sb.append(", roamType=");
    211                 switch(mConnectionEvent.roamType) {
    212                     case 1:
    213                         sb.append("ROAM_NONE");
    214                         break;
    215                     case 2:
    216                         sb.append("ROAM_DBDC");
    217                         break;
    218                     case 3:
    219                         sb.append("ROAM_ENTERPRISE");
    220                         break;
    221                     case 4:
    222                         sb.append("ROAM_USER_SELECTED");
    223                         break;
    224                     case 5:
    225                         sb.append("ROAM_UNRELATED");
    226                         break;
    227                     default:
    228                         sb.append("ROAM_UNKNOWN");
    229                 }
    230                 sb.append(", connectionResult=");
    231                 sb.append(mConnectionEvent.connectionResult);
    232                 sb.append(", level2FailureCode=");
    233                 switch(mConnectionEvent.level2FailureCode) {
    234                     case FAILURE_NONE:
    235                         sb.append("NONE");
    236                         break;
    237                     case FAILURE_ASSOCIATION_REJECTION:
    238                         sb.append("ASSOCIATION_REJECTION");
    239                         break;
    240                     case FAILURE_AUTHENTICATION_FAILURE:
    241                         sb.append("AUTHENTICATION_FAILURE");
    242                         break;
    243                     case FAILURE_SSID_TEMP_DISABLED:
    244                         sb.append("SSID_TEMP_DISABLED");
    245                         break;
    246                     case FAILURE_CONNECT_NETWORK_FAILED:
    247                         sb.append("CONNECT_NETWORK_FAILED");
    248                         break;
    249                     case FAILURE_NETWORK_DISCONNECTION:
    250                         sb.append("NETWORK_DISCONNECTION");
    251                         break;
    252                     case FAILURE_NEW_CONNECTION_ATTEMPT:
    253                         sb.append("NEW_CONNECTION_ATTEMPT");
    254                         break;
    255                     case FAILURE_REDUNDANT_CONNECTION_ATTEMPT:
    256                         sb.append("REDUNDANT_CONNECTION_ATTEMPT");
    257                         break;
    258                     case FAILURE_ROAM_TIMEOUT:
    259                         sb.append("ROAM_TIMEOUT");
    260                         break;
    261                     case FAILURE_DHCP:
    262                         sb.append("DHCP");
    263                     default:
    264                         sb.append("UNKNOWN");
    265                         break;
    266                 }
    267                 sb.append(", connectivityLevelFailureCode=");
    268                 switch(mConnectionEvent.connectivityLevelFailureCode) {
    269                     case WifiMetricsProto.ConnectionEvent.HLF_NONE:
    270                         sb.append("NONE");
    271                         break;
    272                     case WifiMetricsProto.ConnectionEvent.HLF_DHCP:
    273                         sb.append("DHCP");
    274                         break;
    275                     case WifiMetricsProto.ConnectionEvent.HLF_NO_INTERNET:
    276                         sb.append("NO_INTERNET");
    277                         break;
    278                     case WifiMetricsProto.ConnectionEvent.HLF_UNWANTED:
    279                         sb.append("UNWANTED");
    280                         break;
    281                     default:
    282                         sb.append("UNKNOWN");
    283                         break;
    284                 }
    285                 sb.append(", signalStrength=");
    286                 sb.append(mConnectionEvent.signalStrength);
    287                 sb.append(", wifiState=");
    288                 switch(mWifiState) {
    289                     case WifiMetricsProto.WifiLog.WIFI_DISABLED:
    290                         sb.append("WIFI_DISABLED");
    291                         break;
    292                     case WifiMetricsProto.WifiLog.WIFI_DISCONNECTED:
    293                         sb.append("WIFI_DISCONNECTED");
    294                         break;
    295                     case WifiMetricsProto.WifiLog.WIFI_ASSOCIATED:
    296                         sb.append("WIFI_ASSOCIATED");
    297                         break;
    298                     default:
    299                         sb.append("WIFI_UNKNOWN");
    300                         break;
    301                 }
    302                 sb.append(", screenOn=");
    303                 sb.append(mScreenOn);
    304                 sb.append(". mRouterFingerprint: ");
    305                 sb.append(mRouterFingerPrint.toString());
    306             }
    307             return sb.toString();
    308         }
    309     }
    310 
    311     public WifiMetrics(Clock clock) {
    312         mClock = clock;
    313         mCurrentConnectionEvent = null;
    314         mScreenOn = true;
    315         mWifiState = WifiMetricsProto.WifiLog.WIFI_DISABLED;
    316         mRecordStartTimeSec = mClock.elapsedRealtime() / 1000;
    317     }
    318 
    319     // Values used for indexing SystemStateEntries
    320     private static final int SCREEN_ON = 1;
    321     private static final int SCREEN_OFF = 0;
    322 
    323     /**
    324      * Create a new connection event. Call when wifi attempts to make a new network connection
    325      * If there is a current 'un-ended' connection event, it will be ended with UNKNOWN connectivity
    326      * failure code.
    327      * Gathers and sets the RouterFingerPrint data as well
    328      *
    329      * @param config WifiConfiguration of the config used for the current connection attempt
    330      * @param roamType Roam type that caused connection attempt, see WifiMetricsProto.WifiLog.ROAM_X
    331      */
    332     public void startConnectionEvent(WifiConfiguration config, String targetBSSID, int roamType) {
    333         synchronized (mLock) {
    334             // Check if this is overlapping another current connection event
    335             if (mCurrentConnectionEvent != null) {
    336                 //Is this new Connection Event the same as the current one
    337                 if (mCurrentConnectionEvent.mConfigSsid != null
    338                         && mCurrentConnectionEvent.mConfigBssid != null
    339                         && config != null
    340                         && mCurrentConnectionEvent.mConfigSsid.equals(config.SSID)
    341                         && (mCurrentConnectionEvent.mConfigBssid.equals("any")
    342                         || mCurrentConnectionEvent.mConfigBssid.equals(targetBSSID))) {
    343                     mCurrentConnectionEvent.mConfigBssid = targetBSSID;
    344                     // End Connection Event due to new connection attempt to the same network
    345                     endConnectionEvent(ConnectionEvent.FAILURE_REDUNDANT_CONNECTION_ATTEMPT,
    346                             WifiMetricsProto.ConnectionEvent.HLF_NONE);
    347                 } else {
    348                     // End Connection Event due to new connection attempt to different network
    349                     endConnectionEvent(ConnectionEvent.FAILURE_NEW_CONNECTION_ATTEMPT,
    350                             WifiMetricsProto.ConnectionEvent.HLF_NONE);
    351                 }
    352             }
    353             //If past maximum connection events, start removing the oldest
    354             while(mConnectionEventList.size() >= MAX_CONNECTION_EVENTS) {
    355                 mConnectionEventList.remove(0);
    356             }
    357             mCurrentConnectionEvent = new ConnectionEvent();
    358             mCurrentConnectionEvent.mConnectionEvent.startTimeMillis =
    359                     mClock.currentTimeMillis();
    360             mCurrentConnectionEvent.mConfigBssid = targetBSSID;
    361             mCurrentConnectionEvent.mConnectionEvent.roamType = roamType;
    362             mCurrentConnectionEvent.mRouterFingerPrint.updateFromWifiConfiguration(config);
    363             mCurrentConnectionEvent.mConfigBssid = "any";
    364             mCurrentConnectionEvent.mRealStartTime = mClock.elapsedRealtime();
    365             mCurrentConnectionEvent.mWifiState = mWifiState;
    366             mCurrentConnectionEvent.mScreenOn = mScreenOn;
    367             mConnectionEventList.add(mCurrentConnectionEvent);
    368         }
    369     }
    370 
    371     /**
    372      * set the RoamType of the current ConnectionEvent (if any)
    373      */
    374     public void setConnectionEventRoamType(int roamType) {
    375         synchronized (mLock) {
    376             if (mCurrentConnectionEvent != null) {
    377                 mCurrentConnectionEvent.mConnectionEvent.roamType = roamType;
    378             }
    379         }
    380     }
    381 
    382     /**
    383      * Set AP related metrics from ScanDetail
    384      */
    385     public void setConnectionScanDetail(ScanDetail scanDetail) {
    386         synchronized (mLock) {
    387             if (mCurrentConnectionEvent != null && scanDetail != null) {
    388                 NetworkDetail networkDetail = scanDetail.getNetworkDetail();
    389                 ScanResult scanResult = scanDetail.getScanResult();
    390                 //Ensure that we have a networkDetail, and that it corresponds to the currently
    391                 //tracked connection attempt
    392                 if (networkDetail != null && scanResult != null
    393                         && mCurrentConnectionEvent.mConfigSsid != null
    394                         && mCurrentConnectionEvent.mConfigSsid
    395                         .equals("\"" + networkDetail.getSSID() + "\"")) {
    396                     updateMetricsFromNetworkDetail(networkDetail);
    397                     updateMetricsFromScanResult(scanResult);
    398                 }
    399             }
    400         }
    401     }
    402 
    403     /**
    404      * End a Connection event record. Call when wifi connection attempt succeeds or fails.
    405      * If a Connection event has not been started and is active when .end is called, a new one is
    406      * created with zero duration.
    407      *
    408      * @param level2FailureCode Level 2 failure code returned by supplicant
    409      * @param connectivityFailureCode WifiMetricsProto.ConnectionEvent.HLF_X
    410      */
    411     public void endConnectionEvent(int level2FailureCode, int connectivityFailureCode) {
    412         synchronized (mLock) {
    413             if (mCurrentConnectionEvent != null) {
    414                 boolean result = (level2FailureCode == 1)
    415                         && (connectivityFailureCode == WifiMetricsProto.ConnectionEvent.HLF_NONE);
    416                 mCurrentConnectionEvent.mConnectionEvent.connectionResult = result ? 1 : 0;
    417                 mCurrentConnectionEvent.mRealEndTime = mClock.elapsedRealtime();
    418                 mCurrentConnectionEvent.mConnectionEvent.durationTakenToConnectMillis = (int)
    419                         (mCurrentConnectionEvent.mRealEndTime
    420                         - mCurrentConnectionEvent.mRealStartTime);
    421                 mCurrentConnectionEvent.mConnectionEvent.level2FailureCode = level2FailureCode;
    422                 mCurrentConnectionEvent.mConnectionEvent.connectivityLevelFailureCode =
    423                         connectivityFailureCode;
    424                 // ConnectionEvent already added to ConnectionEvents List. Safe to null current here
    425                 mCurrentConnectionEvent = null;
    426             }
    427         }
    428     }
    429 
    430     /**
    431      * Set ConnectionEvent DTIM Interval (if set), and 802.11 Connection mode, from NetworkDetail
    432      */
    433     private void updateMetricsFromNetworkDetail(NetworkDetail networkDetail) {
    434         int dtimInterval = networkDetail.getDtimInterval();
    435         if (dtimInterval > 0) {
    436             mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.dtim =
    437                     dtimInterval;
    438         }
    439         int connectionWifiMode;
    440         switch (networkDetail.getWifiMode()) {
    441             case InformationElementUtil.WifiMode.MODE_UNDEFINED:
    442                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_UNKNOWN;
    443                 break;
    444             case InformationElementUtil.WifiMode.MODE_11A:
    445                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_A;
    446                 break;
    447             case InformationElementUtil.WifiMode.MODE_11B:
    448                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_B;
    449                 break;
    450             case InformationElementUtil.WifiMode.MODE_11G:
    451                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_G;
    452                 break;
    453             case InformationElementUtil.WifiMode.MODE_11N:
    454                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_N;
    455                 break;
    456             case InformationElementUtil.WifiMode.MODE_11AC  :
    457                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_AC;
    458                 break;
    459             default:
    460                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_OTHER;
    461                 break;
    462         }
    463         mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto
    464                 .routerTechnology = connectionWifiMode;
    465     }
    466 
    467     /**
    468      * Set ConnectionEvent RSSI and authentication type from ScanResult
    469      */
    470     private void updateMetricsFromScanResult(ScanResult scanResult) {
    471         mCurrentConnectionEvent.mConnectionEvent.signalStrength = scanResult.level;
    472         mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication =
    473                 WifiMetricsProto.RouterFingerPrint.AUTH_OPEN;
    474         mCurrentConnectionEvent.mConfigBssid = scanResult.BSSID;
    475         if (scanResult.capabilities != null) {
    476             if (scanResult.capabilities.contains("WEP")) {
    477                 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication =
    478                         WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL;
    479             } else if (scanResult.capabilities.contains("PSK")) {
    480                 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication =
    481                         WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL;
    482             } else if (scanResult.capabilities.contains("EAP")) {
    483                 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication =
    484                         WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE;
    485             }
    486         }
    487         mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.channelInfo =
    488                 scanResult.frequency;
    489     }
    490 
    491     void setNumSavedNetworks(int num) {
    492         synchronized (mLock) {
    493             mWifiLogProto.numSavedNetworks = num;
    494         }
    495     }
    496 
    497     void setNumOpenNetworks(int num) {
    498         synchronized (mLock) {
    499             mWifiLogProto.numOpenNetworks = num;
    500         }
    501     }
    502 
    503     void setNumPersonalNetworks(int num) {
    504         synchronized (mLock) {
    505             mWifiLogProto.numPersonalNetworks = num;
    506         }
    507     }
    508 
    509     void setNumEnterpriseNetworks(int num) {
    510         synchronized (mLock) {
    511             mWifiLogProto.numEnterpriseNetworks = num;
    512         }
    513     }
    514 
    515     void setNumNetworksAddedByUser(int num) {
    516         synchronized (mLock) {
    517             mWifiLogProto.numNetworksAddedByUser = num;
    518         }
    519     }
    520 
    521     void setNumNetworksAddedByApps(int num) {
    522         synchronized (mLock) {
    523             mWifiLogProto.numNetworksAddedByApps = num;
    524         }
    525     }
    526 
    527     void setIsLocationEnabled(boolean enabled) {
    528         synchronized (mLock) {
    529             mWifiLogProto.isLocationEnabled = enabled;
    530         }
    531     }
    532 
    533     void setIsScanningAlwaysEnabled(boolean enabled) {
    534         synchronized (mLock) {
    535             mWifiLogProto.isScanningAlwaysEnabled = enabled;
    536         }
    537     }
    538 
    539     /**
    540      * Increment Non Empty Scan Results count
    541      */
    542     public void incrementNonEmptyScanResultCount() {
    543         if (DBG) Log.v(TAG, "incrementNonEmptyScanResultCount");
    544         synchronized (mLock) {
    545             mWifiLogProto.numNonEmptyScanResults++;
    546         }
    547     }
    548 
    549     /**
    550      * Increment Empty Scan Results count
    551      */
    552     public void incrementEmptyScanResultCount() {
    553         if (DBG) Log.v(TAG, "incrementEmptyScanResultCount");
    554         synchronized (mLock) {
    555             mWifiLogProto.numEmptyScanResults++;
    556         }
    557     }
    558 
    559     /**
    560      * Increment background scan count
    561      */
    562     public void incrementBackgroundScanCount() {
    563         if (DBG) Log.v(TAG, "incrementBackgroundScanCount");
    564         synchronized (mLock) {
    565             mWifiLogProto.numBackgroundScans++;
    566         }
    567     }
    568 
    569    /**
    570      * Get Background scan count
    571      */
    572     public int getBackgroundScanCount() {
    573         synchronized (mLock) {
    574             return mWifiLogProto.numBackgroundScans;
    575         }
    576     }
    577 
    578     /**
    579      * Increment oneshot scan count, and the associated WifiSystemScanStateCount entry
    580      */
    581     public void incrementOneshotScanCount() {
    582         synchronized (mLock) {
    583             mWifiLogProto.numOneshotScans++;
    584         }
    585         incrementWifiSystemScanStateCount(mWifiState, mScreenOn);
    586     }
    587 
    588     /**
    589      * Get oneshot scan count
    590      */
    591     public int getOneshotScanCount() {
    592         synchronized (mLock) {
    593             return mWifiLogProto.numOneshotScans;
    594         }
    595     }
    596 
    597     private String returnCodeToString(int scanReturnCode) {
    598         switch(scanReturnCode){
    599             case WifiMetricsProto.WifiLog.SCAN_UNKNOWN:
    600                 return "SCAN_UNKNOWN";
    601             case WifiMetricsProto.WifiLog.SCAN_SUCCESS:
    602                 return "SCAN_SUCCESS";
    603             case WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED:
    604                 return "SCAN_FAILURE_INTERRUPTED";
    605             case WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION:
    606                 return "SCAN_FAILURE_INVALID_CONFIGURATION";
    607             case WifiMetricsProto.WifiLog.FAILURE_WIFI_DISABLED:
    608                 return "FAILURE_WIFI_DISABLED";
    609             default:
    610                 return "<UNKNOWN>";
    611         }
    612     }
    613 
    614     /**
    615      * Increment count of scan return code occurrence
    616      *
    617      * @param scanReturnCode Return code from scan attempt WifiMetricsProto.WifiLog.SCAN_X
    618      */
    619     public void incrementScanReturnEntry(int scanReturnCode, int countToAdd) {
    620         synchronized (mLock) {
    621             if (DBG) Log.v(TAG, "incrementScanReturnEntry " + returnCodeToString(scanReturnCode));
    622             int entry = mScanReturnEntries.get(scanReturnCode);
    623             entry += countToAdd;
    624             mScanReturnEntries.put(scanReturnCode, entry);
    625         }
    626     }
    627     /**
    628      * Get the count of this scanReturnCode
    629      * @param scanReturnCode that we are getting the count for
    630      */
    631     public int getScanReturnEntry(int scanReturnCode) {
    632         synchronized (mLock) {
    633             return mScanReturnEntries.get(scanReturnCode);
    634         }
    635     }
    636 
    637     private String wifiSystemStateToString(int state) {
    638         switch(state){
    639             case WifiMetricsProto.WifiLog.WIFI_UNKNOWN:
    640                 return "WIFI_UNKNOWN";
    641             case WifiMetricsProto.WifiLog.WIFI_DISABLED:
    642                 return "WIFI_DISABLED";
    643             case WifiMetricsProto.WifiLog.WIFI_DISCONNECTED:
    644                 return "WIFI_DISCONNECTED";
    645             case WifiMetricsProto.WifiLog.WIFI_ASSOCIATED:
    646                 return "WIFI_ASSOCIATED";
    647             default:
    648                 return "default";
    649         }
    650     }
    651 
    652     /**
    653      * Increments the count of scans initiated by each wifi state, accounts for screenOn/Off
    654      *
    655      * @param state State of the system when scan was initiated, see WifiMetricsProto.WifiLog.WIFI_X
    656      * @param screenOn Is the screen on
    657      */
    658     public void incrementWifiSystemScanStateCount(int state, boolean screenOn) {
    659         synchronized (mLock) {
    660             if (DBG) {
    661                 Log.v(TAG, "incrementWifiSystemScanStateCount " + wifiSystemStateToString(state)
    662                         + " " + screenOn);
    663             }
    664             int index = (state * 2) + (screenOn ? SCREEN_ON : SCREEN_OFF);
    665             int entry = mWifiSystemStateEntries.get(index);
    666             entry++;
    667             mWifiSystemStateEntries.put(index, entry);
    668         }
    669     }
    670 
    671     /**
    672      * Get the count of this system State Entry
    673      */
    674     public int getSystemStateCount(int state, boolean screenOn) {
    675         synchronized (mLock) {
    676             int index = state * 2 + (screenOn ? SCREEN_ON : SCREEN_OFF);
    677             return mWifiSystemStateEntries.get(index);
    678         }
    679     }
    680 
    681     /**
    682      * Increment number of times the Watchdog of Last Resort triggered, resetting the wifi stack
    683      */
    684     public void incrementNumLastResortWatchdogTriggers() {
    685         synchronized (mLock) {
    686             mWifiLogProto.numLastResortWatchdogTriggers++;
    687         }
    688     }
    689     /**
    690      * @param count number of networks over bad association threshold when watchdog triggered
    691      */
    692     public void addCountToNumLastResortWatchdogBadAssociationNetworksTotal(int count) {
    693         synchronized (mLock) {
    694             mWifiLogProto.numLastResortWatchdogBadAssociationNetworksTotal += count;
    695         }
    696     }
    697     /**
    698      * @param count number of networks over bad authentication threshold when watchdog triggered
    699      */
    700     public void addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal(int count) {
    701         synchronized (mLock) {
    702             mWifiLogProto.numLastResortWatchdogBadAuthenticationNetworksTotal += count;
    703         }
    704     }
    705     /**
    706      * @param count number of networks over bad dhcp threshold when watchdog triggered
    707      */
    708     public void addCountToNumLastResortWatchdogBadDhcpNetworksTotal(int count) {
    709         synchronized (mLock) {
    710             mWifiLogProto.numLastResortWatchdogBadDhcpNetworksTotal += count;
    711         }
    712     }
    713     /**
    714      * @param count number of networks over bad other threshold when watchdog triggered
    715      */
    716     public void addCountToNumLastResortWatchdogBadOtherNetworksTotal(int count) {
    717         synchronized (mLock) {
    718             mWifiLogProto.numLastResortWatchdogBadOtherNetworksTotal += count;
    719         }
    720     }
    721     /**
    722      * @param count number of networks seen when watchdog triggered
    723      */
    724     public void addCountToNumLastResortWatchdogAvailableNetworksTotal(int count) {
    725         synchronized (mLock) {
    726             mWifiLogProto.numLastResortWatchdogAvailableNetworksTotal += count;
    727         }
    728     }
    729     /**
    730      * Increment count of triggers with atleast one bad association network
    731      */
    732     public void incrementNumLastResortWatchdogTriggersWithBadAssociation() {
    733         synchronized (mLock) {
    734             mWifiLogProto.numLastResortWatchdogTriggersWithBadAssociation++;
    735         }
    736     }
    737     /**
    738      * Increment count of triggers with atleast one bad authentication network
    739      */
    740     public void incrementNumLastResortWatchdogTriggersWithBadAuthentication() {
    741         synchronized (mLock) {
    742             mWifiLogProto.numLastResortWatchdogTriggersWithBadAuthentication++;
    743         }
    744     }
    745     /**
    746      * Increment count of triggers with atleast one bad dhcp network
    747      */
    748     public void incrementNumLastResortWatchdogTriggersWithBadDhcp() {
    749         synchronized (mLock) {
    750             mWifiLogProto.numLastResortWatchdogTriggersWithBadDhcp++;
    751         }
    752     }
    753     /**
    754      * Increment count of triggers with atleast one bad other network
    755      */
    756     public void incrementNumLastResortWatchdogTriggersWithBadOther() {
    757         synchronized (mLock) {
    758             mWifiLogProto.numLastResortWatchdogTriggersWithBadOther++;
    759         }
    760     }
    761 
    762     /**
    763      * Increment number of times connectivity watchdog confirmed pno is working
    764      */
    765     public void incrementNumConnectivityWatchdogPnoGood() {
    766         synchronized (mLock) {
    767             mWifiLogProto.numConnectivityWatchdogPnoGood++;
    768         }
    769     }
    770     /**
    771      * Increment number of times connectivity watchdog found pno not working
    772      */
    773     public void incrementNumConnectivityWatchdogPnoBad() {
    774         synchronized (mLock) {
    775             mWifiLogProto.numConnectivityWatchdogPnoBad++;
    776         }
    777     }
    778     /**
    779      * Increment number of times connectivity watchdog confirmed background scan is working
    780      */
    781     public void incrementNumConnectivityWatchdogBackgroundGood() {
    782         synchronized (mLock) {
    783             mWifiLogProto.numConnectivityWatchdogBackgroundGood++;
    784         }
    785     }
    786     /**
    787      * Increment number of times connectivity watchdog found background scan not working
    788      */
    789     public void incrementNumConnectivityWatchdogBackgroundBad() {
    790         synchronized (mLock) {
    791             mWifiLogProto.numConnectivityWatchdogBackgroundBad++;
    792         }
    793     }
    794 
    795     /**
    796      * Increment occurence count of RSSI level from RSSI poll.
    797      * Ignores rssi values outside the bounds of [MIN_RSSI_POLL, MAX_RSSI_POLL]
    798      */
    799     public void incrementRssiPollRssiCount(int rssi) {
    800         if (!(rssi >= MIN_RSSI_POLL && rssi <= MAX_RSSI_POLL)) {
    801             return;
    802         }
    803         synchronized (mLock) {
    804             int count = mRssiPollCounts.get(rssi);
    805             mRssiPollCounts.put(rssi, count + 1);
    806         }
    807     }
    808 
    809     public static final String PROTO_DUMP_ARG = "wifiMetricsProto";
    810     /**
    811      * Dump all WifiMetrics. Collects some metrics from ConfigStore, Settings and WifiManager
    812      * at this time
    813      *
    814      * @param fd unused
    815      * @param pw PrintWriter for writing dump to
    816      * @param args unused
    817      */
    818     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    819         synchronized (mLock) {
    820             pw.println("WifiMetrics:");
    821             if (args.length > 0 && PROTO_DUMP_ARG.equals(args[0])) {
    822                 //Dump serialized WifiLog proto
    823                 consolidateProto(true);
    824                 for (ConnectionEvent event : mConnectionEventList) {
    825                     if (mCurrentConnectionEvent != event) {
    826                         //indicate that automatic bug report has been taken for all valid
    827                         //connection events
    828                         event.mConnectionEvent.automaticBugReportTaken = true;
    829                     }
    830                 }
    831                 byte[] wifiMetricsProto = WifiMetricsProto.WifiLog.toByteArray(mWifiLogProto);
    832                 String metricsProtoDump = Base64.encodeToString(wifiMetricsProto, Base64.DEFAULT);
    833                 pw.println(metricsProtoDump);
    834                 pw.println("EndWifiMetrics");
    835                 clear();
    836             } else {
    837                 pw.println("mConnectionEvents:");
    838                 for (ConnectionEvent event : mConnectionEventList) {
    839                     String eventLine = event.toString();
    840                     if (event == mCurrentConnectionEvent) {
    841                         eventLine += "CURRENTLY OPEN EVENT";
    842                     }
    843                     pw.println(eventLine);
    844                 }
    845                 pw.println("mWifiLogProto.numSavedNetworks=" + mWifiLogProto.numSavedNetworks);
    846                 pw.println("mWifiLogProto.numOpenNetworks=" + mWifiLogProto.numOpenNetworks);
    847                 pw.println("mWifiLogProto.numPersonalNetworks="
    848                         + mWifiLogProto.numPersonalNetworks);
    849                 pw.println("mWifiLogProto.numEnterpriseNetworks="
    850                         + mWifiLogProto.numEnterpriseNetworks);
    851                 pw.println("mWifiLogProto.isLocationEnabled=" + mWifiLogProto.isLocationEnabled);
    852                 pw.println("mWifiLogProto.isScanningAlwaysEnabled="
    853                         + mWifiLogProto.isScanningAlwaysEnabled);
    854                 pw.println("mWifiLogProto.numNetworksAddedByUser="
    855                         + mWifiLogProto.numNetworksAddedByUser);
    856                 pw.println("mWifiLogProto.numNetworksAddedByApps="
    857                         + mWifiLogProto.numNetworksAddedByApps);
    858                 pw.println("mWifiLogProto.numNonEmptyScanResults="
    859                         + mWifiLogProto.numNonEmptyScanResults);
    860                 pw.println("mWifiLogProto.numEmptyScanResults="
    861                         + mWifiLogProto.numEmptyScanResults);
    862                 pw.println("mWifiLogProto.numOneshotScans="
    863                         + mWifiLogProto.numOneshotScans);
    864                 pw.println("mWifiLogProto.numBackgroundScans="
    865                         + mWifiLogProto.numBackgroundScans);
    866 
    867                 pw.println("mScanReturnEntries:");
    868                 pw.println("  SCAN_UNKNOWN: " + getScanReturnEntry(
    869                         WifiMetricsProto.WifiLog.SCAN_UNKNOWN));
    870                 pw.println("  SCAN_SUCCESS: " + getScanReturnEntry(
    871                         WifiMetricsProto.WifiLog.SCAN_SUCCESS));
    872                 pw.println("  SCAN_FAILURE_INTERRUPTED: " + getScanReturnEntry(
    873                         WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED));
    874                 pw.println("  SCAN_FAILURE_INVALID_CONFIGURATION: " + getScanReturnEntry(
    875                         WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION));
    876                 pw.println("  FAILURE_WIFI_DISABLED: " + getScanReturnEntry(
    877                         WifiMetricsProto.WifiLog.FAILURE_WIFI_DISABLED));
    878 
    879                 pw.println("mSystemStateEntries: <state><screenOn> : <scansInitiated>");
    880                 pw.println("  WIFI_UNKNOWN       ON: "
    881                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, true));
    882                 pw.println("  WIFI_DISABLED      ON: "
    883                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISABLED, true));
    884                 pw.println("  WIFI_DISCONNECTED  ON: "
    885                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED, true));
    886                 pw.println("  WIFI_ASSOCIATED    ON: "
    887                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, true));
    888                 pw.println("  WIFI_UNKNOWN      OFF: "
    889                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, false));
    890                 pw.println("  WIFI_DISABLED     OFF: "
    891                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISABLED, false));
    892                 pw.println("  WIFI_DISCONNECTED OFF: "
    893                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED, false));
    894                 pw.println("  WIFI_ASSOCIATED   OFF: "
    895                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, false));
    896                 pw.println("mWifiLogProto.numConnectivityWatchdogPnoGood="
    897                         + mWifiLogProto.numConnectivityWatchdogPnoGood);
    898                 pw.println("mWifiLogProto.numConnectivityWatchdogPnoBad="
    899                         + mWifiLogProto.numConnectivityWatchdogPnoBad);
    900                 pw.println("mWifiLogProto.numConnectivityWatchdogBackgroundGood="
    901                         + mWifiLogProto.numConnectivityWatchdogBackgroundGood);
    902                 pw.println("mWifiLogProto.numConnectivityWatchdogBackgroundBad="
    903                         + mWifiLogProto.numConnectivityWatchdogBackgroundBad);
    904                 pw.println("mWifiLogProto.numLastResortWatchdogTriggers="
    905                         + mWifiLogProto.numLastResortWatchdogTriggers);
    906                 pw.println("mWifiLogProto.numLastResortWatchdogBadAssociationNetworksTotal="
    907                         + mWifiLogProto.numLastResortWatchdogBadAssociationNetworksTotal);
    908                 pw.println("mWifiLogProto.numLastResortWatchdogBadAuthenticationNetworksTotal="
    909                         + mWifiLogProto.numLastResortWatchdogBadAuthenticationNetworksTotal);
    910                 pw.println("mWifiLogProto.numLastResortWatchdogBadDhcpNetworksTotal="
    911                         + mWifiLogProto.numLastResortWatchdogBadDhcpNetworksTotal);
    912                 pw.println("mWifiLogProto.numLastResortWatchdogBadOtherNetworksTotal="
    913                         + mWifiLogProto.numLastResortWatchdogBadOtherNetworksTotal);
    914                 pw.println("mWifiLogProto.numLastResortWatchdogAvailableNetworksTotal="
    915                         + mWifiLogProto.numLastResortWatchdogAvailableNetworksTotal);
    916                 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadAssociation="
    917                         + mWifiLogProto.numLastResortWatchdogTriggersWithBadAssociation);
    918                 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadAuthentication="
    919                         + mWifiLogProto.numLastResortWatchdogTriggersWithBadAuthentication);
    920                 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadDhcp="
    921                         + mWifiLogProto.numLastResortWatchdogTriggersWithBadDhcp);
    922                 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadOther="
    923                         + mWifiLogProto.numLastResortWatchdogTriggersWithBadOther);
    924                 pw.println("mWifiLogProto.recordDurationSec="
    925                         + ((mClock.elapsedRealtime() / 1000) - mRecordStartTimeSec));
    926                 pw.println("mWifiLogProto.rssiPollRssiCount: Printing counts for [" + MIN_RSSI_POLL
    927                         + ", " + MAX_RSSI_POLL + "]");
    928                 StringBuilder sb = new StringBuilder();
    929                 for (int i = MIN_RSSI_POLL; i <= MAX_RSSI_POLL; i++) {
    930                     sb.append(mRssiPollCounts.get(i) + " ");
    931                 }
    932                 pw.println("  " + sb.toString());
    933             }
    934         }
    935     }
    936 
    937     /**
    938      * append the separate ConnectionEvent, SystemStateEntry and ScanReturnCode collections to their
    939      * respective lists within mWifiLogProto
    940      *
    941      * @param incremental Only include ConnectionEvents created since last automatic bug report
    942      */
    943     private void consolidateProto(boolean incremental) {
    944         List<WifiMetricsProto.ConnectionEvent> events = new ArrayList<>();
    945         List<WifiMetricsProto.RssiPollCount> rssis = new ArrayList<>();
    946         synchronized (mLock) {
    947             for (ConnectionEvent event : mConnectionEventList) {
    948                 // If this is not incremental, dump full ConnectionEvent list
    949                 // Else Dump all un-dumped events except for the current one
    950                 if (!incremental || ((mCurrentConnectionEvent != event)
    951                         && !event.mConnectionEvent.automaticBugReportTaken)) {
    952                     //Get all ConnectionEvents that haven not been dumped as a proto, also exclude
    953                     //the current active un-ended connection event
    954                     events.add(event.mConnectionEvent);
    955                     if (incremental) {
    956                         event.mConnectionEvent.automaticBugReportTaken = true;
    957                     }
    958                 }
    959             }
    960             if (events.size() > 0) {
    961                 mWifiLogProto.connectionEvent = events.toArray(mWifiLogProto.connectionEvent);
    962             }
    963 
    964             //Convert the SparseIntArray of scanReturnEntry integers into ScanReturnEntry proto list
    965             mWifiLogProto.scanReturnEntries =
    966                     new WifiMetricsProto.WifiLog.ScanReturnEntry[mScanReturnEntries.size()];
    967             for (int i = 0; i < mScanReturnEntries.size(); i++) {
    968                 mWifiLogProto.scanReturnEntries[i] = new WifiMetricsProto.WifiLog.ScanReturnEntry();
    969                 mWifiLogProto.scanReturnEntries[i].scanReturnCode = mScanReturnEntries.keyAt(i);
    970                 mWifiLogProto.scanReturnEntries[i].scanResultsCount = mScanReturnEntries.valueAt(i);
    971             }
    972 
    973             // Convert the SparseIntArray of systemStateEntry into WifiSystemStateEntry proto list
    974             // This one is slightly more complex, as the Sparse are indexed with:
    975             //     key: wifiState * 2 + isScreenOn, value: wifiStateCount
    976             mWifiLogProto.wifiSystemStateEntries =
    977                     new WifiMetricsProto.WifiLog
    978                     .WifiSystemStateEntry[mWifiSystemStateEntries.size()];
    979             for (int i = 0; i < mWifiSystemStateEntries.size(); i++) {
    980                 mWifiLogProto.wifiSystemStateEntries[i] =
    981                         new WifiMetricsProto.WifiLog.WifiSystemStateEntry();
    982                 mWifiLogProto.wifiSystemStateEntries[i].wifiState =
    983                         mWifiSystemStateEntries.keyAt(i) / 2;
    984                 mWifiLogProto.wifiSystemStateEntries[i].wifiStateCount =
    985                         mWifiSystemStateEntries.valueAt(i);
    986                 mWifiLogProto.wifiSystemStateEntries[i].isScreenOn =
    987                         (mWifiSystemStateEntries.keyAt(i) % 2) > 0;
    988             }
    989             mWifiLogProto.recordDurationSec = (int) ((mClock.elapsedRealtime() / 1000)
    990                     - mRecordStartTimeSec);
    991 
    992             /**
    993              * Convert the SparseIntArray of RSSI poll rssi's and counts to the proto's repeated
    994              * IntKeyVal array.
    995              */
    996             for (int i = 0; i < mRssiPollCounts.size(); i++) {
    997                 WifiMetricsProto.RssiPollCount keyVal = new WifiMetricsProto.RssiPollCount();
    998                 keyVal.rssi = mRssiPollCounts.keyAt(i);
    999                 keyVal.count = mRssiPollCounts.valueAt(i);
   1000                 rssis.add(keyVal);
   1001             }
   1002             mWifiLogProto.rssiPollRssiCount = rssis.toArray(mWifiLogProto.rssiPollRssiCount);
   1003         }
   1004     }
   1005 
   1006     /**
   1007      * Clear all WifiMetrics, except for currentConnectionEvent.
   1008      */
   1009     private void clear() {
   1010         synchronized (mLock) {
   1011             mConnectionEventList.clear();
   1012             if (mCurrentConnectionEvent != null) {
   1013                 mConnectionEventList.add(mCurrentConnectionEvent);
   1014             }
   1015             mScanReturnEntries.clear();
   1016             mWifiSystemStateEntries.clear();
   1017             mRecordStartTimeSec = mClock.elapsedRealtime() / 1000;
   1018             mRssiPollCounts.clear();
   1019             mWifiLogProto.clear();
   1020         }
   1021     }
   1022 
   1023     /**
   1024      *  Set screen state (On/Off)
   1025      */
   1026     public void setScreenState(boolean screenOn) {
   1027         synchronized (mLock) {
   1028             mScreenOn = screenOn;
   1029         }
   1030     }
   1031 
   1032     /**
   1033      *  Set wifi state (WIFI_UNKNOWN, WIFI_DISABLED, WIFI_DISCONNECTED, WIFI_ASSOCIATED)
   1034      */
   1035     public void setWifiState(int wifiState) {
   1036         synchronized (mLock) {
   1037             mWifiState = wifiState;
   1038         }
   1039     }
   1040 }
   1041