• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
RouterFingerPrint()88         RouterFingerPrint() {
89             mRouterFingerPrintProto = new WifiMetricsProto.RouterFingerPrint();
90         }
91 
toString()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         }
updateFromWifiConfiguration(WifiConfiguration config)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 
ConnectionEvent()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 
toString()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 
WifiMetrics(Clock clock)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      */
startConnectionEvent(WifiConfiguration config, String targetBSSID, int roamType)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      */
setConnectionEventRoamType(int roamType)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      */
setConnectionScanDetail(ScanDetail scanDetail)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      */
endConnectionEvent(int level2FailureCode, int connectivityFailureCode)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      */
updateMetricsFromNetworkDetail(NetworkDetail networkDetail)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      */
updateMetricsFromScanResult(ScanResult scanResult)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 
setNumSavedNetworks(int num)491     void setNumSavedNetworks(int num) {
492         synchronized (mLock) {
493             mWifiLogProto.numSavedNetworks = num;
494         }
495     }
496 
setNumOpenNetworks(int num)497     void setNumOpenNetworks(int num) {
498         synchronized (mLock) {
499             mWifiLogProto.numOpenNetworks = num;
500         }
501     }
502 
setNumPersonalNetworks(int num)503     void setNumPersonalNetworks(int num) {
504         synchronized (mLock) {
505             mWifiLogProto.numPersonalNetworks = num;
506         }
507     }
508 
setNumEnterpriseNetworks(int num)509     void setNumEnterpriseNetworks(int num) {
510         synchronized (mLock) {
511             mWifiLogProto.numEnterpriseNetworks = num;
512         }
513     }
514 
setNumNetworksAddedByUser(int num)515     void setNumNetworksAddedByUser(int num) {
516         synchronized (mLock) {
517             mWifiLogProto.numNetworksAddedByUser = num;
518         }
519     }
520 
setNumNetworksAddedByApps(int num)521     void setNumNetworksAddedByApps(int num) {
522         synchronized (mLock) {
523             mWifiLogProto.numNetworksAddedByApps = num;
524         }
525     }
526 
setIsLocationEnabled(boolean enabled)527     void setIsLocationEnabled(boolean enabled) {
528         synchronized (mLock) {
529             mWifiLogProto.isLocationEnabled = enabled;
530         }
531     }
532 
setIsScanningAlwaysEnabled(boolean enabled)533     void setIsScanningAlwaysEnabled(boolean enabled) {
534         synchronized (mLock) {
535             mWifiLogProto.isScanningAlwaysEnabled = enabled;
536         }
537     }
538 
539     /**
540      * Increment Non Empty Scan Results count
541      */
incrementNonEmptyScanResultCount()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      */
incrementEmptyScanResultCount()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      */
incrementBackgroundScanCount()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      */
getBackgroundScanCount()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      */
incrementOneshotScanCount()581     public void incrementOneshotScanCount() {
582         synchronized (mLock) {
583             mWifiLogProto.numOneshotScans++;
584         }
585         incrementWifiSystemScanStateCount(mWifiState, mScreenOn);
586     }
587 
588     /**
589      * Get oneshot scan count
590      */
getOneshotScanCount()591     public int getOneshotScanCount() {
592         synchronized (mLock) {
593             return mWifiLogProto.numOneshotScans;
594         }
595     }
596 
returnCodeToString(int scanReturnCode)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      */
incrementScanReturnEntry(int scanReturnCode, int countToAdd)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      */
getScanReturnEntry(int scanReturnCode)631     public int getScanReturnEntry(int scanReturnCode) {
632         synchronized (mLock) {
633             return mScanReturnEntries.get(scanReturnCode);
634         }
635     }
636 
wifiSystemStateToString(int state)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      */
incrementWifiSystemScanStateCount(int state, boolean screenOn)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      */
getSystemStateCount(int state, boolean screenOn)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      */
incrementNumLastResortWatchdogTriggers()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      */
addCountToNumLastResortWatchdogBadAssociationNetworksTotal(int count)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      */
addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal(int count)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      */
addCountToNumLastResortWatchdogBadDhcpNetworksTotal(int count)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      */
addCountToNumLastResortWatchdogBadOtherNetworksTotal(int count)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      */
addCountToNumLastResortWatchdogAvailableNetworksTotal(int count)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      */
incrementNumLastResortWatchdogTriggersWithBadAssociation()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      */
incrementNumLastResortWatchdogTriggersWithBadAuthentication()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      */
incrementNumLastResortWatchdogTriggersWithBadDhcp()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      */
incrementNumLastResortWatchdogTriggersWithBadOther()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      */
incrementNumConnectivityWatchdogPnoGood()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      */
incrementNumConnectivityWatchdogPnoBad()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      */
incrementNumConnectivityWatchdogBackgroundGood()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      */
incrementNumConnectivityWatchdogBackgroundBad()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      */
incrementRssiPollRssiCount(int rssi)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      */
dump(FileDescriptor fd, PrintWriter pw, String[] args)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      */
consolidateProto(boolean incremental)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      */
clear()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      */
setScreenState(boolean screenOn)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      */
setWifiState(int wifiState)1035     public void setWifiState(int wifiState) {
1036         synchronized (mLock) {
1037             mWifiState = wifiState;
1038         }
1039     }
1040 }
1041