WifiMetrics.java revision 2b152feb1c574f30557581770d4f8c06c770ba34
11b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne/*
21b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne * Copyright (C) 2016 The Android Open Source Project
31b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne *
41b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne * Licensed under the Apache License, Version 2.0 (the "License");
51b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne * you may not use this file except in compliance with the License.
61b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne * You may obtain a copy of the License at
71b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne *
81b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne *      http://www.apache.org/licenses/LICENSE-2.0
91b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne *
101b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne * Unless required by applicable law or agreed to in writing, software
111b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne * distributed under the License is distributed on an "AS IS" BASIS,
121b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne * See the License for the specific language governing permissions and
141b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne * limitations under the License.
151b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne */
161b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
171b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhnepackage com.android.server.wifi;
181b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
194dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhneimport android.net.wifi.ScanResult;
202532a24b254d724a9b6771d327dc410b32b18602Glen Kuhneimport android.net.wifi.WifiConfiguration;
211b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhneimport android.os.SystemClock;
221b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhneimport android.util.Base64;
231b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhneimport android.util.SparseArray;
241b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
25f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhneimport com.android.server.wifi.hotspot2.NetworkDetail;
26f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhneimport com.android.server.wifi.util.InformationElementUtil;
27f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne
281b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhneimport java.io.FileDescriptor;
291b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhneimport java.io.PrintWriter;
301b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhneimport java.util.ArrayList;
311b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhneimport java.util.Calendar;
321b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhneimport java.util.List;
331b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
341b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne/**
351b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne * Provides storage for wireless connectivity metrics, as they are generated.
361b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne * Metrics logged by this class include:
371b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne *   Aggregated connection stats (num of connections, num of failures, ...)
381b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne *   Discrete connection event stats (time, duration, failure codes, ...)
391b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne *   Router details (technology type, authentication type, ...)
401b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne *   Scan stats
411b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne */
421b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhnepublic class WifiMetrics {
431b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    private static final String TAG = "WifiMetrics";
441b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    private final Object mLock = new Object();
452532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne    private static final int MAX_CONNECTION_EVENTS = 256;
461b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    /**
471b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * Metrics are stored within an instance of the WifiLog proto during runtime,
481b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * The ConnectionEvent, SystemStateEntries & ScanReturnEntries metrics are stored during
491b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * runtime in member lists of this WifiMetrics class, with the final WifiLog proto being pieced
501b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * together at dump-time
511b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     */
521b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    private final WifiMetricsProto.WifiLog mWifiLogProto;
531b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    /**
541b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * Session information that gets logged for every Wifi connection attempt.
551b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     */
561b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    private final List<ConnectionEvent> mConnectionEventList;
571b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    /**
581b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * The latest started (but un-ended) connection attempt
591b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     */
601b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    private ConnectionEvent mCurrentConnectionEvent;
611b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    /**
621b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * Count of number of times each scan return code, indexed by WifiLog.ScanReturnCode
631b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     */
641b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    private final SparseArray<WifiMetricsProto.WifiLog.ScanReturnEntry> mScanReturnEntries;
651b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    /**
661b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * Mapping of system state to the counts of scans requested in that wifi state * screenOn
671b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * combination. Indexed by WifiLog.WifiState * (1 + screenOn)
681b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     */
691b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    private final SparseArray<WifiMetricsProto.WifiLog.WifiSystemStateEntry>
701b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            mWifiSystemStateEntries;
711b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
721b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    class RouterFingerPrint {
731b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        private WifiMetricsProto.RouterFingerPrint mRouterFingerPrintProto;
742532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        RouterFingerPrint() {
751b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            mRouterFingerPrintProto = new WifiMetricsProto.RouterFingerPrint();
761b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
771b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
781b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        public String toString() {
791b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            StringBuilder sb = new StringBuilder();
801b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            synchronized (mLock) {
811b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                sb.append("mConnectionEvent.roamType=" + mRouterFingerPrintProto.roamType);
821b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                sb.append(", mChannelInfo=" + mRouterFingerPrintProto.channelInfo);
831b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                sb.append(", mDtim=" + mRouterFingerPrintProto.dtim);
841b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                sb.append(", mAuthentication=" + mRouterFingerPrintProto.authentication);
851b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                sb.append(", mHidden=" + mRouterFingerPrintProto.hidden);
861b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                sb.append(", mRouterTechnology=" + mRouterFingerPrintProto.routerTechnology);
871b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                sb.append(", mSupportsIpv6=" + mRouterFingerPrintProto.supportsIpv6);
881b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            }
891b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            return sb.toString();
901b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
912532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        public void updateFromWifiConfiguration(WifiConfiguration config) {
922532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne            if (config != null) {
932532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                /*<TODO>
942532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                mRouterFingerPrintProto.roamType
952532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                mRouterFingerPrintProto.supportsIpv6
962532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                */
972532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                mRouterFingerPrintProto.hidden = config.hiddenSSID;
982532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                mRouterFingerPrintProto.channelInfo = config.apChannel;
99947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne                // Config may not have a valid dtimInterval set yet, in which case dtim will be zero
100947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne                // (These are only populated from beacon frame scan results, which are returned as
101947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne                // scan results from the chip far less frequently than Probe-responses)
102947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne                if (config.dtimInterval > 0) {
103947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne                    mRouterFingerPrintProto.dtim = config.dtimInterval;
104947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne                }
1052532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne            }
1062532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        }
1071b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
1081b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
1091b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    /**
1101b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * Log event, tracking the start time, end time and result of a wireless connection attempt.
1111b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     */
1121b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    class ConnectionEvent {
1131b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        WifiMetricsProto.ConnectionEvent mConnectionEvent;
1142532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        //<TODO> Move these constants into a wifi.proto Enum
1152532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        // Level 2 Failure Codes
1162532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        // Failure is unknown
1172532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        public static final int LLF_UNKNOWN = 0;
1182532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        // NONE
1192532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        public static final int LLF_NONE = 1;
1202532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        // ASSOCIATION_REJECTION_EVENT
1212532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        public static final int LLF_ASSOCIATION_REJECTION = 2;
1222532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        // AUTHENTICATION_FAILURE_EVENT
1232532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        public static final int LLF_AUTHENTICATION_FAILURE = 3;
1242532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        // SSID_TEMP_DISABLED (Also Auth failure)
1252532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        public static final int LLF_SSID_TEMP_DISABLED = 4;
1264dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne        // reconnect() or reassociate() call to WifiNative failed
1272532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        public static final int LLF_CONNECT_NETWORK_FAILED = 5;
1282532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        // NETWORK_DISCONNECTION_EVENT
1292532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        public static final int LLF_NETWORK_DISCONNECTION = 6;
1304dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne        // NEW_CONNECTION_ATTEMPT before previous finished
1314dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne        public static final int LLF_NEW_CONNECTION_ATTEMPT = 7;
1324dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne        RouterFingerPrint mRouterFingerPrint;
1334dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne        private long mRealStartTime;
1344dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne        private long mRealEndTime;
1354dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne        private String mConfigSsid;
1364dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne        private String mConfigBssid;
1372532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne
1381b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        private ConnectionEvent() {
1391b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            mConnectionEvent = new WifiMetricsProto.ConnectionEvent();
140947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne            mRealEndTime = 0;
141947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne            mRealStartTime = 0;
1422532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne            mRouterFingerPrint = new RouterFingerPrint();
1432532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne            mConnectionEvent.routerFingerprint = mRouterFingerPrint.mRouterFingerPrintProto;
1444dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne            mConfigSsid = "<NULL>";
1454dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne            mConfigBssid = "<NULL>";
1461b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
1471b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
1481b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        public String toString() {
1491b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            StringBuilder sb = new StringBuilder();
1501b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            sb.append("startTime=");
1511b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            Calendar c = Calendar.getInstance();
1521b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            synchronized (mLock) {
1531b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                c.setTimeInMillis(mConnectionEvent.startTimeMillis);
1541b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                sb.append(mConnectionEvent.startTimeMillis == 0 ? "            <null>" :
1551b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                        String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c));
1564dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                sb.append(", SSID=");
1574dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                sb.append(mConfigSsid);
1584dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                sb.append(", BSSID=");
1594dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                sb.append(mConfigBssid);
1604dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                sb.append(", durationMillis=");
1611b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                sb.append(mConnectionEvent.durationTakenToConnectMillis);
1622532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                sb.append(", roamType=");
1634dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                switch(mConnectionEvent.roamType) {
1642532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                    case 1:
1652532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                        sb.append("ROAM_NONE");
1662532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                        break;
1672532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                    case 2:
1682532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                        sb.append("ROAM_DBDC");
1692532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                        break;
1702532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                    case 3:
1712532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                        sb.append("ROAM_ENTERPRISE");
1722532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                        break;
1732532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                    case 4:
1742532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                        sb.append("ROAM_USER_SELECTED");
1752532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                        break;
1762532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                    case 5:
1772532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                        sb.append("ROAM_UNRELATED");
1782532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                        break;
1792532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                    default:
1802532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                        sb.append("ROAM_UNKNOWN");
1812532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                }
1824dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                sb.append(", connectionResult=");
1834dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                sb.append(mConnectionEvent.connectionResult);
1841b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                sb.append(", level2FailureCode=");
1854dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                switch(mConnectionEvent.level2FailureCode) {
1864dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                    case LLF_NONE:
1874dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        sb.append("NONE");
1884dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        break;
1894dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                    case LLF_ASSOCIATION_REJECTION:
1904dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        sb.append("ASSOCIATION_REJECTION");
1914dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        break;
1924dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                    case LLF_AUTHENTICATION_FAILURE:
1934dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        sb.append("AUTHENTICATION_FAILURE");
1944dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        break;
1954dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                    case LLF_SSID_TEMP_DISABLED:
1964dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        sb.append("SSID_TEMP_DISABLED");
1974dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        break;
1984dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                    case LLF_CONNECT_NETWORK_FAILED:
1994dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        sb.append("CONNECT_NETWORK_FAILED");
2004dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        break;
2014dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                    case LLF_NETWORK_DISCONNECTION:
2024dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        sb.append("NETWORK_DISCONNECTION");
2034dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        break;
2044dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                    case LLF_NEW_CONNECTION_ATTEMPT:
2054dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        sb.append("NEW_CONNECTION_ATTEMPT");
2064dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        break;
2074dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                    default:
2084dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        sb.append("UNKNOWN");
2094dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        break;
2104dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                }
2111b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                sb.append(", connectivityLevelFailureCode=");
2124dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                switch(mConnectionEvent.connectivityLevelFailureCode) {
2134dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                    case WifiMetricsProto.ConnectionEvent.HLF_NONE:
2144dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        sb.append("NONE");
2154dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        break;
2164dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                    case WifiMetricsProto.ConnectionEvent.HLF_DHCP:
2174dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        sb.append("DHCP");
2184dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        break;
2194dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                    case WifiMetricsProto.ConnectionEvent.HLF_NO_INTERNET:
2204dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        sb.append("NO_INTERNET");
2214dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        break;
2224dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                    case WifiMetricsProto.ConnectionEvent.HLF_UNWANTED:
2234dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        sb.append("UNWANTED");
2244dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        break;
2254dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                    default:
2264dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        sb.append("UNKNOWN");
2274dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                        break;
2284dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                }
2294dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                sb.append(", signalStrength=");
2304dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                sb.append(mConnectionEvent.signalStrength);
2311b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                sb.append("\n  ");
2322532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                sb.append("mRouterFingerprint: ");
2331b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                sb.append(mRouterFingerPrint.toString());
2341b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            }
2351b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            return sb.toString();
2361b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
2371b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
2381b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
2391b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    public WifiMetrics() {
2401b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        mWifiLogProto = new WifiMetricsProto.WifiLog();
2411b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        mConnectionEventList = new ArrayList<>();
2421b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        mCurrentConnectionEvent = null;
2431b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        mScanReturnEntries = new SparseArray<WifiMetricsProto.WifiLog.ScanReturnEntry>();
2441b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        mWifiSystemStateEntries = new SparseArray<WifiMetricsProto.WifiLog.WifiSystemStateEntry>();
2451b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
2461b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
2471b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    /**
2481b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * Create a new connection event. Call when wifi attempts to make a new network connection
2491b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * If there is a current 'un-ended' connection event, it will be ended with UNKNOWN connectivity
2501b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * failure code.
2511b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * Gathers and sets the RouterFingerPrint data as well
2521b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     *
253947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne     * @param config WifiConfiguration of the config used for the current connection attempt
2541b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * @param roamType Roam type that caused connection attempt, see WifiMetricsProto.WifiLog.ROAM_X
2551b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     */
2564dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne    public void startConnectionEvent(WifiConfiguration config, int roamType) {
2574dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne        if (mCurrentConnectionEvent != null) {
2584dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne            endConnectionEvent(ConnectionEvent.LLF_NEW_CONNECTION_ATTEMPT,
2594dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                    WifiMetricsProto.ConnectionEvent.HLF_NONE);
2604dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne        }
2611b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        synchronized (mLock) {
2624dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne            //If at maximum connection events, start removing the oldest
2634dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne            while(mConnectionEventList.size() >= MAX_CONNECTION_EVENTS) {
2644dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                mConnectionEventList.remove(0);
2654dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne            }
2664dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne            mCurrentConnectionEvent = new ConnectionEvent();
2674dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne            mCurrentConnectionEvent.mConnectionEvent.startTimeMillis =
2684dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                    System.currentTimeMillis();
2694dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne            mCurrentConnectionEvent.mConnectionEvent.roamType = roamType;
2704dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne            mCurrentConnectionEvent.mRouterFingerPrint.updateFromWifiConfiguration(config);
2714dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne            if (config != null) {
2724dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                ScanResult candidate = config.getNetworkSelectionStatus().getCandidate();
2734dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                if (candidate != null) {
2742b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                    updateMetricsFromScanResult(candidate);
2752532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                }
2764dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                mCurrentConnectionEvent.mConfigSsid = config.SSID;
2774dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne                mCurrentConnectionEvent.mConfigBssid = config.BSSID;
2781b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            }
2794dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne            mCurrentConnectionEvent.mRealStartTime = SystemClock.elapsedRealtime();
2804dead162c5336443e9d7b3deae5eb26b07d39254Glen Kuhne            mConnectionEventList.add(mCurrentConnectionEvent);
2811b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
2821b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
2831b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
2841b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    /**
2852532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne     * set the RoamType of the current ConnectionEvent (if any)
2862532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne     */
2872532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne    public void setConnectionEventRoamType(int roamType) {
2882532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        if (mCurrentConnectionEvent != null) {
2892532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne            mCurrentConnectionEvent.mConnectionEvent.roamType = roamType;
2902532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        }
2912532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne    }
292f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne
293f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne    /**
294f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne     * Set AP related metrics from ScanDetail
295f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne     */
296f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne    public void setConnectionScanDetail(ScanDetail scanDetail) {
297f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne        if (mCurrentConnectionEvent != null && scanDetail != null) {
298f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne            NetworkDetail networkDetail = scanDetail.getNetworkDetail();
299f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne            ScanResult scanResult = scanDetail.getScanResult();
300f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne            //Ensure that we have a networkDetail, and that it corresponds to the currently
301f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne            //tracked connection attempt
302f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne            if (networkDetail != null && scanResult != null
303f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    && mCurrentConnectionEvent.mConfigSsid != null
304f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    && mCurrentConnectionEvent.mConfigSsid
305f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    .equals("\"" + networkDetail.getSSID() + "\"")) {
3062b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                updateMetricsFromNetworkDetail(networkDetail);
3072b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                updateMetricsFromScanResult(scanResult);
308f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne            }
309f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne        }
310f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne    }
311f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne
3122532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne    /**
3131b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * End a Connection event record. Call when wifi connection attempt succeeds or fails.
3141b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * If a Connection event has not been started and is active when .end is called, a new one is
3151b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * created with zero duration.
3161b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     *
3171b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * @param level2FailureCode Level 2 failure code returned by supplicant
3181b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * @param connectivityFailureCode WifiMetricsProto.ConnectionEvent.HLF_X
3191b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     */
3201b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    public void endConnectionEvent(int level2FailureCode, int connectivityFailureCode) {
3211b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        synchronized (mLock) {
3222532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne            if (mCurrentConnectionEvent != null) {
3232532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                boolean result = (level2FailureCode == 1)
3242532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                        && (connectivityFailureCode == WifiMetricsProto.ConnectionEvent.HLF_NONE);
3252532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                mCurrentConnectionEvent.mConnectionEvent.connectionResult = result ? 1 : 0;
3262532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                mCurrentConnectionEvent.mRealEndTime = SystemClock.elapsedRealtime();
3272532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                mCurrentConnectionEvent.mConnectionEvent.durationTakenToConnectMillis = (int)
3282532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                        (mCurrentConnectionEvent.mRealEndTime
3292532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                        - mCurrentConnectionEvent.mRealStartTime);
3302532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                mCurrentConnectionEvent.mConnectionEvent.level2FailureCode = level2FailureCode;
3312532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                mCurrentConnectionEvent.mConnectionEvent.connectivityLevelFailureCode =
3322532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                        connectivityFailureCode;
333f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                // ConnectionEvent already added to ConnectionEvents List. Safe to null current here
3342532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                mCurrentConnectionEvent = null;
3351b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            }
3361b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
3371b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
3381b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
3392b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne    /**
3402b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne     * Set ConnectionEvent DTIM Interval (if set), and 802.11 Connection mode, from NetworkDetail
3412b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne     */
3422b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne    private void updateMetricsFromNetworkDetail(NetworkDetail networkDetail) {
3432b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne        int dtimInterval = networkDetail.getDtimInterval();
3442b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne        if (dtimInterval > 0) {
3452b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne            mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.dtim =
3462b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                    dtimInterval;
3472b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne        }
3482b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne        int connectionWifiMode;
3492b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne        switch (networkDetail.getWifiMode()) {
3502b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne            case InformationElementUtil.WifiMode.MODE_UNDEFINED:
3512b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_UNKNOWN;
3522b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                break;
3532b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne            case InformationElementUtil.WifiMode.MODE_11A:
3542b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_A;
3552b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                break;
3562b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne            case InformationElementUtil.WifiMode.MODE_11B:
3572b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_B;
3582b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                break;
3592b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne            case InformationElementUtil.WifiMode.MODE_11G:
3602b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_G;
3612b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                break;
3622b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne            case InformationElementUtil.WifiMode.MODE_11N:
3632b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_N;
3642b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                break;
3652b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne            case InformationElementUtil.WifiMode.MODE_11AC  :
3662b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_AC;
3672b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                break;
3682b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne            default:
3692b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_OTHER;
3702b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                break;
3712b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne        }
3722b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne        mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto
3732b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                .routerTechnology = connectionWifiMode;
3742b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne    }
3752b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne
3762b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne    /**
3772b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne     * Set ConnectionEvent RSSI and authentication type from ScanResult
3782b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne     */
3792b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne    private void updateMetricsFromScanResult(ScanResult scanResult) {
3802b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne        mCurrentConnectionEvent.mConnectionEvent.signalStrength = scanResult.level;
3812b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne        mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication =
3822b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                WifiMetricsProto.RouterFingerPrint.AUTH_OPEN;
3832b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne        if (scanResult.capabilities != null) {
3842b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne            if (scanResult.capabilities.contains("WEP")) {
3852b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication =
3862b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                        WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL;
3872b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne            } else if (scanResult.capabilities.contains("PSK")) {
3882b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication =
3892b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                        WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL;
3902b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne            } else if (scanResult.capabilities.contains("EAP")) {
3912b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication =
3922b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne                        WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE;
3932b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne            }
3942b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne        }
3952b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne    }
3962b152feb1c574f30557581770d4f8c06c770ba34Glen Kuhne
3971b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    void setNumSavedNetworks(int num) {
3981b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        synchronized (mLock) {
3991b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            mWifiLogProto.numSavedNetworks = num;
4001b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
4011b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
4021b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
4031b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    void setNumOpenNetworks(int num) {
4041b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        synchronized (mLock) {
4051b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            mWifiLogProto.numOpenNetworks = num;
4061b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
4071b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
4081b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
4091b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    void setNumPersonalNetworks(int num) {
4101b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        synchronized (mLock) {
4111b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            mWifiLogProto.numPersonalNetworks = num;
4121b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
4131b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
4141b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
4151b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    void setNumEnterpriseNetworks(int num) {
4161b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        synchronized (mLock) {
4171b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            mWifiLogProto.numEnterpriseNetworks = num;
4181b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
4191b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
4201b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
4211b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    void setNumNetworksAddedByUser(int num) {
4221b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        synchronized (mLock) {
4231b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            mWifiLogProto.numNetworksAddedByUser = num;
4241b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
4251b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
4261b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
4271b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    void setNumNetworksAddedByApps(int num) {
4281b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        synchronized (mLock) {
4291b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            mWifiLogProto.numNetworksAddedByApps = num;
4301b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
4311b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
4321b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
4331b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    void setIsLocationEnabled(boolean enabled) {
4341b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        synchronized (mLock) {
4351b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            mWifiLogProto.isLocationEnabled = enabled;
4361b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
4371b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
4381b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
4391b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    void setIsScanningAlwaysEnabled(boolean enabled) {
4401b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        synchronized (mLock) {
4411b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            mWifiLogProto.isScanningAlwaysEnabled = enabled;
4421b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
4431b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
4441b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
4451b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    /**
4461b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * Increment Airplane mode toggle count
4471b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     */
4481b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    public void incrementAirplaneToggleCount() {
4491b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        synchronized (mLock) {
4501b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            mWifiLogProto.numWifiToggledViaAirplane++;
4511b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
4521b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
4531b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
4541b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    /**
4551b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * Increment Wifi Toggle count
4561b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     */
4571b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    public void incrementWifiToggleCount() {
4581b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        synchronized (mLock) {
4591b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            mWifiLogProto.numWifiToggledViaSettings++;
4601b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
4611b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
4621b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
4631b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    /**
4641b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * Increment Non Empty Scan Results count
4651b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     */
4661b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    public void incrementNonEmptyScanResultCount() {
4671b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        synchronized (mLock) {
4681b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            mWifiLogProto.numNonEmptyScanResults++;
4691b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
4701b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
4711b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
4721b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    /**
4731b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * Increment Empty Scan Results count
4741b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     */
4751b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    public void incrementEmptyScanResultCount() {
4761b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        synchronized (mLock) {
4771b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            mWifiLogProto.numEmptyScanResults++;
4781b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
4791b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
4801b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
4811b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    /**
4821b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * Increment count of scan return code occurrence
4831b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     *
4841b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * @param scanReturnCode Return code from scan attempt WifiMetricsProto.WifiLog.SCAN_X
4851b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     */
4861b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    public void incrementScanReturnEntry(int scanReturnCode) {
4871b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        synchronized (mLock) {
4881b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            WifiMetricsProto.WifiLog.ScanReturnEntry entry = mScanReturnEntries.get(scanReturnCode);
4891b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            if (entry == null) {
4901b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                entry = new WifiMetricsProto.WifiLog.ScanReturnEntry();
4911b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                entry.scanReturnCode = scanReturnCode;
4921b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                entry.scanResultsCount = 0;
4931b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            }
4941b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            entry.scanResultsCount++;
4951b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            mScanReturnEntries.put(scanReturnCode, entry);
4961b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
4971b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
4981b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
4991b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    /**
5001b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * Increments the count of scans initiated by each wifi state, accounts for screenOn/Off
5011b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     *
5021b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * @param state State of the system when scan was initiated, see WifiMetricsProto.WifiLog.WIFI_X
5031b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * @param screenOn Is the screen on
5041b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     */
5051b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    public void incrementWifiSystemScanStateCount(int state, boolean screenOn) {
5061b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        synchronized (mLock) {
5071b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            int index = state * (screenOn ? 2 : 1);
5081b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            WifiMetricsProto.WifiLog.WifiSystemStateEntry entry =
5091b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                    mWifiSystemStateEntries.get(index);
5101b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            if (entry == null) {
5111b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                entry = new WifiMetricsProto.WifiLog.WifiSystemStateEntry();
5121b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                entry.wifiState = state;
5131b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                entry.wifiStateCount = 0;
5141b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                entry.isScreenOn = screenOn;
5151b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            }
5161b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            entry.wifiStateCount++;
5171b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            mWifiSystemStateEntries.put(state, entry);
5181b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
5191b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
5201b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
52111638f348ba45f9f417928e79b81186cef76c561Glen Kuhne    public static final String PROTO_DUMP_ARG = "wifiMetricsProto";
5221b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    /**
5231b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * Dump all WifiMetrics. Collects some metrics from ConfigStore, Settings and WifiManager
5241b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * at this time
5251b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     *
5261b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * @param fd unused
5271b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * @param pw PrintWriter for writing dump to
5281b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * @param args unused
5291b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     */
5301b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
5311b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        synchronized (mLock) {
5321b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            pw.println("WifiMetrics:");
53311638f348ba45f9f417928e79b81186cef76c561Glen Kuhne            if (args.length > 0 && PROTO_DUMP_ARG.equals(args[0])) {
5341b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                //Dump serialized WifiLog proto
5351b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                consolidateProto(true);
5361b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                for (ConnectionEvent event : mConnectionEventList) {
5371b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                    if (mCurrentConnectionEvent != event) {
5381b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                        //indicate that automatic bug report has been taken for all valid
5391b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                        //connection events
5401b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                        event.mConnectionEvent.automaticBugReportTaken = true;
5411b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                    }
5421b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                }
5431b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                byte[] wifiMetricsProto = WifiMetricsProto.WifiLog.toByteArray(mWifiLogProto);
5441b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                String metricsProtoDump = Base64.encodeToString(wifiMetricsProto, Base64.DEFAULT);
5451b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                pw.println(metricsProtoDump);
5461b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                pw.println("EndWifiMetrics");
5472532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                clear();
5481b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            } else {
5491b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                pw.println("mConnectionEvents:");
5501b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                for (ConnectionEvent event : mConnectionEventList) {
5511b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                    String eventLine = event.toString();
5521b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                    if (event == mCurrentConnectionEvent) {
5531b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                        eventLine += "CURRENTLY OPEN EVENT";
5541b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                    }
5551b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                    pw.println(eventLine);
5561b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                }
5571b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                pw.println("mWifiLogProto.numSavedNetworks=" + mWifiLogProto.numSavedNetworks);
5581b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                pw.println("mWifiLogProto.numOpenNetworks=" + mWifiLogProto.numOpenNetworks);
5591b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                pw.println("mWifiLogProto.numPersonalNetworks="
5601b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                        + mWifiLogProto.numPersonalNetworks);
5611b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                pw.println("mWifiLogProto.numEnterpriseNetworks="
5621b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                        + mWifiLogProto.numEnterpriseNetworks);
5631b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                pw.println("mWifiLogProto.isLocationEnabled=" + mWifiLogProto.isLocationEnabled);
5641b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                pw.println("mWifiLogProto.isScanningAlwaysEnabled="
5651b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                        + mWifiLogProto.isScanningAlwaysEnabled);
5661b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                pw.println("mWifiLogProto.numWifiToggledViaSettings="
5671b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                        + mWifiLogProto.numWifiToggledViaSettings);
5681b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                pw.println("mWifiLogProto.numWifiToggledViaAirplane="
5691b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                        + mWifiLogProto.numWifiToggledViaAirplane);
5701b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                pw.println("mWifiLogProto.numNetworksAddedByUser="
5711b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                        + mWifiLogProto.numNetworksAddedByUser);
5721b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                //TODO - Pending scanning refactor
5731b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                pw.println("mWifiLogProto.numNetworksAddedByApps=" + "<TODO>");
5741b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                pw.println("mWifiLogProto.numNonEmptyScanResults=" + "<TODO>");
5751b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                pw.println("mWifiLogProto.numEmptyScanResults=" + "<TODO>");
5761b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                pw.println("mWifiLogProto.numOneshotScans=" + "<TODO>");
5771b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                pw.println("mWifiLogProto.numBackgroundScans=" + "<TODO>");
5781b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                pw.println("mScanReturnEntries:" + " <TODO>");
5791b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                pw.println("mSystemStateEntries:" + " <TODO>");
5801b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            }
5811b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
5821b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
5831b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
5841b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    /**
5851b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * Assign the separate ConnectionEvent, SystemStateEntry and ScanReturnCode lists to their
5861b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * respective lists within mWifiLogProto, and clear the original lists managed here.
5871b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     *
5881b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * @param incremental Only include ConnectionEvents created since last automatic bug report
5891b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     */
5901b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    private void consolidateProto(boolean incremental) {
5911b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        List<WifiMetricsProto.ConnectionEvent> events = new ArrayList<>();
5921b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        synchronized (mLock) {
5931b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            for (ConnectionEvent event : mConnectionEventList) {
5941b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                if (!incremental || ((mCurrentConnectionEvent != event)
5951b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                        && !event.mConnectionEvent.automaticBugReportTaken)) {
5961b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                    //Get all ConnectionEvents that haven not been dumped as a proto, also exclude
5971b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                    //the current active un-ended connection event
5981b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                    events.add(event.mConnectionEvent);
5992532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                    event.mConnectionEvent.automaticBugReportTaken = true;
6001b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                }
6011b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            }
6021b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            if (events.size() > 0) {
6031b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne                mWifiLogProto.connectionEvent = events.toArray(mWifiLogProto.connectionEvent);
6041b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            }
6051b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne            //<TODO> SystemStateEntry and ScanReturnCode list consolidation
6061b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        }
6071b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
6081b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne
6091b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    /**
6101b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * Serializes all of WifiMetrics to WifiLog proto, and returns the byte array.
6111b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * Does not count as taking an automatic bug report
6121b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     *
6131b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     * @return byte array of the deserialized & consolidated Proto
6141b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne     */
6151b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    public byte[] toByteArray() {
6161b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        consolidateProto(false);
6171b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne        return mWifiLogProto.toByteArray(mWifiLogProto);
6181b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne    }
6192532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne
6202532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne    /**
6212532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne     * Clear all WifiMetrics, except for currentConnectionEvent.
6222532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne     */
6232532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne    private void clear() {
6242532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        synchronized (mLock) {
6252532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne            mConnectionEventList.clear();
6262532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne            if (mCurrentConnectionEvent != null) {
6272532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne                mConnectionEventList.add(mCurrentConnectionEvent);
6282532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne            }
6292532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne            mScanReturnEntries.clear();
6302532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne            mWifiSystemStateEntries.clear();
6312532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne            mWifiLogProto.clear();
6322532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne        }
6332532a24b254d724a9b6771d327dc410b32b18602Glen Kuhne    }
6341b067831bbff14f8e7a99b927b69f714d1b03448Glen Kuhne}
635