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 static android.net.wifi.WifiConfiguration.MeteredOverride;
20 
21 import static java.lang.StrictMath.toIntExact;
22 
23 import android.content.Context;
24 import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback;
25 import android.net.wifi.EAPConstants;
26 import android.net.wifi.IOnWifiUsabilityStatsListener;
27 import android.net.wifi.ScanResult;
28 import android.net.wifi.SoftApCapability;
29 import android.net.wifi.SoftApConfiguration;
30 import android.net.wifi.SupplicantState;
31 import android.net.wifi.WifiConfiguration;
32 import android.net.wifi.WifiEnterpriseConfig;
33 import android.net.wifi.WifiInfo;
34 import android.net.wifi.WifiManager;
35 import android.net.wifi.WifiManager.DeviceMobilityState;
36 import android.net.wifi.WifiUsabilityStatsEntry.ProbeStatus;
37 import android.net.wifi.hotspot2.PasspointConfiguration;
38 import android.net.wifi.hotspot2.ProvisioningCallback;
39 import android.net.wifi.nl80211.WifiNl80211Manager;
40 import android.os.Handler;
41 import android.os.IBinder;
42 import android.os.Looper;
43 import android.os.Message;
44 import android.os.RemoteException;
45 import android.os.SystemProperties;
46 import android.telephony.TelephonyManager;
47 import android.text.TextUtils;
48 import android.util.ArrayMap;
49 import android.util.Base64;
50 import android.util.Log;
51 import android.util.Pair;
52 import android.util.SparseArray;
53 import android.util.SparseIntArray;
54 
55 import com.android.internal.annotations.VisibleForTesting;
56 import com.android.server.wifi.aware.WifiAwareMetrics;
57 import com.android.server.wifi.hotspot2.ANQPNetworkKey;
58 import com.android.server.wifi.hotspot2.NetworkDetail;
59 import com.android.server.wifi.hotspot2.PasspointManager;
60 import com.android.server.wifi.hotspot2.PasspointMatch;
61 import com.android.server.wifi.hotspot2.PasspointProvider;
62 import com.android.server.wifi.hotspot2.Utils;
63 import com.android.server.wifi.p2p.WifiP2pMetrics;
64 import com.android.server.wifi.proto.WifiStatsLog;
65 import com.android.server.wifi.proto.nano.WifiMetricsProto;
66 import com.android.server.wifi.proto.nano.WifiMetricsProto.CarrierWifiMetrics;
67 import com.android.server.wifi.proto.nano.WifiMetricsProto.ConnectToNetworkNotificationAndActionCount;
68 import com.android.server.wifi.proto.nano.WifiMetricsProto.DeviceMobilityStatePnoScanStats;
69 import com.android.server.wifi.proto.nano.WifiMetricsProto.ExperimentValues;
70 import com.android.server.wifi.proto.nano.WifiMetricsProto.HealthMonitorMetrics;
71 import com.android.server.wifi.proto.nano.WifiMetricsProto.InitPartialScanStats;
72 import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats;
73 import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.ExperimentProbeCounts;
74 import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.LinkProbeFailureReasonCount;
75 import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkSpeedCount;
76 import com.android.server.wifi.proto.nano.WifiMetricsProto.MeteredNetworkStats;
77 import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkSelectionExperimentDecisions;
78 import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProfileTypeCount;
79 import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProvisionStats;
80 import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProvisionStats.ProvisionFailureCount;
81 import com.android.server.wifi.proto.nano.WifiMetricsProto.PnoScanMetrics;
82 import com.android.server.wifi.proto.nano.WifiMetricsProto.SoftApConnectedClientsEvent;
83 import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent;
84 import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent.ConfigInfo;
85 import com.android.server.wifi.proto.nano.WifiMetricsProto.TargetNetworkInfo;
86 import com.android.server.wifi.proto.nano.WifiMetricsProto.UserActionEvent;
87 import com.android.server.wifi.proto.nano.WifiMetricsProto.UserReactionToApprovalUiEvent;
88 import com.android.server.wifi.proto.nano.WifiMetricsProto.UserReactionToApprovalUiEvent.UserReaction;
89 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent;
90 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiLinkLayerUsageStats;
91 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiLockStats;
92 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiNetworkRequestApiLog;
93 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiNetworkSuggestionApiLog;
94 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiNetworkSuggestionApiLog.SuggestionAppCount;
95 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiToggleStats;
96 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats;
97 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStatsEntry;
98 import com.android.server.wifi.rtt.RttMetrics;
99 import com.android.server.wifi.scanner.KnownBandsChannelHelper;
100 import com.android.server.wifi.util.ExternalCallbackTracker;
101 import com.android.server.wifi.util.InformationElementUtil;
102 import com.android.server.wifi.util.IntCounter;
103 import com.android.server.wifi.util.IntHistogram;
104 import com.android.server.wifi.util.MetricsUtils;
105 import com.android.server.wifi.util.ObjectCounter;
106 import com.android.server.wifi.util.ScanResultUtil;
107 import com.android.wifi.resources.R;
108 
109 import org.json.JSONArray;
110 import org.json.JSONException;
111 import org.json.JSONObject;
112 
113 import java.io.FileDescriptor;
114 import java.io.PrintWriter;
115 import java.util.ArrayList;
116 import java.util.BitSet;
117 import java.util.Calendar;
118 import java.util.HashMap;
119 import java.util.HashSet;
120 import java.util.LinkedList;
121 import java.util.List;
122 import java.util.Map;
123 import java.util.Random;
124 import java.util.Set;
125 
126 /**
127  * Provides storage for wireless connectivity metrics, as they are generated.
128  * Metrics logged by this class include:
129  *   Aggregated connection stats (num of connections, num of failures, ...)
130  *   Discrete connection event stats (time, duration, failure codes, ...)
131  *   Router details (technology type, authentication type, ...)
132  *   Scan stats
133  */
134 public class WifiMetrics {
135     private static final String TAG = "WifiMetrics";
136     private static final boolean DBG = false;
137     /**
138      * Clamp the RSSI poll counts to values between [MIN,MAX]_RSSI_POLL
139      */
140     private static final int MAX_RSSI_POLL = 0;
141     private static final int MIN_RSSI_POLL = -127;
142     public static final int MAX_RSSI_DELTA = 127;
143     public static final int MIN_RSSI_DELTA = -127;
144     /** Minimum link speed (Mbps) to count for link_speed_counts */
145     public static final int MIN_LINK_SPEED_MBPS = 0;
146     /** Maximum time period between ScanResult and RSSI poll to generate rssi delta datapoint */
147     public static final long TIMEOUT_RSSI_DELTA_MILLIS =  3000;
148     private static final int MIN_WIFI_SCORE = 0;
149     private static final int MAX_WIFI_SCORE = ConnectedScore.WIFI_MAX_SCORE;
150     private static final int MIN_WIFI_USABILITY_SCORE = 0; // inclusive
151     private static final int MAX_WIFI_USABILITY_SCORE = 100; // inclusive
152     @VisibleForTesting
153     static final int LOW_WIFI_SCORE = 50; // Mobile data score
154     @VisibleForTesting
155     static final int LOW_WIFI_USABILITY_SCORE = 50; // Mobile data score
156     private final Object mLock = new Object();
157     private static final int MAX_CONNECTION_EVENTS = 256;
158     // Largest bucket in the NumConnectableNetworkCount histogram,
159     // anything large will be stored in this bucket
160     public static final int MAX_CONNECTABLE_SSID_NETWORK_BUCKET = 20;
161     public static final int MAX_CONNECTABLE_BSSID_NETWORK_BUCKET = 50;
162     public static final int MAX_TOTAL_SCAN_RESULT_SSIDS_BUCKET = 100;
163     public static final int MAX_TOTAL_SCAN_RESULTS_BUCKET = 250;
164     public static final int MAX_TOTAL_PASSPOINT_APS_BUCKET = 50;
165     public static final int MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET = 20;
166     public static final int MAX_PASSPOINT_APS_PER_UNIQUE_ESS_BUCKET = 50;
167     public static final int MAX_TOTAL_80211MC_APS_BUCKET = 20;
168     private static final int CONNECT_TO_NETWORK_NOTIFICATION_ACTION_KEY_MULTIPLIER = 1000;
169     // Max limit for number of soft AP related events, extra events will be dropped.
170     private static final int MAX_NUM_SOFT_AP_EVENTS = 256;
171     // Maximum number of WifiIsUnusableEvent
172     public static final int MAX_UNUSABLE_EVENTS = 20;
173     // Minimum time wait before generating next WifiIsUnusableEvent from data stall
174     public static final int MIN_DATA_STALL_WAIT_MS = 120 * 1000; // 2 minutes
175     // Max number of WifiUsabilityStatsEntry elements to store in the ringbuffer.
176     public static final int MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE = 40;
177     // Max number of WifiUsabilityStats elements to store for each type.
178     public static final int MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE = 10;
179     // Max number of WifiUsabilityStats per labeled type to upload to server
180     public static final int MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD = 2;
181     public static final int NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD = 100;
182     public static final int MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS = 1000 * 3600; // 1 hour
183     // Histogram for WifiConfigStore IO duration times. Indicates the following 5 buckets (in ms):
184     //   < 50
185     //   [50, 100)
186     //   [100, 150)
187     //   [150, 200)
188     //   [200, 300)
189     //   >= 300
190     private static final int[] WIFI_CONFIG_STORE_IO_DURATION_BUCKET_RANGES_MS =
191             {50, 100, 150, 200, 300};
192     // Minimum time wait before generating a LABEL_GOOD stats after score breaching low.
193     public static final int MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS = 60 * 1000; // 1 minute
194     // Maximum time that a score breaching low event stays valid.
195     public static final int VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS = 90 * 1000; // 1.5 minutes
196 
197     private Clock mClock;
198     private boolean mScreenOn;
199     private int mWifiState;
200     private WifiAwareMetrics mWifiAwareMetrics;
201     private RttMetrics mRttMetrics;
202     private final PnoScanMetrics mPnoScanMetrics = new PnoScanMetrics();
203     private final WifiLinkLayerUsageStats mWifiLinkLayerUsageStats = new WifiLinkLayerUsageStats();
204     private final ExperimentValues mExperimentValues = new ExperimentValues();
205     private Handler mHandler;
206     private ScoringParams mScoringParams;
207     private WifiConfigManager mWifiConfigManager;
208     private BssidBlocklistMonitor mBssidBlocklistMonitor;
209     private WifiNetworkSelector mWifiNetworkSelector;
210     private PasspointManager mPasspointManager;
211     private Context mContext;
212     private FrameworkFacade mFacade;
213     private WifiDataStall mWifiDataStall;
214     private WifiLinkLayerStats mLastLinkLayerStats;
215     private WifiHealthMonitor mWifiHealthMonitor;
216     private WifiScoreCard mWifiScoreCard;
217     private String mLastBssid;
218     private int mLastFrequency = -1;
219     private int mSeqNumInsideFramework = 0;
220     private int mLastWifiUsabilityScore = -1;
221     private int mLastWifiUsabilityScoreNoReset = -1;
222     private int mLastPredictionHorizonSec = -1;
223     private int mLastPredictionHorizonSecNoReset = -1;
224     private int mSeqNumToFramework = -1;
225     @ProbeStatus private int mProbeStatusSinceLastUpdate =
226             android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE;
227     private int mProbeElapsedTimeSinceLastUpdateMs = -1;
228     private int mProbeMcsRateSinceLastUpdate = -1;
229     private long mScoreBreachLowTimeMillis = -1;
230 
231     public static final int MAX_STA_EVENTS = 768;
232     @VisibleForTesting static final int MAX_USER_ACTION_EVENTS = 200;
233     private LinkedList<StaEventWithTime> mStaEventList = new LinkedList<>();
234     private LinkedList<UserActionEventWithTime> mUserActionEventList = new LinkedList<>();
235     private int mLastPollRssi = -127;
236     private int mLastPollLinkSpeed = -1;
237     private int mLastPollRxLinkSpeed = -1;
238     private int mLastPollFreq = -1;
239     private int mLastScore = -1;
240 
241     /**
242      * Metrics are stored within an instance of the WifiLog proto during runtime,
243      * The ConnectionEvent, SystemStateEntries & ScanReturnEntries metrics are stored during
244      * runtime in member lists of this WifiMetrics class, with the final WifiLog proto being pieced
245      * together at dump-time
246      */
247     private final WifiMetricsProto.WifiLog mWifiLogProto = new WifiMetricsProto.WifiLog();
248     /**
249      * Session information that gets logged for every Wifi connection attempt.
250      */
251     private final List<ConnectionEvent> mConnectionEventList = new ArrayList<>();
252     /**
253      * The latest started (but un-ended) connection attempt
254      */
255     private ConnectionEvent mCurrentConnectionEvent;
256     /**
257      * Count of number of times each scan return code, indexed by WifiLog.ScanReturnCode
258      */
259     private final SparseIntArray mScanReturnEntries = new SparseIntArray();
260     /**
261      * Mapping of system state to the counts of scans requested in that wifi state * screenOn
262      * combination. Indexed by WifiLog.WifiState * (1 + screenOn)
263      */
264     private final SparseIntArray mWifiSystemStateEntries = new SparseIntArray();
265     /** Mapping of channel frequency to its RSSI distribution histogram **/
266     private final Map<Integer, SparseIntArray> mRssiPollCountsMap = new HashMap<>();
267     /** Mapping of RSSI scan-poll delta values to counts. */
268     private final SparseIntArray mRssiDeltaCounts = new SparseIntArray();
269     /** Mapping of link speed values to LinkSpeedCount objects. */
270     private final SparseArray<LinkSpeedCount> mLinkSpeedCounts = new SparseArray<>();
271 
272     private final IntCounter mTxLinkSpeedCount2g = new IntCounter();
273     private final IntCounter mTxLinkSpeedCount5gLow = new IntCounter();
274     private final IntCounter mTxLinkSpeedCount5gMid = new IntCounter();
275     private final IntCounter mTxLinkSpeedCount5gHigh = new IntCounter();
276     private final IntCounter mTxLinkSpeedCount6gLow = new IntCounter();
277     private final IntCounter mTxLinkSpeedCount6gMid = new IntCounter();
278     private final IntCounter mTxLinkSpeedCount6gHigh = new IntCounter();
279 
280     private final IntCounter mRxLinkSpeedCount2g = new IntCounter();
281     private final IntCounter mRxLinkSpeedCount5gLow = new IntCounter();
282     private final IntCounter mRxLinkSpeedCount5gMid = new IntCounter();
283     private final IntCounter mRxLinkSpeedCount5gHigh = new IntCounter();
284     private final IntCounter mRxLinkSpeedCount6gLow = new IntCounter();
285     private final IntCounter mRxLinkSpeedCount6gMid = new IntCounter();
286     private final IntCounter mRxLinkSpeedCount6gHigh = new IntCounter();
287 
288     /** RSSI of the scan result for the last connection event*/
289     private int mScanResultRssi = 0;
290     /** Boot-relative timestamp when the last candidate scanresult was received, used to calculate
291         RSSI deltas. -1 designates no candidate scanResult being tracked */
292     private long mScanResultRssiTimestampMillis = -1;
293     /** Mapping of alert reason to the respective alert count. */
294     private final SparseIntArray mWifiAlertReasonCounts = new SparseIntArray();
295     /**
296      * Records the getElapsedSinceBootMillis (in seconds) that represents the beginning of data
297      * capture for for this WifiMetricsProto
298      */
299     private long mRecordStartTimeSec;
300     /** Mapping of Wifi Scores to counts */
301     private final SparseIntArray mWifiScoreCounts = new SparseIntArray();
302     /** Mapping of Wifi Usability Scores to counts */
303     private final SparseIntArray mWifiUsabilityScoreCounts = new SparseIntArray();
304     /** Mapping of SoftApManager start SoftAp return codes to counts */
305     private final SparseIntArray mSoftApManagerReturnCodeCounts = new SparseIntArray();
306 
307     private final SparseIntArray mTotalSsidsInScanHistogram = new SparseIntArray();
308     private final SparseIntArray mTotalBssidsInScanHistogram = new SparseIntArray();
309     private final SparseIntArray mAvailableOpenSsidsInScanHistogram = new SparseIntArray();
310     private final SparseIntArray mAvailableOpenBssidsInScanHistogram = new SparseIntArray();
311     private final SparseIntArray mAvailableSavedSsidsInScanHistogram = new SparseIntArray();
312     private final SparseIntArray mAvailableSavedBssidsInScanHistogram = new SparseIntArray();
313     private final SparseIntArray mAvailableOpenOrSavedSsidsInScanHistogram = new SparseIntArray();
314     private final SparseIntArray mAvailableOpenOrSavedBssidsInScanHistogram = new SparseIntArray();
315     private final SparseIntArray mAvailableSavedPasspointProviderProfilesInScanHistogram =
316             new SparseIntArray();
317     private final SparseIntArray mAvailableSavedPasspointProviderBssidsInScanHistogram =
318             new SparseIntArray();
319 
320     private final IntCounter mInstalledPasspointProfileTypeForR1 = new IntCounter();
321     private final IntCounter mInstalledPasspointProfileTypeForR2 = new IntCounter();
322 
323     /** Mapping of "Connect to Network" notifications to counts. */
324     private final SparseIntArray mConnectToNetworkNotificationCount = new SparseIntArray();
325     /** Mapping of "Connect to Network" notification user actions to counts. */
326     private final SparseIntArray mConnectToNetworkNotificationActionCount = new SparseIntArray();
327     private int mOpenNetworkRecommenderBlacklistSize = 0;
328     private boolean mIsWifiNetworksAvailableNotificationOn = false;
329     private int mNumOpenNetworkConnectMessageFailedToSend = 0;
330     private int mNumOpenNetworkRecommendationUpdates = 0;
331     /** List of soft AP events related to number of connected clients in tethered mode */
332     private final List<SoftApConnectedClientsEvent> mSoftApEventListTethered = new ArrayList<>();
333     /** List of soft AP events related to number of connected clients in local only mode */
334     private final List<SoftApConnectedClientsEvent> mSoftApEventListLocalOnly = new ArrayList<>();
335 
336     private final SparseIntArray mObservedHotspotR1ApInScanHistogram = new SparseIntArray();
337     private final SparseIntArray mObservedHotspotR2ApInScanHistogram = new SparseIntArray();
338     private final SparseIntArray mObservedHotspotR3ApInScanHistogram = new SparseIntArray();
339     private final SparseIntArray mObservedHotspotR1EssInScanHistogram = new SparseIntArray();
340     private final SparseIntArray mObservedHotspotR2EssInScanHistogram = new SparseIntArray();
341     private final SparseIntArray mObservedHotspotR3EssInScanHistogram = new SparseIntArray();
342     private final SparseIntArray mObservedHotspotR1ApsPerEssInScanHistogram = new SparseIntArray();
343     private final SparseIntArray mObservedHotspotR2ApsPerEssInScanHistogram = new SparseIntArray();
344     private final SparseIntArray mObservedHotspotR3ApsPerEssInScanHistogram = new SparseIntArray();
345 
346     private final SparseIntArray mObserved80211mcApInScanHistogram = new SparseIntArray();
347 
348     // link probing stats
349     private final IntCounter mLinkProbeSuccessRssiCounts = new IntCounter(-85, -65);
350     private final IntCounter mLinkProbeFailureRssiCounts = new IntCounter(-85, -65);
351     private final IntCounter mLinkProbeSuccessLinkSpeedCounts = new IntCounter();
352     private final IntCounter mLinkProbeFailureLinkSpeedCounts = new IntCounter();
353 
354     private static final int[] LINK_PROBE_TIME_SINCE_LAST_TX_SUCCESS_SECONDS_HISTOGRAM_BUCKETS =
355             {5, 15, 45, 135};
356     private final IntHistogram mLinkProbeSuccessSecondsSinceLastTxSuccessHistogram =
357             new IntHistogram(LINK_PROBE_TIME_SINCE_LAST_TX_SUCCESS_SECONDS_HISTOGRAM_BUCKETS);
358     private final IntHistogram mLinkProbeFailureSecondsSinceLastTxSuccessHistogram =
359             new IntHistogram(LINK_PROBE_TIME_SINCE_LAST_TX_SUCCESS_SECONDS_HISTOGRAM_BUCKETS);
360 
361     private static final int[] LINK_PROBE_ELAPSED_TIME_MS_HISTOGRAM_BUCKETS =
362             {5, 10, 15, 20, 25, 50, 100, 200, 400, 800};
363     private final IntHistogram mLinkProbeSuccessElapsedTimeMsHistogram = new IntHistogram(
364             LINK_PROBE_ELAPSED_TIME_MS_HISTOGRAM_BUCKETS);
365     private final IntCounter mLinkProbeFailureReasonCounts = new IntCounter();
366     private final MeteredNetworkStatsBuilder mMeteredNetworkStatsBuilder =
367             new MeteredNetworkStatsBuilder();
368 
369     /**
370      * Maps a String link probe experiment ID to the number of link probes that were sent for this
371      * experiment.
372      */
373     private final ObjectCounter<String> mLinkProbeExperimentProbeCounts = new ObjectCounter<>();
374     private int mLinkProbeStaEventCount = 0;
375     @VisibleForTesting static final int MAX_LINK_PROBE_STA_EVENTS = MAX_STA_EVENTS / 4;
376 
377     private final LinkedList<WifiUsabilityStatsEntry> mWifiUsabilityStatsEntriesList =
378             new LinkedList<>();
379     private final LinkedList<WifiUsabilityStats> mWifiUsabilityStatsListBad = new LinkedList<>();
380     private final LinkedList<WifiUsabilityStats> mWifiUsabilityStatsListGood = new LinkedList<>();
381     private int mWifiUsabilityStatsCounter = 0;
382     private final Random mRand = new Random();
383     private final ExternalCallbackTracker<IOnWifiUsabilityStatsListener> mOnWifiUsabilityListeners;
384 
385     private final SparseArray<DeviceMobilityStatePnoScanStats> mMobilityStatePnoStatsMap =
386             new SparseArray<>();
387     private int mCurrentDeviceMobilityState;
388     /**
389      * The timestamp of the start of the current device mobility state.
390      */
391     private long mCurrentDeviceMobilityStateStartMs;
392     /**
393      * The timestamp of when the PNO scan started in the current device mobility state.
394      */
395     private long mCurrentDeviceMobilityStatePnoScanStartMs;
396 
397     /** Wifi power metrics*/
398     private WifiPowerMetrics mWifiPowerMetrics;
399 
400     /** Wifi Wake metrics */
401     private final WifiWakeMetrics mWifiWakeMetrics = new WifiWakeMetrics();
402 
403     /** Wifi P2p metrics */
404     private final WifiP2pMetrics mWifiP2pMetrics;
405 
406     /** DPP */
407     private final DppMetrics mDppMetrics;
408 
409     /** WifiConfigStore read duration histogram. */
410     private SparseIntArray mWifiConfigStoreReadDurationHistogram = new SparseIntArray();
411 
412     /** WifiConfigStore write duration histogram. */
413     private SparseIntArray mWifiConfigStoreWriteDurationHistogram = new SparseIntArray();
414 
415     /** New  API surface metrics */
416     private final WifiNetworkRequestApiLog mWifiNetworkRequestApiLog =
417             new WifiNetworkRequestApiLog();
418     private static final int[] NETWORK_REQUEST_API_MATCH_SIZE_HISTOGRAM_BUCKETS =
419             {0, 1, 5, 10};
420     private final IntHistogram mWifiNetworkRequestApiMatchSizeHistogram =
421             new IntHistogram(NETWORK_REQUEST_API_MATCH_SIZE_HISTOGRAM_BUCKETS);
422 
423     private final WifiNetworkSuggestionApiLog mWifiNetworkSuggestionApiLog =
424             new WifiNetworkSuggestionApiLog();
425     private static final int[] NETWORK_SUGGESTION_API_LIST_SIZE_HISTOGRAM_BUCKETS =
426             {5, 20, 50, 100, 500};
427     private final IntHistogram mWifiNetworkSuggestionApiListSizeHistogram =
428             new IntHistogram(NETWORK_SUGGESTION_API_LIST_SIZE_HISTOGRAM_BUCKETS);
429     private final IntCounter mWifiNetworkSuggestionApiAppTypeCounter = new IntCounter();
430     private final List<UserReaction> mUserApprovalSuggestionAppUiReactionList =
431             new ArrayList<>();
432     private final List<UserReaction> mUserApprovalCarrierUiReactionList =
433             new ArrayList<>();
434 
435     private final WifiLockStats mWifiLockStats = new WifiLockStats();
436     private static final int[] WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS =
437             {1, 10, 60, 600, 3600};
438     private final WifiToggleStats mWifiToggleStats = new WifiToggleStats();
439     private BssidBlocklistStats mBssidBlocklistStats = new BssidBlocklistStats();
440 
441     private final IntHistogram mWifiLockHighPerfAcqDurationSecHistogram =
442             new IntHistogram(WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS);
443     private final IntHistogram mWifiLockLowLatencyAcqDurationSecHistogram =
444             new IntHistogram(WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS);
445 
446     private final IntHistogram mWifiLockHighPerfActiveSessionDurationSecHistogram =
447             new IntHistogram(WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS);
448     private final IntHistogram mWifiLockLowLatencyActiveSessionDurationSecHistogram =
449             new IntHistogram(WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS);
450 
451     /**
452      * (experiment1Id, experiment2Id) =>
453      *     (sameSelectionNumChoicesCounter, differentSelectionNumChoicesCounter)
454      */
455     private Map<Pair<Integer, Integer>, NetworkSelectionExperimentResults>
456             mNetworkSelectionExperimentPairNumChoicesCounts = new ArrayMap<>();
457 
458     private int mNetworkSelectorExperimentId;
459 
460     /**
461      * Tracks the nominator for each network (i.e. which entity made the suggestion to connect).
462      * This object should not be cleared.
463      */
464     private final SparseIntArray mNetworkIdToNominatorId = new SparseIntArray();
465 
466     /** passpoint provision success count */
467     private int mNumProvisionSuccess = 0;
468 
469     /** Mapping of failure code to the respective passpoint provision failure count. */
470     private final IntCounter mPasspointProvisionFailureCounts = new IntCounter();
471 
472     // Connection duration stats collected while link layer stats reports are on
473     private final ConnectionDurationStats mConnectionDurationStats = new ConnectionDurationStats();
474 
475     private static final int[] CHANNEL_UTILIZATION_BUCKETS =
476             {25, 50, 75, 100, 125, 150, 175, 200, 225};
477 
478     private final IntHistogram mChannelUtilizationHistogram2G =
479             new IntHistogram(CHANNEL_UTILIZATION_BUCKETS);
480 
481     private final IntHistogram mChannelUtilizationHistogramAbove2G =
482             new IntHistogram(CHANNEL_UTILIZATION_BUCKETS);
483 
484     private static final int[] THROUGHPUT_MBPS_BUCKETS =
485             {1, 5, 10, 15, 25, 50, 100, 150, 200, 300, 450, 600, 800, 1200, 1600};
486     private final IntHistogram mTxThroughputMbpsHistogram2G =
487             new IntHistogram(THROUGHPUT_MBPS_BUCKETS);
488     private final IntHistogram mRxThroughputMbpsHistogram2G =
489             new IntHistogram(THROUGHPUT_MBPS_BUCKETS);
490     private final IntHistogram mTxThroughputMbpsHistogramAbove2G =
491             new IntHistogram(THROUGHPUT_MBPS_BUCKETS);
492     private final IntHistogram mRxThroughputMbpsHistogramAbove2G =
493             new IntHistogram(THROUGHPUT_MBPS_BUCKETS);
494 
495     // Init partial scan metrics
496     private int mInitPartialScanTotalCount;
497     private int mInitPartialScanSuccessCount;
498     private int mInitPartialScanFailureCount;
499     private static final int[] INIT_PARTIAL_SCAN_HISTOGRAM_BUCKETS =
500             {1, 3, 5, 10};
501     private final IntHistogram mInitPartialScanSuccessHistogram =
502             new IntHistogram(INIT_PARTIAL_SCAN_HISTOGRAM_BUCKETS);
503     private final IntHistogram mInitPartialScanFailureHistogram =
504             new IntHistogram(INIT_PARTIAL_SCAN_HISTOGRAM_BUCKETS);
505 
506     // Wi-Fi off metrics
507     private final WifiOffMetrics mWifiOffMetrics = new WifiOffMetrics();
508 
509     private final SoftApConfigLimitationMetrics mSoftApConfigLimitationMetrics =
510             new SoftApConfigLimitationMetrics();
511 
512     private final CarrierWifiMetrics mCarrierWifiMetrics =
513             new CarrierWifiMetrics();
514 
515     @VisibleForTesting
516     static class NetworkSelectionExperimentResults {
517         public static final int MAX_CHOICES = 10;
518 
519         public IntCounter sameSelectionNumChoicesCounter = new IntCounter(0, MAX_CHOICES);
520         public IntCounter differentSelectionNumChoicesCounter = new IntCounter(0, MAX_CHOICES);
521 
522         @Override
toString()523         public String toString() {
524             return "NetworkSelectionExperimentResults{"
525                     + "sameSelectionNumChoicesCounter="
526                     + sameSelectionNumChoicesCounter
527                     + ", differentSelectionNumChoicesCounter="
528                     + differentSelectionNumChoicesCounter
529                     + '}';
530         }
531     }
532 
533     class RouterFingerPrint {
534         private WifiMetricsProto.RouterFingerPrint mRouterFingerPrintProto;
RouterFingerPrint()535         RouterFingerPrint() {
536             mRouterFingerPrintProto = new WifiMetricsProto.RouterFingerPrint();
537         }
538 
toString()539         public String toString() {
540             StringBuilder sb = new StringBuilder();
541             synchronized (mLock) {
542                 sb.append("mConnectionEvent.roamType=" + mRouterFingerPrintProto.roamType);
543                 sb.append(", mChannelInfo=" + mRouterFingerPrintProto.channelInfo);
544                 sb.append(", mDtim=" + mRouterFingerPrintProto.dtim);
545                 sb.append(", mAuthentication=" + mRouterFingerPrintProto.authentication);
546                 sb.append(", mHidden=" + mRouterFingerPrintProto.hidden);
547                 sb.append(", mRouterTechnology=" + mRouterFingerPrintProto.routerTechnology);
548                 sb.append(", mSupportsIpv6=" + mRouterFingerPrintProto.supportsIpv6);
549                 sb.append(", mEapMethod=" + mRouterFingerPrintProto.eapMethod);
550                 sb.append(", mAuthPhase2Method=" + mRouterFingerPrintProto.authPhase2Method);
551                 sb.append(", mOcspType=" + mRouterFingerPrintProto.ocspType);
552                 sb.append(", mPmkCache=" + mRouterFingerPrintProto.pmkCacheEnabled);
553                 sb.append(", mMaxSupportedTxLinkSpeedMbps=" + mRouterFingerPrintProto
554                         .maxSupportedTxLinkSpeedMbps);
555                 sb.append(", mMaxSupportedRxLinkSpeedMbps=" + mRouterFingerPrintProto
556                         .maxSupportedRxLinkSpeedMbps);
557             }
558             return sb.toString();
559         }
updateFromWifiConfiguration(WifiConfiguration config)560         public void updateFromWifiConfiguration(WifiConfiguration config) {
561             synchronized (mLock) {
562                 if (config != null) {
563                     // Is this a hidden network
564                     mRouterFingerPrintProto.hidden = config.hiddenSSID;
565                     // Config may not have a valid dtimInterval set yet, in which case dtim will be zero
566                     // (These are only populated from beacon frame scan results, which are returned as
567                     // scan results from the chip far less frequently than Probe-responses)
568                     if (config.dtimInterval > 0) {
569                         mRouterFingerPrintProto.dtim = config.dtimInterval;
570                     }
571                     mCurrentConnectionEvent.mConfigSsid = config.SSID;
572                     // Get AuthType information from config (We do this again from ScanResult after
573                     // associating with BSSID)
574                     if (config.allowedKeyManagement != null
575                             && config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)) {
576                         mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto
577                                 .authentication = WifiMetricsProto.RouterFingerPrint.AUTH_OPEN;
578                     } else if (config.isEnterprise()) {
579                         mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto
580                                 .authentication = WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE;
581                     } else {
582                         mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto
583                                 .authentication = WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL;
584                     }
585                     mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto
586                             .passpoint = config.isPasspoint();
587                     // If there's a ScanResult candidate associated with this config already, get it and
588                     // log (more accurate) metrics from it
589                     ScanResult candidate = config.getNetworkSelectionStatus().getCandidate();
590                     if (candidate != null) {
591                         updateMetricsFromScanResult(candidate);
592                     }
593                     if (mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto
594                             .authentication == WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE
595                             && config.enterpriseConfig != null) {
596                         int eapMethod = config.enterpriseConfig.getEapMethod();
597                         mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto
598                                 .eapMethod = getEapMethodProto(eapMethod);
599                         int phase2Method = config.enterpriseConfig.getPhase2Method();
600                         mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto
601                                 .authPhase2Method = getAuthPhase2MethodProto(phase2Method);
602                         int ocspType = config.enterpriseConfig.getOcsp();
603                         mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto
604                                 .ocspType = getOcspTypeProto(ocspType);
605                     }
606                 }
607             }
608         }
609 
setPmkCache(boolean isEnabled)610         public void setPmkCache(boolean isEnabled) {
611             synchronized (mLock) {
612                 mRouterFingerPrintProto.pmkCacheEnabled = isEnabled;
613             }
614         }
615 
setMaxSupportedLinkSpeedMbps(int maxSupportedTxLinkSpeedMbps, int maxSupportedRxLinkSpeedMbps)616         public void setMaxSupportedLinkSpeedMbps(int maxSupportedTxLinkSpeedMbps,
617                 int maxSupportedRxLinkSpeedMbps) {
618             synchronized (mLock) {
619                 mRouterFingerPrintProto.maxSupportedTxLinkSpeedMbps = maxSupportedTxLinkSpeedMbps;
620                 mRouterFingerPrintProto.maxSupportedRxLinkSpeedMbps = maxSupportedRxLinkSpeedMbps;
621             }
622         }
623     }
getEapMethodProto(int eapMethod)624     private int getEapMethodProto(int eapMethod) {
625         switch (eapMethod) {
626             case WifiEnterpriseConfig.Eap.WAPI_CERT:
627                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_WAPI_CERT;
628             case WifiEnterpriseConfig.Eap.TLS:
629                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_TLS;
630             case WifiEnterpriseConfig.Eap.UNAUTH_TLS:
631                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_UNAUTH_TLS;
632             case WifiEnterpriseConfig.Eap.PEAP:
633                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_PEAP;
634             case WifiEnterpriseConfig.Eap.PWD:
635                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_PWD;
636             case WifiEnterpriseConfig.Eap.TTLS:
637                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_TTLS;
638             case WifiEnterpriseConfig.Eap.SIM:
639                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_SIM;
640             case WifiEnterpriseConfig.Eap.AKA:
641                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_AKA;
642             case WifiEnterpriseConfig.Eap.AKA_PRIME:
643                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_AKA_PRIME;
644             default:
645                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_UNKNOWN;
646         }
647     }
getAuthPhase2MethodProto(int phase2Method)648     private int getAuthPhase2MethodProto(int phase2Method) {
649         switch (phase2Method) {
650             case WifiEnterpriseConfig.Phase2.PAP:
651                 return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_PAP;
652             case WifiEnterpriseConfig.Phase2.MSCHAP:
653                 return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_MSCHAP;
654             case WifiEnterpriseConfig.Phase2.MSCHAPV2:
655                 return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_MSCHAPV2;
656             case WifiEnterpriseConfig.Phase2.GTC:
657                 return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_GTC;
658             case WifiEnterpriseConfig.Phase2.SIM:
659                 return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_SIM;
660             case WifiEnterpriseConfig.Phase2.AKA:
661                 return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_AKA;
662             case WifiEnterpriseConfig.Phase2.AKA_PRIME:
663                 return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_AKA_PRIME;
664             default:
665                 return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_NONE;
666         }
667     }
668 
getOcspTypeProto(int ocspType)669     private int getOcspTypeProto(int ocspType) {
670         switch (ocspType) {
671             case WifiEnterpriseConfig.OCSP_NONE:
672                 return WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_NONE;
673             case WifiEnterpriseConfig.OCSP_REQUEST_CERT_STATUS:
674                 return WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_REQUEST_CERT_STATUS;
675             case WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS:
676                 return WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_REQUIRE_CERT_STATUS;
677             case WifiEnterpriseConfig.OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS:
678                 return WifiMetricsProto.RouterFingerPrint
679                         .TYPE_OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS;
680             default:
681                 return WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_NONE;
682         }
683     }
684 
685     class BssidBlocklistStats {
686         public IntCounter networkSelectionFilteredBssidCount = new IntCounter();
687         public int numHighMovementConnectionSkipped = 0;
688         public int numHighMovementConnectionStarted = 0;
689 
toProto()690         public WifiMetricsProto.BssidBlocklistStats toProto() {
691             WifiMetricsProto.BssidBlocklistStats proto = new WifiMetricsProto.BssidBlocklistStats();
692             proto.networkSelectionFilteredBssidCount = networkSelectionFilteredBssidCount.toProto();
693             proto.highMovementMultipleScansFeatureEnabled = mContext.getResources().getBoolean(
694                     R.bool.config_wifiHighMovementNetworkSelectionOptimizationEnabled);
695             proto.numHighMovementConnectionSkipped = numHighMovementConnectionSkipped;
696             proto.numHighMovementConnectionStarted = numHighMovementConnectionStarted;
697             return proto;
698         }
699 
700         @Override
toString()701         public String toString() {
702             StringBuilder sb = new StringBuilder();
703             sb.append("networkSelectionFilteredBssidCount=" + networkSelectionFilteredBssidCount);
704             sb.append(", highMovementMultipleScansFeatureEnabled="
705                     + mContext.getResources().getBoolean(
706                             R.bool.config_wifiHighMovementNetworkSelectionOptimizationEnabled));
707             sb.append(", numHighMovementConnectionSkipped=" + numHighMovementConnectionSkipped);
708             sb.append(", numHighMovementConnectionStarted=" + numHighMovementConnectionStarted);
709             return sb.toString();
710         }
711     }
712 
713     class ConnectionDurationStats {
714         private int mConnectionDurationCellularDataOffMs;
715         private int mConnectionDurationSufficientThroughputMs;
716         private int mConnectionDurationInSufficientThroughputMs;
717 
toProto()718         public WifiMetricsProto.ConnectionDurationStats toProto() {
719             WifiMetricsProto.ConnectionDurationStats proto =
720                     new WifiMetricsProto.ConnectionDurationStats();
721             proto.totalTimeSufficientThroughputMs = mConnectionDurationSufficientThroughputMs;
722             proto.totalTimeInsufficientThroughputMs = mConnectionDurationInSufficientThroughputMs;
723             proto.totalTimeCellularDataOffMs = mConnectionDurationCellularDataOffMs;
724             return proto;
725         }
clear()726         public void clear() {
727             mConnectionDurationCellularDataOffMs = 0;
728             mConnectionDurationSufficientThroughputMs = 0;
729             mConnectionDurationInSufficientThroughputMs = 0;
730         }
incrementDurationCount(int timeDeltaLastTwoPollsMs, boolean isThroughputSufficient, boolean isCellularDataAvailable)731         public void incrementDurationCount(int timeDeltaLastTwoPollsMs,
732                 boolean isThroughputSufficient, boolean isCellularDataAvailable) {
733             if (!isCellularDataAvailable) {
734                 mConnectionDurationCellularDataOffMs += timeDeltaLastTwoPollsMs;
735             } else {
736                 if (isThroughputSufficient) {
737                     mConnectionDurationSufficientThroughputMs += timeDeltaLastTwoPollsMs;
738                 } else {
739                     mConnectionDurationInSufficientThroughputMs += timeDeltaLastTwoPollsMs;
740                 }
741             }
742         }
743         @Override
toString()744         public String toString() {
745             StringBuilder sb = new StringBuilder();
746             sb.append("connectionDurationSufficientThroughputMs=")
747                     .append(mConnectionDurationSufficientThroughputMs)
748                     .append(", connectionDurationInSufficientThroughputMs=")
749                     .append(mConnectionDurationInSufficientThroughputMs)
750                     .append(", connectionDurationCellularDataOffMs=")
751                     .append(mConnectionDurationCellularDataOffMs);
752             return sb.toString();
753         }
754     }
755 
756     class UserActionEventWithTime {
757         private UserActionEvent mUserActionEvent;
758         private long mWallClockTimeMs = 0; // wall clock time for debugging only
759 
UserActionEventWithTime(int eventType, TargetNetworkInfo targetNetworkInfo)760         UserActionEventWithTime(int eventType, TargetNetworkInfo targetNetworkInfo) {
761             mUserActionEvent = new UserActionEvent();
762             mUserActionEvent.eventType = eventType;
763             mUserActionEvent.startTimeMillis = mClock.getElapsedSinceBootMillis();
764             mWallClockTimeMs = mClock.getWallClockMillis();
765             mUserActionEvent.targetNetworkInfo = targetNetworkInfo;
766         }
767 
UserActionEventWithTime(int eventType, int targetNetId)768         UserActionEventWithTime(int eventType, int targetNetId) {
769             mUserActionEvent = new UserActionEvent();
770             mUserActionEvent.eventType = eventType;
771             mUserActionEvent.startTimeMillis = mClock.getElapsedSinceBootMillis();
772             mWallClockTimeMs = mClock.getWallClockMillis();
773             if (targetNetId >= 0) {
774                 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(targetNetId);
775                 if (config != null) {
776                     TargetNetworkInfo networkInfo = new TargetNetworkInfo();
777                     networkInfo.isEphemeral = config.isEphemeral();
778                     networkInfo.isPasspoint = config.isPasspoint();
779                     mUserActionEvent.targetNetworkInfo = networkInfo;
780                 }
781             }
782         }
783 
toString()784         public String toString() {
785             StringBuilder sb = new StringBuilder();
786             Calendar c = Calendar.getInstance();
787             c.setTimeInMillis(mWallClockTimeMs);
788             sb.append(String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c));
789             String eventType = "UNKNOWN";
790             switch (mUserActionEvent.eventType) {
791                 case UserActionEvent.EVENT_FORGET_WIFI:
792                     eventType = "EVENT_FORGET_WIFI";
793                     break;
794                 case UserActionEvent.EVENT_DISCONNECT_WIFI:
795                     eventType = "EVENT_DISCONNECT_WIFI";
796                     break;
797                 case UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_METERED:
798                     eventType = "EVENT_CONFIGURE_METERED_STATUS_METERED";
799                     break;
800                 case UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_UNMETERED:
801                     eventType = "EVENT_CONFIGURE_METERED_STATUS_UNMETERED";
802                     break;
803                 case UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_AUTO:
804                     eventType = "EVENT_CONFIGURE_METERED_STATUS_AUTO";
805                     break;
806                 case UserActionEvent.EVENT_CONFIGURE_MAC_RANDOMIZATION_ON:
807                     eventType = "EVENT_CONFIGURE_MAC_RANDOMIZATION_ON";
808                     break;
809                 case UserActionEvent.EVENT_CONFIGURE_MAC_RANDOMIZATION_OFF:
810                     eventType = "EVENT_CONFIGURE_MAC_RANDOMIZATION_OFF";
811                     break;
812                 case UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_ON:
813                     eventType = "EVENT_CONFIGURE_AUTO_CONNECT_ON";
814                     break;
815                 case UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_OFF:
816                     eventType = "EVENT_CONFIGURE_AUTO_CONNECT_OFF";
817                     break;
818                 case UserActionEvent.EVENT_TOGGLE_WIFI_ON:
819                     eventType = "EVENT_TOGGLE_WIFI_ON";
820                     break;
821                 case UserActionEvent.EVENT_TOGGLE_WIFI_OFF:
822                     eventType = "EVENT_TOGGLE_WIFI_OFF";
823                     break;
824                 case UserActionEvent.EVENT_MANUAL_CONNECT:
825                     eventType = "EVENT_MANUAL_CONNECT";
826                     break;
827             }
828             sb.append(" eventType=").append(eventType);
829             sb.append(" startTimeMillis=").append(mUserActionEvent.startTimeMillis);
830             TargetNetworkInfo networkInfo = mUserActionEvent.targetNetworkInfo;
831             if (networkInfo != null) {
832                 sb.append(" isEphemeral=").append(networkInfo.isEphemeral);
833                 sb.append(" isPasspoint=").append(networkInfo.isPasspoint);
834             }
835             return sb.toString();
836         }
837 
toProto()838         public UserActionEvent toProto() {
839             return mUserActionEvent;
840         }
841     }
842 
843     /**
844      * Log event, tracking the start time, end time and result of a wireless connection attempt.
845      */
846     class ConnectionEvent {
847         WifiMetricsProto.ConnectionEvent mConnectionEvent;
848         //<TODO> Move these constants into a wifi.proto Enum, and create a new Failure Type field
849         //covering more than just l2 failures. see b/27652362
850         /**
851          * Failure codes, used for the 'level_2_failure_code' Connection event field (covers a lot
852          * more failures than just l2 though, since the proto does not have a place to log
853          * framework failures)
854          */
855         // Failure is unknown
856         public static final int FAILURE_UNKNOWN = 0;
857         // NONE
858         public static final int FAILURE_NONE = 1;
859         // ASSOCIATION_REJECTION_EVENT
860         public static final int FAILURE_ASSOCIATION_REJECTION = 2;
861         // AUTHENTICATION_FAILURE_EVENT
862         public static final int FAILURE_AUTHENTICATION_FAILURE = 3;
863         // SSID_TEMP_DISABLED (Also Auth failure)
864         public static final int FAILURE_SSID_TEMP_DISABLED = 4;
865         // reconnect() or reassociate() call to WifiNative failed
866         public static final int FAILURE_CONNECT_NETWORK_FAILED = 5;
867         // NETWORK_DISCONNECTION_EVENT
868         public static final int FAILURE_NETWORK_DISCONNECTION = 6;
869         // NEW_CONNECTION_ATTEMPT before previous finished
870         public static final int FAILURE_NEW_CONNECTION_ATTEMPT = 7;
871         // New connection attempt to the same network & bssid
872         public static final int FAILURE_REDUNDANT_CONNECTION_ATTEMPT = 8;
873         // Roam Watchdog timer triggered (Roaming timed out)
874         public static final int FAILURE_ROAM_TIMEOUT = 9;
875         // DHCP failure
876         public static final int FAILURE_DHCP = 10;
877         // ASSOCIATION_TIMED_OUT
878         public static final int FAILURE_ASSOCIATION_TIMED_OUT = 11;
879 
880         RouterFingerPrint mRouterFingerPrint;
881         private long mRealStartTime;
882         private long mRealEndTime;
883         private String mConfigSsid;
884         private String mConfigBssid;
885         private int mWifiState;
886         private boolean mScreenOn;
887 
ConnectionEvent()888         private ConnectionEvent() {
889             mConnectionEvent = new WifiMetricsProto.ConnectionEvent();
890             mRealEndTime = 0;
891             mRealStartTime = 0;
892             mRouterFingerPrint = new RouterFingerPrint();
893             mConnectionEvent.routerFingerprint = mRouterFingerPrint.mRouterFingerPrintProto;
894             mConfigSsid = "<NULL>";
895             mConfigBssid = "<NULL>";
896             mWifiState = WifiMetricsProto.WifiLog.WIFI_UNKNOWN;
897             mScreenOn = false;
898         }
899 
toString()900         public String toString() {
901             StringBuilder sb = new StringBuilder();
902             sb.append("startTime=");
903             Calendar c = Calendar.getInstance();
904             synchronized (mLock) {
905                 c.setTimeInMillis(mConnectionEvent.startTimeMillis);
906                 sb.append(mConnectionEvent.startTimeMillis == 0 ? "            <null>" :
907                         String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c));
908                 sb.append(", SSID=");
909                 sb.append(mConfigSsid);
910                 sb.append(", BSSID=");
911                 sb.append(mConfigBssid);
912                 sb.append(", durationMillis=");
913                 sb.append(mConnectionEvent.durationTakenToConnectMillis);
914                 sb.append(", roamType=");
915                 switch(mConnectionEvent.roamType) {
916                     case 1:
917                         sb.append("ROAM_NONE");
918                         break;
919                     case 2:
920                         sb.append("ROAM_DBDC");
921                         break;
922                     case 3:
923                         sb.append("ROAM_ENTERPRISE");
924                         break;
925                     case 4:
926                         sb.append("ROAM_USER_SELECTED");
927                         break;
928                     case 5:
929                         sb.append("ROAM_UNRELATED");
930                         break;
931                     default:
932                         sb.append("ROAM_UNKNOWN");
933                 }
934                 sb.append(", connectionResult=");
935                 sb.append(mConnectionEvent.connectionResult);
936                 sb.append(", level2FailureCode=");
937                 switch(mConnectionEvent.level2FailureCode) {
938                     case FAILURE_NONE:
939                         sb.append("NONE");
940                         break;
941                     case FAILURE_ASSOCIATION_REJECTION:
942                         sb.append("ASSOCIATION_REJECTION");
943                         break;
944                     case FAILURE_AUTHENTICATION_FAILURE:
945                         sb.append("AUTHENTICATION_FAILURE");
946                         break;
947                     case FAILURE_SSID_TEMP_DISABLED:
948                         sb.append("SSID_TEMP_DISABLED");
949                         break;
950                     case FAILURE_CONNECT_NETWORK_FAILED:
951                         sb.append("CONNECT_NETWORK_FAILED");
952                         break;
953                     case FAILURE_NETWORK_DISCONNECTION:
954                         sb.append("NETWORK_DISCONNECTION");
955                         break;
956                     case FAILURE_NEW_CONNECTION_ATTEMPT:
957                         sb.append("NEW_CONNECTION_ATTEMPT");
958                         break;
959                     case FAILURE_REDUNDANT_CONNECTION_ATTEMPT:
960                         sb.append("REDUNDANT_CONNECTION_ATTEMPT");
961                         break;
962                     case FAILURE_ROAM_TIMEOUT:
963                         sb.append("ROAM_TIMEOUT");
964                         break;
965                     case FAILURE_DHCP:
966                         sb.append("DHCP");
967                         break;
968                     case FAILURE_ASSOCIATION_TIMED_OUT:
969                         sb.append("ASSOCIATION_TIMED_OUT");
970                         break;
971                     default:
972                         sb.append("UNKNOWN");
973                         break;
974                 }
975                 sb.append(", connectivityLevelFailureCode=");
976                 switch(mConnectionEvent.connectivityLevelFailureCode) {
977                     case WifiMetricsProto.ConnectionEvent.HLF_NONE:
978                         sb.append("NONE");
979                         break;
980                     case WifiMetricsProto.ConnectionEvent.HLF_DHCP:
981                         sb.append("DHCP");
982                         break;
983                     case WifiMetricsProto.ConnectionEvent.HLF_NO_INTERNET:
984                         sb.append("NO_INTERNET");
985                         break;
986                     case WifiMetricsProto.ConnectionEvent.HLF_UNWANTED:
987                         sb.append("UNWANTED");
988                         break;
989                     default:
990                         sb.append("UNKNOWN");
991                         break;
992                 }
993                 sb.append(", signalStrength=");
994                 sb.append(mConnectionEvent.signalStrength);
995                 sb.append(", wifiState=");
996                 switch(mWifiState) {
997                     case WifiMetricsProto.WifiLog.WIFI_DISABLED:
998                         sb.append("WIFI_DISABLED");
999                         break;
1000                     case WifiMetricsProto.WifiLog.WIFI_DISCONNECTED:
1001                         sb.append("WIFI_DISCONNECTED");
1002                         break;
1003                     case WifiMetricsProto.WifiLog.WIFI_ASSOCIATED:
1004                         sb.append("WIFI_ASSOCIATED");
1005                         break;
1006                     default:
1007                         sb.append("WIFI_UNKNOWN");
1008                         break;
1009                 }
1010                 sb.append(", screenOn=");
1011                 sb.append(mScreenOn);
1012                 sb.append(", mRouterFingerprint=");
1013                 sb.append(mRouterFingerPrint.toString());
1014                 sb.append(", useRandomizedMac=");
1015                 sb.append(mConnectionEvent.useRandomizedMac);
1016                 sb.append(", useAggressiveMac=" + mConnectionEvent.useAggressiveMac);
1017                 sb.append(", connectionNominator=");
1018                 switch (mConnectionEvent.connectionNominator) {
1019                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_UNKNOWN:
1020                         sb.append("NOMINATOR_UNKNOWN");
1021                         break;
1022                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL:
1023                         sb.append("NOMINATOR_MANUAL");
1024                         break;
1025                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED:
1026                         sb.append("NOMINATOR_SAVED");
1027                         break;
1028                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_SUGGESTION:
1029                         sb.append("NOMINATOR_SUGGESTION");
1030                         break;
1031                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_PASSPOINT:
1032                         sb.append("NOMINATOR_PASSPOINT");
1033                         break;
1034                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_CARRIER:
1035                         sb.append("NOMINATOR_CARRIER");
1036                         break;
1037                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_EXTERNAL_SCORED:
1038                         sb.append("NOMINATOR_EXTERNAL_SCORED");
1039                         break;
1040                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER:
1041                         sb.append("NOMINATOR_SPECIFIER");
1042                         break;
1043                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED_USER_CONNECT_CHOICE:
1044                         sb.append("NOMINATOR_SAVED_USER_CONNECT_CHOICE");
1045                         break;
1046                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_OPEN_NETWORK_AVAILABLE:
1047                         sb.append("NOMINATOR_OPEN_NETWORK_AVAILABLE");
1048                         break;
1049                     default:
1050                         sb.append(String.format("UnrecognizedNominator(%d)",
1051                                 mConnectionEvent.connectionNominator));
1052                 }
1053                 sb.append(", networkSelectorExperimentId=");
1054                 sb.append(mConnectionEvent.networkSelectorExperimentId);
1055                 sb.append(", numBssidInBlocklist=" + mConnectionEvent.numBssidInBlocklist);
1056                 sb.append(", level2FailureReason=");
1057                 switch(mConnectionEvent.level2FailureReason) {
1058                     case WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE:
1059                         sb.append("AUTH_FAILURE_NONE");
1060                         break;
1061                     case WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_TIMEOUT:
1062                         sb.append("AUTH_FAILURE_TIMEOUT");
1063                         break;
1064                     case WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD:
1065                         sb.append("AUTH_FAILURE_WRONG_PSWD");
1066                         break;
1067                     case WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_EAP_FAILURE:
1068                         sb.append("AUTH_FAILURE_EAP_FAILURE");
1069                         break;
1070                     default:
1071                         sb.append("FAILURE_REASON_UNKNOWN");
1072                         break;
1073                 }
1074                 sb.append(", networkType=");
1075                 switch(mConnectionEvent.networkType) {
1076                     case WifiMetricsProto.ConnectionEvent.TYPE_UNKNOWN:
1077                         sb.append("TYPE_UNKNOWN");
1078                         break;
1079                     case WifiMetricsProto.ConnectionEvent.TYPE_WPA2:
1080                         sb.append("TYPE_WPA2");
1081                         break;
1082                     case WifiMetricsProto.ConnectionEvent.TYPE_WPA3:
1083                         sb.append("TYPE_WPA3");
1084                         break;
1085                     case WifiMetricsProto.ConnectionEvent.TYPE_PASSPOINT:
1086                         sb.append("TYPE_PASSPOINT");
1087                         break;
1088                     case WifiMetricsProto.ConnectionEvent.TYPE_EAP:
1089                         sb.append("TYPE_EAP");
1090                         break;
1091                     case WifiMetricsProto.ConnectionEvent.TYPE_OWE:
1092                         sb.append("TYPE_OWE");
1093                         break;
1094                     case WifiMetricsProto.ConnectionEvent.TYPE_OPEN:
1095                         sb.append("TYPE_OPEN");
1096                         break;
1097                     case WifiMetricsProto.ConnectionEvent.TYPE_WAPI:
1098                         sb.append("TYPE_WAPI");
1099                         break;
1100                 }
1101                 sb.append(", networkCreator=");
1102                 switch (mConnectionEvent.networkCreator) {
1103                     case WifiMetricsProto.ConnectionEvent.CREATOR_UNKNOWN:
1104                         sb.append("CREATOR_UNKNOWN");
1105                         break;
1106                     case WifiMetricsProto.ConnectionEvent.CREATOR_USER:
1107                         sb.append("CREATOR_USER");
1108                         break;
1109                     case WifiMetricsProto.ConnectionEvent.CREATOR_CARRIER:
1110                         sb.append("CREATOR_CARRIER");
1111                         break;
1112                 }
1113                 sb.append(", numConsecutiveConnectionFailure="
1114                         + mConnectionEvent.numConsecutiveConnectionFailure);
1115                 sb.append(", isOsuProvisioned=" + mConnectionEvent.isOsuProvisioned);
1116             }
1117             return sb.toString();
1118         }
1119     }
1120 
1121     class WifiOffMetrics {
1122         public int numWifiOff = 0;
1123         public int numWifiOffDeferring = 0;
1124         public int numWifiOffDeferringTimeout = 0;
1125         public final IntCounter wifiOffDeferringTimeHistogram = new IntCounter();
1126 
toProto()1127         public WifiMetricsProto.WifiOffMetrics toProto() {
1128             WifiMetricsProto.WifiOffMetrics proto =
1129                     new WifiMetricsProto.WifiOffMetrics();
1130             proto.numWifiOff = numWifiOff;
1131             proto.numWifiOffDeferring = numWifiOffDeferring;
1132             proto.numWifiOffDeferringTimeout = numWifiOffDeferringTimeout;
1133             proto.wifiOffDeferringTimeHistogram = wifiOffDeferringTimeHistogram.toProto();
1134             return proto;
1135         }
1136 
clear()1137         public void clear() {
1138             numWifiOff = 0;
1139             numWifiOffDeferring = 0;
1140             numWifiOffDeferringTimeout = 0;
1141             wifiOffDeferringTimeHistogram.clear();
1142         }
1143 
1144         @Override
toString()1145         public String toString() {
1146             StringBuilder sb = new StringBuilder();
1147             sb.append("numWifiOff=")
1148                     .append(numWifiOff)
1149                     .append(", numWifiOffDeferring=")
1150                     .append(numWifiOffDeferring)
1151                     .append(", numWifiOffDeferringTimeout=")
1152                     .append(numWifiOffDeferringTimeout)
1153                     .append(", wifiOffDeferringTimeHistogram=")
1154                     .append(wifiOffDeferringTimeHistogram);
1155             return sb.toString();
1156         }
1157     }
1158 
1159     class SoftApConfigLimitationMetrics {
1160         // Collect the number of softap security setting reset to default during the restore
1161         public int numSecurityTypeResetToDefault = 0;
1162         // Collect the number of softap max client setting reset to default during the restore
1163         public int numMaxClientSettingResetToDefault = 0;
1164         // Collect the number of softap client control setting reset to default during the restore
1165         public int numClientControlByUserResetToDefault = 0;
1166         // Collect the max client setting when reach it cause client is blocked
1167         public final IntCounter maxClientSettingWhenReachHistogram = new IntCounter();
1168 
toProto()1169         public WifiMetricsProto.SoftApConfigLimitationMetrics toProto() {
1170             WifiMetricsProto.SoftApConfigLimitationMetrics proto =
1171                     new WifiMetricsProto.SoftApConfigLimitationMetrics();
1172             proto.numSecurityTypeResetToDefault = numSecurityTypeResetToDefault;
1173             proto.numMaxClientSettingResetToDefault = numMaxClientSettingResetToDefault;
1174             proto.numClientControlByUserResetToDefault = numClientControlByUserResetToDefault;
1175             proto.maxClientSettingWhenReachHistogram = maxClientSettingWhenReachHistogram.toProto();
1176             return proto;
1177         }
1178 
clear()1179         public void clear() {
1180             numSecurityTypeResetToDefault = 0;
1181             numMaxClientSettingResetToDefault = 0;
1182             numClientControlByUserResetToDefault = 0;
1183             maxClientSettingWhenReachHistogram.clear();
1184         }
1185 
1186         @Override
toString()1187         public String toString() {
1188             StringBuilder sb = new StringBuilder();
1189             sb.append("numSecurityTypeResetToDefault=")
1190                     .append(numSecurityTypeResetToDefault)
1191                     .append(", numMaxClientSettingResetToDefault=")
1192                     .append(numMaxClientSettingResetToDefault)
1193                     .append(", numClientControlByUserResetToDefault=")
1194                     .append(numClientControlByUserResetToDefault)
1195                     .append(", maxClientSettingWhenReachHistogram=")
1196                     .append(maxClientSettingWhenReachHistogram);
1197             return sb.toString();
1198         }
1199     }
1200 
1201     class CarrierWifiMetrics {
1202         public int numConnectionSuccess = 0;
1203         public int numConnectionAuthFailure = 0;
1204         public int numConnectionNonAuthFailure = 0;
1205 
toProto()1206         public WifiMetricsProto.CarrierWifiMetrics toProto() {
1207             WifiMetricsProto.CarrierWifiMetrics proto =
1208                     new WifiMetricsProto.CarrierWifiMetrics();
1209             proto.numConnectionSuccess = numConnectionSuccess;
1210             proto.numConnectionAuthFailure = numConnectionAuthFailure;
1211             proto.numConnectionNonAuthFailure = numConnectionNonAuthFailure;
1212             return proto;
1213         }
1214 
clear()1215         public void clear() {
1216             numConnectionSuccess = 0;
1217             numConnectionAuthFailure = 0;
1218             numConnectionNonAuthFailure = 0;
1219         }
1220 
1221         @Override
toString()1222         public String toString() {
1223             StringBuilder sb = new StringBuilder();
1224             sb.append("numConnectionSuccess=")
1225                     .append(numConnectionSuccess)
1226                     .append(", numConnectionAuthFailure=")
1227                     .append(numConnectionAuthFailure)
1228                     .append(", numConnectionNonAuthFailure")
1229                     .append(numConnectionNonAuthFailure);
1230             return sb.toString();
1231         }
1232     }
1233 
WifiMetrics(Context context, FrameworkFacade facade, Clock clock, Looper looper, WifiAwareMetrics awareMetrics, RttMetrics rttMetrics, WifiPowerMetrics wifiPowerMetrics, WifiP2pMetrics wifiP2pMetrics, DppMetrics dppMetrics)1234     public WifiMetrics(Context context, FrameworkFacade facade, Clock clock, Looper looper,
1235             WifiAwareMetrics awareMetrics, RttMetrics rttMetrics,
1236             WifiPowerMetrics wifiPowerMetrics, WifiP2pMetrics wifiP2pMetrics,
1237             DppMetrics dppMetrics) {
1238         mContext = context;
1239         mFacade = facade;
1240         mClock = clock;
1241         mCurrentConnectionEvent = null;
1242         mScreenOn = true;
1243         mWifiState = WifiMetricsProto.WifiLog.WIFI_DISABLED;
1244         mRecordStartTimeSec = mClock.getElapsedSinceBootMillis() / 1000;
1245         mWifiAwareMetrics = awareMetrics;
1246         mRttMetrics = rttMetrics;
1247         mWifiPowerMetrics = wifiPowerMetrics;
1248         mWifiP2pMetrics = wifiP2pMetrics;
1249         mDppMetrics = dppMetrics;
1250         mHandler = new Handler(looper) {
1251             public void handleMessage(Message msg) {
1252                 synchronized (mLock) {
1253                     processMessage(msg);
1254                 }
1255             }
1256         };
1257 
1258         mCurrentDeviceMobilityState = WifiManager.DEVICE_MOBILITY_STATE_UNKNOWN;
1259         DeviceMobilityStatePnoScanStats unknownStateStats =
1260                 getOrCreateDeviceMobilityStatePnoScanStats(mCurrentDeviceMobilityState);
1261         unknownStateStats.numTimesEnteredState++;
1262         mCurrentDeviceMobilityStateStartMs = mClock.getElapsedSinceBootMillis();
1263         mCurrentDeviceMobilityStatePnoScanStartMs = -1;
1264         mOnWifiUsabilityListeners =
1265                 new ExternalCallbackTracker<IOnWifiUsabilityStatsListener>(mHandler);
1266     }
1267 
1268     /** Sets internal ScoringParams member */
setScoringParams(ScoringParams scoringParams)1269     public void setScoringParams(ScoringParams scoringParams) {
1270         mScoringParams = scoringParams;
1271     }
1272 
1273     /** Sets internal WifiConfigManager member */
setWifiConfigManager(WifiConfigManager wifiConfigManager)1274     public void setWifiConfigManager(WifiConfigManager wifiConfigManager) {
1275         mWifiConfigManager = wifiConfigManager;
1276     }
1277 
1278     /** Sets internal WifiNetworkSelector member */
setWifiNetworkSelector(WifiNetworkSelector wifiNetworkSelector)1279     public void setWifiNetworkSelector(WifiNetworkSelector wifiNetworkSelector) {
1280         mWifiNetworkSelector = wifiNetworkSelector;
1281     }
1282 
1283     /** Sets internal PasspointManager member */
setPasspointManager(PasspointManager passpointManager)1284     public void setPasspointManager(PasspointManager passpointManager) {
1285         mPasspointManager = passpointManager;
1286     }
1287 
1288     /** Sets internal WifiDataStall member */
setWifiDataStall(WifiDataStall wifiDataStall)1289     public void setWifiDataStall(WifiDataStall wifiDataStall) {
1290         mWifiDataStall = wifiDataStall;
1291     }
1292 
1293     /** Sets internal BssidBlocklistMonitor member */
setBssidBlocklistMonitor(BssidBlocklistMonitor bssidBlocklistMonitor)1294     public void setBssidBlocklistMonitor(BssidBlocklistMonitor bssidBlocklistMonitor) {
1295         mBssidBlocklistMonitor = bssidBlocklistMonitor;
1296     }
1297 
1298     /** Sets internal WifiHealthMonitor member */
setWifiHealthMonitor(WifiHealthMonitor wifiHealthMonitor)1299     public void setWifiHealthMonitor(WifiHealthMonitor wifiHealthMonitor) {
1300         mWifiHealthMonitor = wifiHealthMonitor;
1301     }
1302 
1303     /** Sets internal WifiScoreCard member */
setWifiScoreCard(WifiScoreCard wifiScoreCard)1304     public void setWifiScoreCard(WifiScoreCard wifiScoreCard) {
1305         mWifiScoreCard = wifiScoreCard;
1306     }
1307 
1308     /**
1309      * Increment cumulative counters for link layer stats.
1310      * @param newStats
1311      */
incrementWifiLinkLayerUsageStats(WifiLinkLayerStats newStats)1312     public void incrementWifiLinkLayerUsageStats(WifiLinkLayerStats newStats) {
1313         if (newStats == null) {
1314             return;
1315         }
1316         if (mLastLinkLayerStats == null) {
1317             mLastLinkLayerStats = newStats;
1318             return;
1319         }
1320         if (!newLinkLayerStatsIsValid(mLastLinkLayerStats, newStats)) {
1321             // This could mean the radio chip is reset or the data is incorrectly reported.
1322             // Don't increment any counts and discard the possibly corrupt |newStats| completely.
1323             mLastLinkLayerStats = null;
1324             return;
1325         }
1326         mWifiLinkLayerUsageStats.loggingDurationMs +=
1327                 (newStats.timeStampInMs - mLastLinkLayerStats.timeStampInMs);
1328         mWifiLinkLayerUsageStats.radioOnTimeMs += (newStats.on_time - mLastLinkLayerStats.on_time);
1329         mWifiLinkLayerUsageStats.radioTxTimeMs += (newStats.tx_time - mLastLinkLayerStats.tx_time);
1330         mWifiLinkLayerUsageStats.radioRxTimeMs += (newStats.rx_time - mLastLinkLayerStats.rx_time);
1331         mWifiLinkLayerUsageStats.radioScanTimeMs +=
1332                 (newStats.on_time_scan - mLastLinkLayerStats.on_time_scan);
1333         mWifiLinkLayerUsageStats.radioNanScanTimeMs +=
1334                 (newStats.on_time_nan_scan - mLastLinkLayerStats.on_time_nan_scan);
1335         mWifiLinkLayerUsageStats.radioBackgroundScanTimeMs +=
1336                 (newStats.on_time_background_scan - mLastLinkLayerStats.on_time_background_scan);
1337         mWifiLinkLayerUsageStats.radioRoamScanTimeMs +=
1338                 (newStats.on_time_roam_scan - mLastLinkLayerStats.on_time_roam_scan);
1339         mWifiLinkLayerUsageStats.radioPnoScanTimeMs +=
1340                 (newStats.on_time_pno_scan - mLastLinkLayerStats.on_time_pno_scan);
1341         mWifiLinkLayerUsageStats.radioHs20ScanTimeMs +=
1342                 (newStats.on_time_hs20_scan - mLastLinkLayerStats.on_time_hs20_scan);
1343         mLastLinkLayerStats = newStats;
1344     }
1345 
newLinkLayerStatsIsValid(WifiLinkLayerStats oldStats, WifiLinkLayerStats newStats)1346     private boolean newLinkLayerStatsIsValid(WifiLinkLayerStats oldStats,
1347             WifiLinkLayerStats newStats) {
1348         if (newStats.on_time < oldStats.on_time
1349                 || newStats.tx_time < oldStats.tx_time
1350                 || newStats.rx_time < oldStats.rx_time
1351                 || newStats.on_time_scan < oldStats.on_time_scan) {
1352             return false;
1353         }
1354         return true;
1355     }
1356 
1357     /**
1358      * Increment total number of attempts to start a pno scan
1359      */
incrementPnoScanStartAttemptCount()1360     public void incrementPnoScanStartAttemptCount() {
1361         synchronized (mLock) {
1362             mPnoScanMetrics.numPnoScanAttempts++;
1363         }
1364     }
1365 
1366     /**
1367      * Increment total number of attempts with pno scan failed
1368      */
incrementPnoScanFailedCount()1369     public void incrementPnoScanFailedCount() {
1370         synchronized (mLock) {
1371             mPnoScanMetrics.numPnoScanFailed++;
1372         }
1373     }
1374 
1375     /**
1376      * Increment number of times pno scan found a result
1377      */
incrementPnoFoundNetworkEventCount()1378     public void incrementPnoFoundNetworkEventCount() {
1379         synchronized (mLock) {
1380             mPnoScanMetrics.numPnoFoundNetworkEvents++;
1381         }
1382     }
1383 
1384     // Values used for indexing SystemStateEntries
1385     private static final int SCREEN_ON = 1;
1386     private static final int SCREEN_OFF = 0;
1387 
1388     /**
1389      * Create a new connection event and check if the new one overlaps with previous one.
1390      * Call when wifi attempts to make a new network connection
1391      * If there is a current 'un-ended' connection event, it will be ended with UNKNOWN connectivity
1392      * failure code.
1393      * Gathers and sets the RouterFingerPrint data as well
1394      *
1395      * @param config WifiConfiguration of the config used for the current connection attempt
1396      * @param roamType Roam type that caused connection attempt, see WifiMetricsProto.WifiLog.ROAM_X
1397      * @return The duration in ms since the last unfinished connection attempt,
1398      * or 0 if there is no unfinished connection
1399      */
startConnectionEvent( WifiConfiguration config, String targetBSSID, int roamType)1400     public int startConnectionEvent(
1401             WifiConfiguration config, String targetBSSID, int roamType) {
1402         synchronized (mLock) {
1403             int overlapWithLastConnectionMs = 0;
1404             if (mCurrentConnectionEvent != null) {
1405                 overlapWithLastConnectionMs = (int) (mClock.getElapsedSinceBootMillis()
1406                         - mCurrentConnectionEvent.mRealStartTime);
1407                 //Is this new Connection Event the same as the current one
1408                 if (mCurrentConnectionEvent.mConfigSsid != null
1409                         && mCurrentConnectionEvent.mConfigBssid != null
1410                         && config != null
1411                         && mCurrentConnectionEvent.mConfigSsid.equals(config.SSID)
1412                         && (mCurrentConnectionEvent.mConfigBssid.equals("any")
1413                         || mCurrentConnectionEvent.mConfigBssid.equals(targetBSSID))) {
1414                     mCurrentConnectionEvent.mConfigBssid = targetBSSID;
1415                     // End Connection Event due to new connection attempt to the same network
1416                     endConnectionEvent(ConnectionEvent.FAILURE_REDUNDANT_CONNECTION_ATTEMPT,
1417                             WifiMetricsProto.ConnectionEvent.HLF_NONE,
1418                             WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
1419                 } else {
1420                     // End Connection Event due to new connection attempt to different network
1421                     endConnectionEvent(ConnectionEvent.FAILURE_NEW_CONNECTION_ATTEMPT,
1422                             WifiMetricsProto.ConnectionEvent.HLF_NONE,
1423                             WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
1424                 }
1425             }
1426             //If past maximum connection events, start removing the oldest
1427             while(mConnectionEventList.size() >= MAX_CONNECTION_EVENTS) {
1428                 mConnectionEventList.remove(0);
1429             }
1430             mCurrentConnectionEvent = new ConnectionEvent();
1431             mCurrentConnectionEvent.mConnectionEvent.startTimeMillis =
1432                     mClock.getWallClockMillis();
1433             mCurrentConnectionEvent.mConfigBssid = targetBSSID;
1434             mCurrentConnectionEvent.mConnectionEvent.roamType = roamType;
1435             mCurrentConnectionEvent.mConnectionEvent.networkSelectorExperimentId =
1436                     mNetworkSelectorExperimentId;
1437             mCurrentConnectionEvent.mRouterFingerPrint.updateFromWifiConfiguration(config);
1438             mCurrentConnectionEvent.mConfigBssid = "any";
1439             mCurrentConnectionEvent.mRealStartTime = mClock.getElapsedSinceBootMillis();
1440             mCurrentConnectionEvent.mWifiState = mWifiState;
1441             mCurrentConnectionEvent.mScreenOn = mScreenOn;
1442             mConnectionEventList.add(mCurrentConnectionEvent);
1443             mScanResultRssiTimestampMillis = -1;
1444             if (config != null) {
1445                 mCurrentConnectionEvent.mConnectionEvent.useRandomizedMac =
1446                         config.macRandomizationSetting
1447                         == WifiConfiguration.RANDOMIZATION_PERSISTENT;
1448                 mCurrentConnectionEvent.mConnectionEvent.useAggressiveMac =
1449                         mWifiConfigManager.shouldUseAggressiveRandomization(config);
1450                 mCurrentConnectionEvent.mConnectionEvent.connectionNominator =
1451                         mNetworkIdToNominatorId.get(config.networkId,
1452                                 WifiMetricsProto.ConnectionEvent.NOMINATOR_UNKNOWN);
1453                 ScanResult candidate = config.getNetworkSelectionStatus().getCandidate();
1454                 if (candidate != null) {
1455                     // Cache the RSSI of the candidate, as the connection event level is updated
1456                     // from other sources (polls, bssid_associations) and delta requires the
1457                     // scanResult rssi
1458                     mScanResultRssi = candidate.level;
1459                     mScanResultRssiTimestampMillis = mClock.getElapsedSinceBootMillis();
1460                 }
1461                 mCurrentConnectionEvent.mConnectionEvent.numBssidInBlocklist =
1462                         mBssidBlocklistMonitor.getNumBlockedBssidsForSsid(config.SSID);
1463                 mCurrentConnectionEvent.mConnectionEvent.networkType =
1464                         WifiMetricsProto.ConnectionEvent.TYPE_UNKNOWN;
1465                 mCurrentConnectionEvent.mConnectionEvent.isOsuProvisioned = false;
1466                 if (config.isPasspoint()) {
1467                     mCurrentConnectionEvent.mConnectionEvent.networkType =
1468                             WifiMetricsProto.ConnectionEvent.TYPE_PASSPOINT;
1469                     mCurrentConnectionEvent.mConnectionEvent.isOsuProvisioned =
1470                             !TextUtils.isEmpty(config.updateIdentifier);
1471                 } else if (WifiConfigurationUtil.isConfigForSaeNetwork(config)) {
1472                     mCurrentConnectionEvent.mConnectionEvent.networkType =
1473                             WifiMetricsProto.ConnectionEvent.TYPE_WPA3;
1474                 } else if (WifiConfigurationUtil.isConfigForWapiPskNetwork(config)) {
1475                     mCurrentConnectionEvent.mConnectionEvent.networkType =
1476                             WifiMetricsProto.ConnectionEvent.TYPE_WAPI;
1477                 } else if (WifiConfigurationUtil.isConfigForWapiCertNetwork(config)) {
1478                     mCurrentConnectionEvent.mConnectionEvent.networkType =
1479                             WifiMetricsProto.ConnectionEvent.TYPE_WAPI;
1480                 } else if (WifiConfigurationUtil.isConfigForPskNetwork(config)) {
1481                     mCurrentConnectionEvent.mConnectionEvent.networkType =
1482                             WifiMetricsProto.ConnectionEvent.TYPE_WPA2;
1483                 } else if (WifiConfigurationUtil.isConfigForEapNetwork(config)) {
1484                     mCurrentConnectionEvent.mConnectionEvent.networkType =
1485                             WifiMetricsProto.ConnectionEvent.TYPE_EAP;
1486                 } else if (WifiConfigurationUtil.isConfigForOweNetwork(config)) {
1487                     mCurrentConnectionEvent.mConnectionEvent.networkType =
1488                             WifiMetricsProto.ConnectionEvent.TYPE_OWE;
1489                 } else if (WifiConfigurationUtil.isConfigForOpenNetwork(config)) {
1490                     mCurrentConnectionEvent.mConnectionEvent.networkType =
1491                             WifiMetricsProto.ConnectionEvent.TYPE_OPEN;
1492                 }
1493 
1494                 if (!config.fromWifiNetworkSuggestion) {
1495                     mCurrentConnectionEvent.mConnectionEvent.networkCreator =
1496                             WifiMetricsProto.ConnectionEvent.CREATOR_USER;
1497                 } else if (config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) {
1498                     mCurrentConnectionEvent.mConnectionEvent.networkCreator =
1499                             WifiMetricsProto.ConnectionEvent.CREATOR_CARRIER;
1500                 } else {
1501                     mCurrentConnectionEvent.mConnectionEvent.networkCreator =
1502                             WifiMetricsProto.ConnectionEvent.CREATOR_UNKNOWN;
1503                 }
1504 
1505                 mCurrentConnectionEvent.mConnectionEvent.screenOn = mScreenOn;
1506                 if (mCurrentConnectionEvent.mConfigSsid != null) {
1507                     WifiScoreCard.NetworkConnectionStats recentStats = mWifiScoreCard.lookupNetwork(
1508                             mCurrentConnectionEvent.mConfigSsid).getRecentStats();
1509                     mCurrentConnectionEvent.mConnectionEvent.numConsecutiveConnectionFailure =
1510                             recentStats.getCount(WifiScoreCard.CNT_CONSECUTIVE_CONNECTION_FAILURE);
1511                 }
1512             }
1513             return overlapWithLastConnectionMs;
1514         }
1515     }
1516 
1517     /**
1518      * set the RoamType of the current ConnectionEvent (if any)
1519      */
setConnectionEventRoamType(int roamType)1520     public void setConnectionEventRoamType(int roamType) {
1521         synchronized (mLock) {
1522             if (mCurrentConnectionEvent != null) {
1523                 mCurrentConnectionEvent.mConnectionEvent.roamType = roamType;
1524             }
1525         }
1526     }
1527 
1528     /**
1529      * Set AP related metrics from ScanDetail
1530      */
setConnectionScanDetail(ScanDetail scanDetail)1531     public void setConnectionScanDetail(ScanDetail scanDetail) {
1532         synchronized (mLock) {
1533             if (mCurrentConnectionEvent != null && scanDetail != null) {
1534                 NetworkDetail networkDetail = scanDetail.getNetworkDetail();
1535                 ScanResult scanResult = scanDetail.getScanResult();
1536                 //Ensure that we have a networkDetail, and that it corresponds to the currently
1537                 //tracked connection attempt
1538                 if (networkDetail != null && scanResult != null
1539                         && mCurrentConnectionEvent.mConfigSsid != null
1540                         && mCurrentConnectionEvent.mConfigSsid
1541                         .equals("\"" + networkDetail.getSSID() + "\"")) {
1542                     updateMetricsFromNetworkDetail(networkDetail);
1543                     updateMetricsFromScanResult(scanResult);
1544                 }
1545             }
1546         }
1547     }
1548 
1549     /**
1550      * Set PMK cache status for a connection event
1551      */
setConnectionPmkCache(boolean isEnabled)1552     public void setConnectionPmkCache(boolean isEnabled) {
1553         synchronized (mLock) {
1554             if (mCurrentConnectionEvent != null) {
1555                 mCurrentConnectionEvent.mRouterFingerPrint.setPmkCache(isEnabled);
1556             }
1557         }
1558     }
1559 
1560     /**
1561      * Set the max link speed supported by current network
1562      */
setConnectionMaxSupportedLinkSpeedMbps(int maxSupportedTxLinkSpeedMbps, int maxSupportedRxLinkSpeedMbps)1563     public void setConnectionMaxSupportedLinkSpeedMbps(int maxSupportedTxLinkSpeedMbps,
1564             int maxSupportedRxLinkSpeedMbps) {
1565         synchronized (mLock) {
1566             if (mCurrentConnectionEvent != null) {
1567                 mCurrentConnectionEvent.mRouterFingerPrint.setMaxSupportedLinkSpeedMbps(
1568                         maxSupportedTxLinkSpeedMbps, maxSupportedRxLinkSpeedMbps);
1569             }
1570         }
1571     }
1572 
1573     /**
1574      * End a Connection event record. Call when wifi connection attempt succeeds or fails.
1575      * If a Connection event has not been started and is active when .end is called, then this
1576      * method will do nothing.
1577      *
1578      * @param level2FailureCode Level 2 failure code returned by supplicant
1579      * @param connectivityFailureCode WifiMetricsProto.ConnectionEvent.HLF_X
1580      * @param level2FailureReason Breakdown of level2FailureCode with more detailed reason
1581      */
endConnectionEvent(int level2FailureCode, int connectivityFailureCode, int level2FailureReason)1582     public void endConnectionEvent(int level2FailureCode, int connectivityFailureCode,
1583             int level2FailureReason) {
1584         synchronized (mLock) {
1585             if (mCurrentConnectionEvent != null) {
1586                 boolean result = (level2FailureCode == 1)
1587                         && (connectivityFailureCode == WifiMetricsProto.ConnectionEvent.HLF_NONE);
1588                 mCurrentConnectionEvent.mConnectionEvent.connectionResult = result ? 1 : 0;
1589                 mCurrentConnectionEvent.mRealEndTime = mClock.getElapsedSinceBootMillis();
1590                 mCurrentConnectionEvent.mConnectionEvent.durationTakenToConnectMillis = (int)
1591                         (mCurrentConnectionEvent.mRealEndTime
1592                         - mCurrentConnectionEvent.mRealStartTime);
1593                 mCurrentConnectionEvent.mConnectionEvent.level2FailureCode = level2FailureCode;
1594                 mCurrentConnectionEvent.mConnectionEvent.connectivityLevelFailureCode =
1595                         connectivityFailureCode;
1596                 mCurrentConnectionEvent.mConnectionEvent.level2FailureReason = level2FailureReason;
1597 
1598                 // Write metrics to statsd
1599                 int wwFailureCode = getConnectionResultFailureCode(level2FailureCode,
1600                         level2FailureReason);
1601                 if (wwFailureCode != -1) {
1602                     WifiStatsLog.write(WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED, result,
1603                             wwFailureCode, mCurrentConnectionEvent.mConnectionEvent.signalStrength);
1604                 }
1605                 // ConnectionEvent already added to ConnectionEvents List. Safe to null current here
1606                 mCurrentConnectionEvent = null;
1607                 if (!result) {
1608                     mScanResultRssiTimestampMillis = -1;
1609                 }
1610             }
1611         }
1612     }
1613 
getConnectionResultFailureCode(int level2FailureCode, int level2FailureReason)1614     private int getConnectionResultFailureCode(int level2FailureCode, int level2FailureReason) {
1615         switch (level2FailureCode) {
1616             case ConnectionEvent.FAILURE_NONE:
1617                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_UNKNOWN;
1618             case ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT:
1619                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_ASSOCIATION_TIMEOUT;
1620             case ConnectionEvent.FAILURE_ASSOCIATION_REJECTION:
1621                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_ASSOCIATION_REJECTION;
1622             case ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE:
1623                 switch (level2FailureReason) {
1624                     case WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_EAP_FAILURE:
1625                         return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_AUTHENTICATION_EAP;
1626                     case WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD:
1627                         return -1;
1628                     default:
1629                         return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_AUTHENTICATION_GENERAL;
1630                 }
1631             case ConnectionEvent.FAILURE_DHCP:
1632                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_DHCP;
1633             case ConnectionEvent.FAILURE_NETWORK_DISCONNECTION:
1634                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_NETWORK_DISCONNECTION;
1635             case ConnectionEvent.FAILURE_ROAM_TIMEOUT:
1636                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_ROAM_TIMEOUT;
1637             case ConnectionEvent.FAILURE_NEW_CONNECTION_ATTEMPT:
1638             case ConnectionEvent.FAILURE_REDUNDANT_CONNECTION_ATTEMPT:
1639                 return -1;
1640             default:
1641                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_UNKNOWN;
1642         }
1643     }
1644 
1645     /**
1646      * Set ConnectionEvent DTIM Interval (if set), and 802.11 Connection mode, from NetworkDetail
1647      */
updateMetricsFromNetworkDetail(NetworkDetail networkDetail)1648     private void updateMetricsFromNetworkDetail(NetworkDetail networkDetail) {
1649         int dtimInterval = networkDetail.getDtimInterval();
1650         if (dtimInterval > 0) {
1651             mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.dtim =
1652                     dtimInterval;
1653         }
1654         int connectionWifiMode;
1655         switch (networkDetail.getWifiMode()) {
1656             case InformationElementUtil.WifiMode.MODE_UNDEFINED:
1657                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_UNKNOWN;
1658                 break;
1659             case InformationElementUtil.WifiMode.MODE_11A:
1660                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_A;
1661                 break;
1662             case InformationElementUtil.WifiMode.MODE_11B:
1663                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_B;
1664                 break;
1665             case InformationElementUtil.WifiMode.MODE_11G:
1666                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_G;
1667                 break;
1668             case InformationElementUtil.WifiMode.MODE_11N:
1669                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_N;
1670                 break;
1671             case InformationElementUtil.WifiMode.MODE_11AC  :
1672                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_AC;
1673                 break;
1674             case InformationElementUtil.WifiMode.MODE_11AX  :
1675                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_AX;
1676                 break;
1677             default:
1678                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_OTHER;
1679                 break;
1680         }
1681         mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto
1682                 .routerTechnology = connectionWifiMode;
1683 
1684         if (networkDetail.isMboSupported()) {
1685             mWifiLogProto.numConnectToNetworkSupportingMbo++;
1686             if (networkDetail.isOceSupported()) {
1687                 mWifiLogProto.numConnectToNetworkSupportingOce++;
1688             }
1689         }
1690     }
1691 
1692     /**
1693      * Set ConnectionEvent RSSI and authentication type from ScanResult
1694      */
updateMetricsFromScanResult(ScanResult scanResult)1695     private void updateMetricsFromScanResult(ScanResult scanResult) {
1696         mCurrentConnectionEvent.mConnectionEvent.signalStrength = scanResult.level;
1697         mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication =
1698                 WifiMetricsProto.RouterFingerPrint.AUTH_OPEN;
1699         mCurrentConnectionEvent.mConfigBssid = scanResult.BSSID;
1700         if (scanResult.capabilities != null) {
1701             if (ScanResultUtil.isScanResultForWepNetwork(scanResult)) {
1702                 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication =
1703                         WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL;
1704             } else if (ScanResultUtil.isScanResultForPskNetwork(scanResult)
1705                     || ScanResultUtil.isScanResultForSaeNetwork(scanResult)) {
1706                 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication =
1707                         WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL;
1708             } else if (ScanResultUtil.isScanResultForEapNetwork(scanResult)
1709                     || ScanResultUtil.isScanResultForEapSuiteBNetwork(scanResult)) {
1710                 mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication =
1711                         WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE;
1712             }
1713         }
1714         mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.channelInfo =
1715                 scanResult.frequency;
1716     }
1717 
setIsLocationEnabled(boolean enabled)1718     void setIsLocationEnabled(boolean enabled) {
1719         synchronized (mLock) {
1720             mWifiLogProto.isLocationEnabled = enabled;
1721         }
1722     }
1723 
setIsScanningAlwaysEnabled(boolean enabled)1724     void setIsScanningAlwaysEnabled(boolean enabled) {
1725         synchronized (mLock) {
1726             mWifiLogProto.isScanningAlwaysEnabled = enabled;
1727         }
1728     }
1729 
1730     /**
1731      * Developer options toggle value for verbose logging.
1732      */
setVerboseLoggingEnabled(boolean enabled)1733     public void setVerboseLoggingEnabled(boolean enabled) {
1734         synchronized (mLock) {
1735             mWifiLogProto.isVerboseLoggingEnabled = enabled;
1736         }
1737     }
1738 
1739     /**
1740      * Developer options toggle value for enhanced MAC randomization.
1741      */
setEnhancedMacRandomizationForceEnabled(boolean enabled)1742     public void setEnhancedMacRandomizationForceEnabled(boolean enabled) {
1743         synchronized (mLock) {
1744             mWifiLogProto.isEnhancedMacRandomizationForceEnabled = enabled;
1745         }
1746     }
1747 
1748     /**
1749      * Wifi wake feature toggle.
1750      */
setWifiWakeEnabled(boolean enabled)1751     public void setWifiWakeEnabled(boolean enabled) {
1752         synchronized (mLock) {
1753             mWifiLogProto.isWifiWakeEnabled = enabled;
1754         }
1755     }
1756 
1757     /**
1758      * Increment Non Empty Scan Results count
1759      */
incrementNonEmptyScanResultCount()1760     public void incrementNonEmptyScanResultCount() {
1761         if (DBG) Log.v(TAG, "incrementNonEmptyScanResultCount");
1762         synchronized (mLock) {
1763             mWifiLogProto.numNonEmptyScanResults++;
1764         }
1765     }
1766 
1767     /**
1768      * Increment Empty Scan Results count
1769      */
incrementEmptyScanResultCount()1770     public void incrementEmptyScanResultCount() {
1771         if (DBG) Log.v(TAG, "incrementEmptyScanResultCount");
1772         synchronized (mLock) {
1773             mWifiLogProto.numEmptyScanResults++;
1774         }
1775     }
1776 
1777     /**
1778      * Increment background scan count
1779      */
incrementBackgroundScanCount()1780     public void incrementBackgroundScanCount() {
1781         if (DBG) Log.v(TAG, "incrementBackgroundScanCount");
1782         synchronized (mLock) {
1783             mWifiLogProto.numBackgroundScans++;
1784         }
1785     }
1786 
1787     /**
1788      * Get Background scan count
1789      */
getBackgroundScanCount()1790     public int getBackgroundScanCount() {
1791         synchronized (mLock) {
1792             return mWifiLogProto.numBackgroundScans;
1793         }
1794     }
1795 
1796     /**
1797      * Increment oneshot scan count, and the associated WifiSystemScanStateCount entry
1798      */
incrementOneshotScanCount()1799     public void incrementOneshotScanCount() {
1800         synchronized (mLock) {
1801             mWifiLogProto.numOneshotScans++;
1802         }
1803         incrementWifiSystemScanStateCount(mWifiState, mScreenOn);
1804     }
1805 
1806     /**
1807      * Increment the count of oneshot scans that include DFS channels.
1808      */
incrementOneshotScanWithDfsCount()1809     public void incrementOneshotScanWithDfsCount() {
1810         synchronized (mLock) {
1811             mWifiLogProto.numOneshotHasDfsChannelScans++;
1812         }
1813     }
1814 
1815     /**
1816      * Increment connectivity oneshot scan count.
1817      */
incrementConnectivityOneshotScanCount()1818     public void incrementConnectivityOneshotScanCount() {
1819         synchronized (mLock) {
1820             mWifiLogProto.numConnectivityOneshotScans++;
1821         }
1822     }
1823 
1824     /**
1825      * Get oneshot scan count
1826      */
getOneshotScanCount()1827     public int getOneshotScanCount() {
1828         synchronized (mLock) {
1829             return mWifiLogProto.numOneshotScans;
1830         }
1831     }
1832 
1833     /**
1834      * Get connectivity oneshot scan count
1835      */
getConnectivityOneshotScanCount()1836     public int getConnectivityOneshotScanCount() {
1837         synchronized (mLock) {
1838             return mWifiLogProto.numConnectivityOneshotScans;
1839         }
1840     }
1841 
1842     /**
1843      * Get the count of oneshot scan requests that included DFS channels.
1844      */
getOneshotScanWithDfsCount()1845     public int getOneshotScanWithDfsCount() {
1846         synchronized (mLock) {
1847             return mWifiLogProto.numOneshotHasDfsChannelScans;
1848         }
1849     }
1850 
1851     /**
1852      * Increment oneshot scan count for external apps.
1853      */
incrementExternalAppOneshotScanRequestsCount()1854     public void incrementExternalAppOneshotScanRequestsCount() {
1855         synchronized (mLock) {
1856             mWifiLogProto.numExternalAppOneshotScanRequests++;
1857         }
1858     }
1859     /**
1860      * Increment oneshot scan throttle count for external foreground apps.
1861      */
incrementExternalForegroundAppOneshotScanRequestsThrottledCount()1862     public void incrementExternalForegroundAppOneshotScanRequestsThrottledCount() {
1863         synchronized (mLock) {
1864             mWifiLogProto.numExternalForegroundAppOneshotScanRequestsThrottled++;
1865         }
1866     }
1867 
1868     /**
1869      * Increment oneshot scan throttle count for external background apps.
1870      */
incrementExternalBackgroundAppOneshotScanRequestsThrottledCount()1871     public void incrementExternalBackgroundAppOneshotScanRequestsThrottledCount() {
1872         synchronized (mLock) {
1873             mWifiLogProto.numExternalBackgroundAppOneshotScanRequestsThrottled++;
1874         }
1875     }
1876 
returnCodeToString(int scanReturnCode)1877     private String returnCodeToString(int scanReturnCode) {
1878         switch(scanReturnCode){
1879             case WifiMetricsProto.WifiLog.SCAN_UNKNOWN:
1880                 return "SCAN_UNKNOWN";
1881             case WifiMetricsProto.WifiLog.SCAN_SUCCESS:
1882                 return "SCAN_SUCCESS";
1883             case WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED:
1884                 return "SCAN_FAILURE_INTERRUPTED";
1885             case WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION:
1886                 return "SCAN_FAILURE_INVALID_CONFIGURATION";
1887             case WifiMetricsProto.WifiLog.FAILURE_WIFI_DISABLED:
1888                 return "FAILURE_WIFI_DISABLED";
1889             default:
1890                 return "<UNKNOWN>";
1891         }
1892     }
1893 
1894     /**
1895      * Increment count of scan return code occurrence
1896      *
1897      * @param scanReturnCode Return code from scan attempt WifiMetricsProto.WifiLog.SCAN_X
1898      */
incrementScanReturnEntry(int scanReturnCode, int countToAdd)1899     public void incrementScanReturnEntry(int scanReturnCode, int countToAdd) {
1900         synchronized (mLock) {
1901             if (DBG) Log.v(TAG, "incrementScanReturnEntry " + returnCodeToString(scanReturnCode));
1902             int entry = mScanReturnEntries.get(scanReturnCode);
1903             entry += countToAdd;
1904             mScanReturnEntries.put(scanReturnCode, entry);
1905         }
1906     }
1907     /**
1908      * Get the count of this scanReturnCode
1909      * @param scanReturnCode that we are getting the count for
1910      */
getScanReturnEntry(int scanReturnCode)1911     public int getScanReturnEntry(int scanReturnCode) {
1912         synchronized (mLock) {
1913             return mScanReturnEntries.get(scanReturnCode);
1914         }
1915     }
1916 
wifiSystemStateToString(int state)1917     private String wifiSystemStateToString(int state) {
1918         switch(state){
1919             case WifiMetricsProto.WifiLog.WIFI_UNKNOWN:
1920                 return "WIFI_UNKNOWN";
1921             case WifiMetricsProto.WifiLog.WIFI_DISABLED:
1922                 return "WIFI_DISABLED";
1923             case WifiMetricsProto.WifiLog.WIFI_DISCONNECTED:
1924                 return "WIFI_DISCONNECTED";
1925             case WifiMetricsProto.WifiLog.WIFI_ASSOCIATED:
1926                 return "WIFI_ASSOCIATED";
1927             default:
1928                 return "default";
1929         }
1930     }
1931 
1932     /**
1933      * Increments the count of scans initiated by each wifi state, accounts for screenOn/Off
1934      *
1935      * @param state State of the system when scan was initiated, see WifiMetricsProto.WifiLog.WIFI_X
1936      * @param screenOn Is the screen on
1937      */
incrementWifiSystemScanStateCount(int state, boolean screenOn)1938     public void incrementWifiSystemScanStateCount(int state, boolean screenOn) {
1939         synchronized (mLock) {
1940             if (DBG) {
1941                 Log.v(TAG, "incrementWifiSystemScanStateCount " + wifiSystemStateToString(state)
1942                         + " " + screenOn);
1943             }
1944             int index = (state * 2) + (screenOn ? SCREEN_ON : SCREEN_OFF);
1945             int entry = mWifiSystemStateEntries.get(index);
1946             entry++;
1947             mWifiSystemStateEntries.put(index, entry);
1948         }
1949     }
1950 
1951     /**
1952      * Get the count of this system State Entry
1953      */
getSystemStateCount(int state, boolean screenOn)1954     public int getSystemStateCount(int state, boolean screenOn) {
1955         synchronized (mLock) {
1956             int index = state * 2 + (screenOn ? SCREEN_ON : SCREEN_OFF);
1957             return mWifiSystemStateEntries.get(index);
1958         }
1959     }
1960 
1961     /**
1962      * Increment number of times the Watchdog of Last Resort triggered, resetting the wifi stack
1963      */
incrementNumLastResortWatchdogTriggers()1964     public void incrementNumLastResortWatchdogTriggers() {
1965         synchronized (mLock) {
1966             mWifiLogProto.numLastResortWatchdogTriggers++;
1967         }
1968     }
1969     /**
1970      * @param count number of networks over bad association threshold when watchdog triggered
1971      */
addCountToNumLastResortWatchdogBadAssociationNetworksTotal(int count)1972     public void addCountToNumLastResortWatchdogBadAssociationNetworksTotal(int count) {
1973         synchronized (mLock) {
1974             mWifiLogProto.numLastResortWatchdogBadAssociationNetworksTotal += count;
1975         }
1976     }
1977     /**
1978      * @param count number of networks over bad authentication threshold when watchdog triggered
1979      */
addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal(int count)1980     public void addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal(int count) {
1981         synchronized (mLock) {
1982             mWifiLogProto.numLastResortWatchdogBadAuthenticationNetworksTotal += count;
1983         }
1984     }
1985     /**
1986      * @param count number of networks over bad dhcp threshold when watchdog triggered
1987      */
addCountToNumLastResortWatchdogBadDhcpNetworksTotal(int count)1988     public void addCountToNumLastResortWatchdogBadDhcpNetworksTotal(int count) {
1989         synchronized (mLock) {
1990             mWifiLogProto.numLastResortWatchdogBadDhcpNetworksTotal += count;
1991         }
1992     }
1993     /**
1994      * @param count number of networks over bad other threshold when watchdog triggered
1995      */
addCountToNumLastResortWatchdogBadOtherNetworksTotal(int count)1996     public void addCountToNumLastResortWatchdogBadOtherNetworksTotal(int count) {
1997         synchronized (mLock) {
1998             mWifiLogProto.numLastResortWatchdogBadOtherNetworksTotal += count;
1999         }
2000     }
2001     /**
2002      * @param count number of networks seen when watchdog triggered
2003      */
addCountToNumLastResortWatchdogAvailableNetworksTotal(int count)2004     public void addCountToNumLastResortWatchdogAvailableNetworksTotal(int count) {
2005         synchronized (mLock) {
2006             mWifiLogProto.numLastResortWatchdogAvailableNetworksTotal += count;
2007         }
2008     }
2009     /**
2010      * Increment count of triggers with atleast one bad association network
2011      */
incrementNumLastResortWatchdogTriggersWithBadAssociation()2012     public void incrementNumLastResortWatchdogTriggersWithBadAssociation() {
2013         synchronized (mLock) {
2014             mWifiLogProto.numLastResortWatchdogTriggersWithBadAssociation++;
2015         }
2016     }
2017     /**
2018      * Increment count of triggers with atleast one bad authentication network
2019      */
incrementNumLastResortWatchdogTriggersWithBadAuthentication()2020     public void incrementNumLastResortWatchdogTriggersWithBadAuthentication() {
2021         synchronized (mLock) {
2022             mWifiLogProto.numLastResortWatchdogTriggersWithBadAuthentication++;
2023         }
2024     }
2025     /**
2026      * Increment count of triggers with atleast one bad dhcp network
2027      */
incrementNumLastResortWatchdogTriggersWithBadDhcp()2028     public void incrementNumLastResortWatchdogTriggersWithBadDhcp() {
2029         synchronized (mLock) {
2030             mWifiLogProto.numLastResortWatchdogTriggersWithBadDhcp++;
2031         }
2032     }
2033     /**
2034      * Increment count of triggers with atleast one bad other network
2035      */
incrementNumLastResortWatchdogTriggersWithBadOther()2036     public void incrementNumLastResortWatchdogTriggersWithBadOther() {
2037         synchronized (mLock) {
2038             mWifiLogProto.numLastResortWatchdogTriggersWithBadOther++;
2039         }
2040     }
2041 
2042     /**
2043      * Increment number of times connectivity watchdog confirmed pno is working
2044      */
incrementNumConnectivityWatchdogPnoGood()2045     public void incrementNumConnectivityWatchdogPnoGood() {
2046         synchronized (mLock) {
2047             mWifiLogProto.numConnectivityWatchdogPnoGood++;
2048         }
2049     }
2050     /**
2051      * Increment number of times connectivity watchdog found pno not working
2052      */
incrementNumConnectivityWatchdogPnoBad()2053     public void incrementNumConnectivityWatchdogPnoBad() {
2054         synchronized (mLock) {
2055             mWifiLogProto.numConnectivityWatchdogPnoBad++;
2056         }
2057     }
2058     /**
2059      * Increment number of times connectivity watchdog confirmed background scan is working
2060      */
incrementNumConnectivityWatchdogBackgroundGood()2061     public void incrementNumConnectivityWatchdogBackgroundGood() {
2062         synchronized (mLock) {
2063             mWifiLogProto.numConnectivityWatchdogBackgroundGood++;
2064         }
2065     }
2066     /**
2067      * Increment number of times connectivity watchdog found background scan not working
2068      */
incrementNumConnectivityWatchdogBackgroundBad()2069     public void incrementNumConnectivityWatchdogBackgroundBad() {
2070         synchronized (mLock) {
2071             mWifiLogProto.numConnectivityWatchdogBackgroundBad++;
2072         }
2073     }
2074 
2075     /**
2076      * Increment various poll related metrics, and cache performance data for StaEvent logging
2077      */
handlePollResult(WifiInfo wifiInfo)2078     public void handlePollResult(WifiInfo wifiInfo) {
2079         mLastPollRssi = wifiInfo.getRssi();
2080         mLastPollLinkSpeed = wifiInfo.getLinkSpeed();
2081         mLastPollFreq = wifiInfo.getFrequency();
2082         incrementRssiPollRssiCount(mLastPollFreq, mLastPollRssi);
2083         incrementLinkSpeedCount(mLastPollLinkSpeed, mLastPollRssi);
2084         mLastPollRxLinkSpeed = wifiInfo.getRxLinkSpeedMbps();
2085         incrementTxLinkSpeedBandCount(mLastPollLinkSpeed, mLastPollFreq);
2086         incrementRxLinkSpeedBandCount(mLastPollRxLinkSpeed, mLastPollFreq);
2087     }
2088 
2089     /**
2090      * Increment occurence count of RSSI level from RSSI poll for the given frequency.
2091      * @param frequency (MHz)
2092      * @param rssi
2093      */
2094     @VisibleForTesting
incrementRssiPollRssiCount(int frequency, int rssi)2095     public void incrementRssiPollRssiCount(int frequency, int rssi) {
2096         if (!(rssi >= MIN_RSSI_POLL && rssi <= MAX_RSSI_POLL)) {
2097             return;
2098         }
2099         synchronized (mLock) {
2100             if (!mRssiPollCountsMap.containsKey(frequency)) {
2101                 mRssiPollCountsMap.put(frequency, new SparseIntArray());
2102             }
2103             SparseIntArray sparseIntArray = mRssiPollCountsMap.get(frequency);
2104             int count = sparseIntArray.get(rssi);
2105             sparseIntArray.put(rssi, count + 1);
2106             maybeIncrementRssiDeltaCount(rssi - mScanResultRssi);
2107         }
2108     }
2109 
2110     /**
2111      * Increment occurence count of difference between scan result RSSI and the first RSSI poll.
2112      * Ignores rssi values outside the bounds of [MIN_RSSI_DELTA, MAX_RSSI_DELTA]
2113      * mLock must be held when calling this method.
2114      */
maybeIncrementRssiDeltaCount(int rssi)2115     private void maybeIncrementRssiDeltaCount(int rssi) {
2116         // Check if this RSSI poll is close enough to a scan result RSSI to log a delta value
2117         if (mScanResultRssiTimestampMillis >= 0) {
2118             long timeDelta = mClock.getElapsedSinceBootMillis() - mScanResultRssiTimestampMillis;
2119             if (timeDelta <= TIMEOUT_RSSI_DELTA_MILLIS) {
2120                 if (rssi >= MIN_RSSI_DELTA && rssi <= MAX_RSSI_DELTA) {
2121                     int count = mRssiDeltaCounts.get(rssi);
2122                     mRssiDeltaCounts.put(rssi, count + 1);
2123                 }
2124             }
2125             mScanResultRssiTimestampMillis = -1;
2126         }
2127     }
2128 
2129     /**
2130      * Increment occurrence count of link speed.
2131      * Ignores link speed values that are lower than MIN_LINK_SPEED_MBPS
2132      * and rssi values outside the bounds of [MIN_RSSI_POLL, MAX_RSSI_POLL]
2133      */
2134     @VisibleForTesting
incrementLinkSpeedCount(int linkSpeed, int rssi)2135     public void incrementLinkSpeedCount(int linkSpeed, int rssi) {
2136         if (!(mContext.getResources().getBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled)
2137                 && linkSpeed >= MIN_LINK_SPEED_MBPS
2138                 && rssi >= MIN_RSSI_POLL
2139                 && rssi <= MAX_RSSI_POLL)) {
2140             return;
2141         }
2142         synchronized (mLock) {
2143             LinkSpeedCount linkSpeedCount = mLinkSpeedCounts.get(linkSpeed);
2144             if (linkSpeedCount == null) {
2145                 linkSpeedCount = new LinkSpeedCount();
2146                 linkSpeedCount.linkSpeedMbps = linkSpeed;
2147                 mLinkSpeedCounts.put(linkSpeed, linkSpeedCount);
2148             }
2149             linkSpeedCount.count++;
2150             linkSpeedCount.rssiSumDbm += Math.abs(rssi);
2151             linkSpeedCount.rssiSumOfSquaresDbmSq += rssi * rssi;
2152         }
2153     }
2154 
2155     /**
2156      * Increment occurrence count of Tx link speed for operating sub-band
2157      * Ignores link speed values that are lower than MIN_LINK_SPEED_MBPS
2158      * @param txLinkSpeed PHY layer Tx link speed in Mbps
2159      * @param frequency Channel frequency of beacon frames in MHz
2160      */
2161     @VisibleForTesting
incrementTxLinkSpeedBandCount(int txLinkSpeed, int frequency)2162     public void incrementTxLinkSpeedBandCount(int txLinkSpeed, int frequency) {
2163         if (!(mContext.getResources().getBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled)
2164                 && txLinkSpeed >= MIN_LINK_SPEED_MBPS)) {
2165             return;
2166         }
2167         synchronized (mLock) {
2168             if (ScanResult.is24GHz(frequency)) {
2169                 mTxLinkSpeedCount2g.increment(txLinkSpeed);
2170             } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_LOW_END_FREQ) {
2171                 mTxLinkSpeedCount5gLow.increment(txLinkSpeed);
2172             } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_MID_END_FREQ) {
2173                 mTxLinkSpeedCount5gMid.increment(txLinkSpeed);
2174             } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_HIGH_END_FREQ) {
2175                 mTxLinkSpeedCount5gHigh.increment(txLinkSpeed);
2176             } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_LOW_END_FREQ) {
2177                 mTxLinkSpeedCount6gLow.increment(txLinkSpeed);
2178             } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_MID_END_FREQ) {
2179                 mTxLinkSpeedCount6gMid.increment(txLinkSpeed);
2180             } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_HIGH_END_FREQ) {
2181                 mTxLinkSpeedCount6gHigh.increment(txLinkSpeed);
2182             }
2183         }
2184     }
2185 
2186     /**
2187      * Increment occurrence count of Rx link speed for operating sub-band
2188      * Ignores link speed values that are lower than MIN_LINK_SPEED_MBPS
2189      * @param rxLinkSpeed PHY layer Tx link speed in Mbps
2190      * @param frequency Channel frequency of beacon frames in MHz
2191      */
2192     @VisibleForTesting
incrementRxLinkSpeedBandCount(int rxLinkSpeed, int frequency)2193     public void incrementRxLinkSpeedBandCount(int rxLinkSpeed, int frequency) {
2194         if (!(mContext.getResources().getBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled)
2195                 && rxLinkSpeed >= MIN_LINK_SPEED_MBPS)) {
2196             return;
2197         }
2198         synchronized (mLock) {
2199             if (ScanResult.is24GHz(frequency)) {
2200                 mRxLinkSpeedCount2g.increment(rxLinkSpeed);
2201             } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_LOW_END_FREQ) {
2202                 mRxLinkSpeedCount5gLow.increment(rxLinkSpeed);
2203             } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_MID_END_FREQ) {
2204                 mRxLinkSpeedCount5gMid.increment(rxLinkSpeed);
2205             } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_HIGH_END_FREQ) {
2206                 mRxLinkSpeedCount5gHigh.increment(rxLinkSpeed);
2207             } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_LOW_END_FREQ) {
2208                 mRxLinkSpeedCount6gLow.increment(rxLinkSpeed);
2209             } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_MID_END_FREQ) {
2210                 mRxLinkSpeedCount6gMid.increment(rxLinkSpeed);
2211             } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_HIGH_END_FREQ) {
2212                 mRxLinkSpeedCount6gHigh.increment(rxLinkSpeed);
2213             }
2214         }
2215     }
2216 
2217     /**
2218      * Increment occurrence count of channel utilization
2219      * @param channelUtilization Channel utilization of current network
2220      * @param frequency Channel frequency of current network
2221      */
2222     @VisibleForTesting
incrementChannelUtilizationCount(int channelUtilization, int frequency)2223     public void incrementChannelUtilizationCount(int channelUtilization, int frequency) {
2224         if (channelUtilization < InformationElementUtil.BssLoad.MIN_CHANNEL_UTILIZATION
2225                 || channelUtilization > InformationElementUtil.BssLoad.MAX_CHANNEL_UTILIZATION) {
2226             return;
2227         }
2228         synchronized (mLock) {
2229             if (ScanResult.is24GHz(frequency)) {
2230                 mChannelUtilizationHistogram2G.increment(channelUtilization);
2231             } else {
2232                 mChannelUtilizationHistogramAbove2G.increment(channelUtilization);
2233             }
2234         }
2235     }
2236 
2237     /**
2238      * Increment occurrence count of Tx and Rx throughput
2239      * @param txThroughputKbps Tx throughput of current network in Kbps
2240      * @param rxThroughputKbps Rx throughput of current network in Kbps
2241      * @param frequency Channel frequency of current network in MHz
2242      */
2243     @VisibleForTesting
incrementThroughputKbpsCount(int txThroughputKbps, int rxThroughputKbps, int frequency)2244     public void incrementThroughputKbpsCount(int txThroughputKbps, int rxThroughputKbps,
2245             int frequency) {
2246         synchronized (mLock) {
2247             if (ScanResult.is24GHz(frequency)) {
2248                 if (txThroughputKbps >= 0) {
2249                     mTxThroughputMbpsHistogram2G.increment(txThroughputKbps / 1000);
2250                 }
2251                 if (rxThroughputKbps >= 0) {
2252                     mRxThroughputMbpsHistogram2G.increment(rxThroughputKbps / 1000);
2253                 }
2254             } else {
2255                 if (txThroughputKbps >= 0) {
2256                     mTxThroughputMbpsHistogramAbove2G.increment(txThroughputKbps / 1000);
2257                 }
2258                 if (rxThroughputKbps >= 0) {
2259                     mRxThroughputMbpsHistogramAbove2G.increment(rxThroughputKbps / 1000);
2260                 }
2261             }
2262         }
2263     }
2264 
2265     /**
2266      * Increment count of Watchdog successes.
2267      */
incrementNumLastResortWatchdogSuccesses()2268     public void incrementNumLastResortWatchdogSuccesses() {
2269         synchronized (mLock) {
2270             mWifiLogProto.numLastResortWatchdogSuccesses++;
2271         }
2272     }
2273 
2274     /**
2275      * Increment the count of network connection failures that happened after watchdog has been
2276      * triggered.
2277      */
incrementWatchdogTotalConnectionFailureCountAfterTrigger()2278     public void incrementWatchdogTotalConnectionFailureCountAfterTrigger() {
2279         synchronized (mLock) {
2280             mWifiLogProto.watchdogTotalConnectionFailureCountAfterTrigger++;
2281         }
2282     }
2283 
2284     /**
2285      * Sets the time taken for wifi to connect after a watchdog triggers a restart.
2286      * @param milliseconds
2287      */
setWatchdogSuccessTimeDurationMs(long ms)2288     public void setWatchdogSuccessTimeDurationMs(long ms) {
2289         synchronized (mLock) {
2290             mWifiLogProto.watchdogTriggerToConnectionSuccessDurationMs = ms;
2291         }
2292     }
2293 
2294     /**
2295      * Increments the count of alerts by alert reason.
2296      *
2297      * @param reason The cause of the alert. The reason values are driver-specific.
2298      */
incrementAlertReasonCount(int reason)2299     private void incrementAlertReasonCount(int reason) {
2300         if (reason > WifiLoggerHal.WIFI_ALERT_REASON_MAX
2301                 || reason < WifiLoggerHal.WIFI_ALERT_REASON_MIN) {
2302             reason = WifiLoggerHal.WIFI_ALERT_REASON_RESERVED;
2303         }
2304         synchronized (mLock) {
2305             int alertCount = mWifiAlertReasonCounts.get(reason);
2306             mWifiAlertReasonCounts.put(reason, alertCount + 1);
2307         }
2308     }
2309 
2310     /**
2311      * Counts all the different types of networks seen in a set of scan results
2312      */
countScanResults(List<ScanDetail> scanDetails)2313     public void countScanResults(List<ScanDetail> scanDetails) {
2314         if (scanDetails == null) {
2315             return;
2316         }
2317         int totalResults = 0;
2318         int openNetworks = 0;
2319         int personalNetworks = 0;
2320         int enterpriseNetworks = 0;
2321         int hiddenNetworks = 0;
2322         int hotspot2r1Networks = 0;
2323         int hotspot2r2Networks = 0;
2324         int hotspot2r3Networks = 0;
2325         int enhacedOpenNetworks = 0;
2326         int wpa3PersonalNetworks = 0;
2327         int wpa3EnterpriseNetworks = 0;
2328         int wapiPersonalNetworks = 0;
2329         int wapiEnterpriseNetworks = 0;
2330         int mboSupportedNetworks = 0;
2331         int mboCellularDataAwareNetworks = 0;
2332         int oceSupportedNetworks = 0;
2333         int filsSupportedNetworks = 0;
2334         int band6gNetworks = 0;
2335         int standard11axNetworks = 0;
2336 
2337         for (ScanDetail scanDetail : scanDetails) {
2338             NetworkDetail networkDetail = scanDetail.getNetworkDetail();
2339             ScanResult scanResult = scanDetail.getScanResult();
2340             totalResults++;
2341             if (networkDetail != null) {
2342                 if (networkDetail.isHiddenBeaconFrame()) {
2343                     hiddenNetworks++;
2344                 }
2345                 if (networkDetail.getHSRelease() != null) {
2346                     if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R1) {
2347                         hotspot2r1Networks++;
2348                     } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R2) {
2349                         hotspot2r2Networks++;
2350                     } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R3) {
2351                         hotspot2r3Networks++;
2352                     }
2353                 }
2354                 if (networkDetail.isMboSupported()) {
2355                     mboSupportedNetworks++;
2356                     if (networkDetail.isMboCellularDataAware()) {
2357                         mboCellularDataAwareNetworks++;
2358                     }
2359                     if (networkDetail.isOceSupported()) {
2360                         oceSupportedNetworks++;
2361                     }
2362                 }
2363                 if (networkDetail.getWifiMode() == InformationElementUtil.WifiMode.MODE_11AX) {
2364                     standard11axNetworks++;
2365                 }
2366             }
2367             if (scanResult != null && scanResult.capabilities != null) {
2368                 if (ScanResultUtil.isScanResultForFilsSha256Network(scanResult)
2369                         || ScanResultUtil.isScanResultForFilsSha384Network(scanResult)) {
2370                     filsSupportedNetworks++;
2371                 }
2372                 if (scanResult.is6GHz()) {
2373                     band6gNetworks++;
2374                 }
2375                 if (ScanResultUtil.isScanResultForEapSuiteBNetwork(scanResult)) {
2376                     wpa3EnterpriseNetworks++;
2377                 } else if (ScanResultUtil.isScanResultForWapiPskNetwork(scanResult)) {
2378                     wapiPersonalNetworks++;
2379                 } else if (ScanResultUtil.isScanResultForWapiCertNetwork(scanResult)) {
2380                     wapiEnterpriseNetworks++;
2381                 } else if (ScanResultUtil.isScanResultForEapNetwork(scanResult)) {
2382                     enterpriseNetworks++;
2383                 } else if (ScanResultUtil.isScanResultForSaeNetwork(scanResult)) {
2384                     wpa3PersonalNetworks++;
2385                 } else if (ScanResultUtil.isScanResultForPskNetwork(scanResult)
2386                         || ScanResultUtil.isScanResultForWepNetwork(scanResult)) {
2387                     personalNetworks++;
2388                 } else if (ScanResultUtil.isScanResultForOweNetwork(scanResult)) {
2389                     enhacedOpenNetworks++;
2390                 } else {
2391                     openNetworks++;
2392                 }
2393             }
2394         }
2395         synchronized (mLock) {
2396             mWifiLogProto.numTotalScanResults += totalResults;
2397             mWifiLogProto.numOpenNetworkScanResults += openNetworks;
2398             mWifiLogProto.numLegacyPersonalNetworkScanResults += personalNetworks;
2399             mWifiLogProto.numLegacyEnterpriseNetworkScanResults += enterpriseNetworks;
2400             mWifiLogProto.numEnhancedOpenNetworkScanResults += enhacedOpenNetworks;
2401             mWifiLogProto.numWpa3PersonalNetworkScanResults += wpa3PersonalNetworks;
2402             mWifiLogProto.numWpa3EnterpriseNetworkScanResults += wpa3EnterpriseNetworks;
2403             mWifiLogProto.numWapiPersonalNetworkScanResults += wapiPersonalNetworks;
2404             mWifiLogProto.numWapiEnterpriseNetworkScanResults += wapiEnterpriseNetworks;
2405             mWifiLogProto.numHiddenNetworkScanResults += hiddenNetworks;
2406             mWifiLogProto.numHotspot2R1NetworkScanResults += hotspot2r1Networks;
2407             mWifiLogProto.numHotspot2R2NetworkScanResults += hotspot2r2Networks;
2408             mWifiLogProto.numHotspot2R3NetworkScanResults += hotspot2r3Networks;
2409             mWifiLogProto.numMboSupportedNetworkScanResults += mboSupportedNetworks;
2410             mWifiLogProto.numMboCellularDataAwareNetworkScanResults += mboCellularDataAwareNetworks;
2411             mWifiLogProto.numOceSupportedNetworkScanResults += oceSupportedNetworks;
2412             mWifiLogProto.numFilsSupportedNetworkScanResults += filsSupportedNetworks;
2413             mWifiLogProto.num11AxNetworkScanResults += standard11axNetworks;
2414             mWifiLogProto.num6GNetworkScanResults += band6gNetworks;
2415             mWifiLogProto.numScans++;
2416         }
2417     }
2418 
2419     private boolean mWifiWins = false; // Based on scores, use wifi instead of mobile data?
2420     // Based on Wifi usability scores. use wifi instead of mobile data?
2421     private boolean mWifiWinsUsabilityScore = false;
2422 
2423     /**
2424      * Increments occurence of a particular wifi score calculated
2425      * in WifiScoreReport by current connected network. Scores are bounded
2426      * within  [MIN_WIFI_SCORE, MAX_WIFI_SCORE] to limit size of SparseArray.
2427      *
2428      * Also records events when the current score breaches significant thresholds.
2429      */
incrementWifiScoreCount(int score)2430     public void incrementWifiScoreCount(int score) {
2431         if (score < MIN_WIFI_SCORE || score > MAX_WIFI_SCORE) {
2432             return;
2433         }
2434         synchronized (mLock) {
2435             int count = mWifiScoreCounts.get(score);
2436             mWifiScoreCounts.put(score, count + 1);
2437 
2438             boolean wifiWins = mWifiWins;
2439             if (mWifiWins && score < LOW_WIFI_SCORE) {
2440                 wifiWins = false;
2441             } else if (!mWifiWins && score > LOW_WIFI_SCORE) {
2442                 wifiWins = true;
2443             }
2444             mLastScore = score;
2445             mLastScoreNoReset = score;
2446             if (wifiWins != mWifiWins) {
2447                 mWifiWins = wifiWins;
2448                 StaEvent event = new StaEvent();
2449                 event.type = StaEvent.TYPE_SCORE_BREACH;
2450                 addStaEvent(event);
2451                 // Only record the first score breach by checking whether mScoreBreachLowTimeMillis
2452                 // has been set to -1
2453                 if (!wifiWins && mScoreBreachLowTimeMillis == -1) {
2454                     mScoreBreachLowTimeMillis = mClock.getElapsedSinceBootMillis();
2455                 }
2456             }
2457         }
2458     }
2459 
2460     /**
2461      * Increments occurence of the results from attempting to start SoftAp.
2462      * Maps the |result| and WifiManager |failureCode| constant to proto defined SoftApStartResult
2463      * codes.
2464      */
incrementSoftApStartResult(boolean result, int failureCode)2465     public void incrementSoftApStartResult(boolean result, int failureCode) {
2466         synchronized (mLock) {
2467             if (result) {
2468                 int count = mSoftApManagerReturnCodeCounts.get(
2469                         WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY);
2470                 mSoftApManagerReturnCodeCounts.put(
2471                         WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY,
2472                         count + 1);
2473                 return;
2474             }
2475 
2476             // now increment failure modes - if not explicitly handled, dump into the general
2477             // error bucket.
2478             if (failureCode == WifiManager.SAP_START_FAILURE_NO_CHANNEL) {
2479                 int count = mSoftApManagerReturnCodeCounts.get(
2480                         WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL);
2481                 mSoftApManagerReturnCodeCounts.put(
2482                         WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL,
2483                         count + 1);
2484             } else if (failureCode == WifiManager.SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION) {
2485                 int count = mSoftApManagerReturnCodeCounts.get(
2486                         WifiMetricsProto.SoftApReturnCodeCount
2487                         .SOFT_AP_FAILED_UNSUPPORTED_CONFIGURATION);
2488                 mSoftApManagerReturnCodeCounts.put(
2489                         WifiMetricsProto.SoftApReturnCodeCount
2490                         .SOFT_AP_FAILED_UNSUPPORTED_CONFIGURATION,
2491                         count + 1);
2492             } else {
2493                 // failure mode not tracked at this time...  count as a general error for now.
2494                 int count = mSoftApManagerReturnCodeCounts.get(
2495                         WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR);
2496                 mSoftApManagerReturnCodeCounts.put(
2497                         WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR,
2498                         count + 1);
2499             }
2500         }
2501     }
2502 
2503     /**
2504      * Adds a record indicating the current up state of soft AP
2505      */
addSoftApUpChangedEvent(boolean isUp, int mode, long defaultShutdownTimeoutMillis)2506     public void addSoftApUpChangedEvent(boolean isUp, int mode, long defaultShutdownTimeoutMillis) {
2507         SoftApConnectedClientsEvent event = new SoftApConnectedClientsEvent();
2508         event.eventType = isUp ? SoftApConnectedClientsEvent.SOFT_AP_UP :
2509                 SoftApConnectedClientsEvent.SOFT_AP_DOWN;
2510         event.numConnectedClients = 0;
2511         event.defaultShutdownTimeoutSetting = defaultShutdownTimeoutMillis;
2512         addSoftApConnectedClientsEvent(event, mode);
2513     }
2514 
2515     /**
2516      * Adds a record for current number of associated stations to soft AP
2517      */
addSoftApNumAssociatedStationsChangedEvent(int numStations, int mode)2518     public void addSoftApNumAssociatedStationsChangedEvent(int numStations, int mode) {
2519         SoftApConnectedClientsEvent event = new SoftApConnectedClientsEvent();
2520         event.eventType = SoftApConnectedClientsEvent.NUM_CLIENTS_CHANGED;
2521         event.numConnectedClients = numStations;
2522         addSoftApConnectedClientsEvent(event, mode);
2523     }
2524 
2525     /**
2526      * Adds a record to the corresponding event list based on mode param
2527      */
addSoftApConnectedClientsEvent(SoftApConnectedClientsEvent event, int mode)2528     private void addSoftApConnectedClientsEvent(SoftApConnectedClientsEvent event, int mode) {
2529         synchronized (mLock) {
2530             List<SoftApConnectedClientsEvent> softApEventList;
2531             switch (mode) {
2532                 case WifiManager.IFACE_IP_MODE_TETHERED:
2533                     softApEventList = mSoftApEventListTethered;
2534                     break;
2535                 case WifiManager.IFACE_IP_MODE_LOCAL_ONLY:
2536                     softApEventList = mSoftApEventListLocalOnly;
2537                     break;
2538                 default:
2539                     return;
2540             }
2541 
2542             if (softApEventList.size() > MAX_NUM_SOFT_AP_EVENTS) {
2543                 return;
2544             }
2545 
2546             event.timeStampMillis = mClock.getElapsedSinceBootMillis();
2547             softApEventList.add(event);
2548         }
2549     }
2550 
2551     /**
2552      * Updates current soft AP events with channel info
2553      */
addSoftApChannelSwitchedEvent(int frequency, int bandwidth, int mode)2554     public void addSoftApChannelSwitchedEvent(int frequency, int bandwidth, int mode) {
2555         synchronized (mLock) {
2556             List<SoftApConnectedClientsEvent> softApEventList;
2557             switch (mode) {
2558                 case WifiManager.IFACE_IP_MODE_TETHERED:
2559                     softApEventList = mSoftApEventListTethered;
2560                     break;
2561                 case WifiManager.IFACE_IP_MODE_LOCAL_ONLY:
2562                     softApEventList = mSoftApEventListLocalOnly;
2563                     break;
2564                 default:
2565                     return;
2566             }
2567 
2568             for (int index = softApEventList.size() - 1; index >= 0; index--) {
2569                 SoftApConnectedClientsEvent event = softApEventList.get(index);
2570 
2571                 if (event != null && event.eventType == SoftApConnectedClientsEvent.SOFT_AP_UP) {
2572                     event.channelFrequency = frequency;
2573                     event.channelBandwidth = bandwidth;
2574                     break;
2575                 }
2576             }
2577         }
2578     }
2579 
2580     /**
2581      * Updates current soft AP events with softap configuration
2582      */
updateSoftApConfiguration(SoftApConfiguration config, int mode)2583     public void updateSoftApConfiguration(SoftApConfiguration config, int mode) {
2584         synchronized (mLock) {
2585             List<SoftApConnectedClientsEvent> softApEventList;
2586             switch (mode) {
2587                 case WifiManager.IFACE_IP_MODE_TETHERED:
2588                     softApEventList = mSoftApEventListTethered;
2589                     break;
2590                 case WifiManager.IFACE_IP_MODE_LOCAL_ONLY:
2591                     softApEventList = mSoftApEventListLocalOnly;
2592                     break;
2593                 default:
2594                     return;
2595             }
2596 
2597             for (int index = softApEventList.size() - 1; index >= 0; index--) {
2598                 SoftApConnectedClientsEvent event = softApEventList.get(index);
2599 
2600                 if (event != null && event.eventType == SoftApConnectedClientsEvent.SOFT_AP_UP) {
2601                     event.maxNumClientsSettingInSoftapConfiguration =
2602                             config.getMaxNumberOfClients();
2603                     event.shutdownTimeoutSettingInSoftapConfiguration =
2604                             config.getShutdownTimeoutMillis();
2605                     event.clientControlIsEnabled = config.isClientControlByUserEnabled();
2606                     break;
2607                 }
2608             }
2609         }
2610     }
2611 
2612     /**
2613      * Updates current soft AP events with softap capability
2614      */
updateSoftApCapability(SoftApCapability capability, int mode)2615     public void updateSoftApCapability(SoftApCapability capability, int mode) {
2616         synchronized (mLock) {
2617             List<SoftApConnectedClientsEvent> softApEventList;
2618             switch (mode) {
2619                 case WifiManager.IFACE_IP_MODE_TETHERED:
2620                     softApEventList = mSoftApEventListTethered;
2621                     break;
2622                 case WifiManager.IFACE_IP_MODE_LOCAL_ONLY:
2623                     softApEventList = mSoftApEventListLocalOnly;
2624                     break;
2625                 default:
2626                     return;
2627             }
2628 
2629             for (int index = softApEventList.size() - 1; index >= 0; index--) {
2630                 SoftApConnectedClientsEvent event = softApEventList.get(index);
2631                 if (event != null && event.eventType == SoftApConnectedClientsEvent.SOFT_AP_UP) {
2632                     event.maxNumClientsSettingInSoftapCapability =
2633                             capability.getMaxSupportedClients();
2634                     break;
2635                 }
2636             }
2637         }
2638     }
2639 
2640     /**
2641      * Increment number of times the HAL crashed.
2642      */
incrementNumHalCrashes()2643     public void incrementNumHalCrashes() {
2644         synchronized (mLock) {
2645             mWifiLogProto.numHalCrashes++;
2646         }
2647     }
2648 
2649     /**
2650      * Increment number of times the Wificond crashed.
2651      */
incrementNumWificondCrashes()2652     public void incrementNumWificondCrashes() {
2653         synchronized (mLock) {
2654             mWifiLogProto.numWificondCrashes++;
2655         }
2656     }
2657 
2658     /**
2659      * Increment number of times the supplicant crashed.
2660      */
incrementNumSupplicantCrashes()2661     public void incrementNumSupplicantCrashes() {
2662         synchronized (mLock) {
2663             mWifiLogProto.numSupplicantCrashes++;
2664         }
2665     }
2666 
2667     /**
2668      * Increment number of times the hostapd crashed.
2669      */
incrementNumHostapdCrashes()2670     public void incrementNumHostapdCrashes() {
2671         synchronized (mLock) {
2672             mWifiLogProto.numHostapdCrashes++;
2673         }
2674     }
2675 
2676     /**
2677      * Increment number of times the wifi on failed due to an error in HAL.
2678      */
incrementNumSetupClientInterfaceFailureDueToHal()2679     public void incrementNumSetupClientInterfaceFailureDueToHal() {
2680         synchronized (mLock) {
2681             mWifiLogProto.numSetupClientInterfaceFailureDueToHal++;
2682         }
2683     }
2684 
2685     /**
2686      * Increment number of times the wifi on failed due to an error in wificond.
2687      */
incrementNumSetupClientInterfaceFailureDueToWificond()2688     public void incrementNumSetupClientInterfaceFailureDueToWificond() {
2689         synchronized (mLock) {
2690             mWifiLogProto.numSetupClientInterfaceFailureDueToWificond++;
2691         }
2692     }
2693 
2694     /**
2695      * Increment number of times the wifi on failed due to an error in supplicant.
2696      */
incrementNumSetupClientInterfaceFailureDueToSupplicant()2697     public void incrementNumSetupClientInterfaceFailureDueToSupplicant() {
2698         synchronized (mLock) {
2699             mWifiLogProto.numSetupClientInterfaceFailureDueToSupplicant++;
2700         }
2701     }
2702 
2703     /**
2704      * Increment number of times the SoftAp on failed due to an error in HAL.
2705      */
incrementNumSetupSoftApInterfaceFailureDueToHal()2706     public void incrementNumSetupSoftApInterfaceFailureDueToHal() {
2707         synchronized (mLock) {
2708             mWifiLogProto.numSetupSoftApInterfaceFailureDueToHal++;
2709         }
2710     }
2711 
2712     /**
2713      * Increment number of times the SoftAp on failed due to an error in wificond.
2714      */
incrementNumSetupSoftApInterfaceFailureDueToWificond()2715     public void incrementNumSetupSoftApInterfaceFailureDueToWificond() {
2716         synchronized (mLock) {
2717             mWifiLogProto.numSetupSoftApInterfaceFailureDueToWificond++;
2718         }
2719     }
2720 
2721     /**
2722      * Increment number of times the SoftAp on failed due to an error in hostapd.
2723      */
incrementNumSetupSoftApInterfaceFailureDueToHostapd()2724     public void incrementNumSetupSoftApInterfaceFailureDueToHostapd() {
2725         synchronized (mLock) {
2726             mWifiLogProto.numSetupSoftApInterfaceFailureDueToHostapd++;
2727         }
2728     }
2729 
2730     /**
2731      * Increment number of times we got client interface down.
2732      */
incrementNumClientInterfaceDown()2733     public void incrementNumClientInterfaceDown() {
2734         synchronized (mLock) {
2735             mWifiLogProto.numClientInterfaceDown++;
2736         }
2737     }
2738 
2739     /**
2740      * Increment number of times we got client interface down.
2741      */
incrementNumSoftApInterfaceDown()2742     public void incrementNumSoftApInterfaceDown() {
2743         synchronized (mLock) {
2744             mWifiLogProto.numSoftApInterfaceDown++;
2745         }
2746     }
2747 
2748     /**
2749      * Increment number of times Passpoint provider being installed.
2750      */
incrementNumPasspointProviderInstallation()2751     public void incrementNumPasspointProviderInstallation() {
2752         synchronized (mLock) {
2753             mWifiLogProto.numPasspointProviderInstallation++;
2754         }
2755     }
2756 
2757     /**
2758      * Increment number of times Passpoint provider is installed successfully.
2759      */
incrementNumPasspointProviderInstallSuccess()2760     public void incrementNumPasspointProviderInstallSuccess() {
2761         synchronized (mLock) {
2762             mWifiLogProto.numPasspointProviderInstallSuccess++;
2763         }
2764     }
2765 
2766     /**
2767      * Increment number of times Passpoint provider being uninstalled.
2768      */
incrementNumPasspointProviderUninstallation()2769     public void incrementNumPasspointProviderUninstallation() {
2770         synchronized (mLock) {
2771             mWifiLogProto.numPasspointProviderUninstallation++;
2772         }
2773     }
2774 
2775     /**
2776      * Increment number of times Passpoint provider is uninstalled successfully.
2777      */
incrementNumPasspointProviderUninstallSuccess()2778     public void incrementNumPasspointProviderUninstallSuccess() {
2779         synchronized (mLock) {
2780             mWifiLogProto.numPasspointProviderUninstallSuccess++;
2781         }
2782     }
2783 
2784     /**
2785      * Increment number of Passpoint providers with no Root CA in their profile.
2786      */
incrementNumPasspointProviderWithNoRootCa()2787     public void incrementNumPasspointProviderWithNoRootCa() {
2788         synchronized (mLock) {
2789             mWifiLogProto.numPasspointProviderWithNoRootCa++;
2790         }
2791     }
2792 
2793     /**
2794      * Increment number of Passpoint providers with a self-signed Root CA in their profile.
2795      */
incrementNumPasspointProviderWithSelfSignedRootCa()2796     public void incrementNumPasspointProviderWithSelfSignedRootCa() {
2797         synchronized (mLock) {
2798             mWifiLogProto.numPasspointProviderWithSelfSignedRootCa++;
2799         }
2800     }
2801 
2802     /**
2803      * Increment number of Passpoint providers with subscription expiration date in their profile.
2804      */
incrementNumPasspointProviderWithSubscriptionExpiration()2805     public void incrementNumPasspointProviderWithSubscriptionExpiration() {
2806         synchronized (mLock) {
2807             mWifiLogProto.numPasspointProviderWithSubscriptionExpiration++;
2808         }
2809     }
2810 
2811     /**
2812      * Increment number of times we detected a radio mode change to MCC.
2813      */
incrementNumRadioModeChangeToMcc()2814     public void incrementNumRadioModeChangeToMcc() {
2815         synchronized (mLock) {
2816             mWifiLogProto.numRadioModeChangeToMcc++;
2817         }
2818     }
2819 
2820     /**
2821      * Increment number of times we detected a radio mode change to SCC.
2822      */
incrementNumRadioModeChangeToScc()2823     public void incrementNumRadioModeChangeToScc() {
2824         synchronized (mLock) {
2825             mWifiLogProto.numRadioModeChangeToScc++;
2826         }
2827     }
2828 
2829     /**
2830      * Increment number of times we detected a radio mode change to SBS.
2831      */
incrementNumRadioModeChangeToSbs()2832     public void incrementNumRadioModeChangeToSbs() {
2833         synchronized (mLock) {
2834             mWifiLogProto.numRadioModeChangeToSbs++;
2835         }
2836     }
2837 
2838     /**
2839      * Increment number of times we detected a radio mode change to DBS.
2840      */
incrementNumRadioModeChangeToDbs()2841     public void incrementNumRadioModeChangeToDbs() {
2842         synchronized (mLock) {
2843             mWifiLogProto.numRadioModeChangeToDbs++;
2844         }
2845     }
2846 
2847     /**
2848      * Increment number of times we detected a channel did not satisfy user band preference.
2849      */
incrementNumSoftApUserBandPreferenceUnsatisfied()2850     public void incrementNumSoftApUserBandPreferenceUnsatisfied() {
2851         synchronized (mLock) {
2852             mWifiLogProto.numSoftApUserBandPreferenceUnsatisfied++;
2853         }
2854     }
2855 
2856     /**
2857      * Increment N-Way network selection decision histograms:
2858      * Counts the size of various sets of scanDetails within a scan, and increment the occurrence
2859      * of that size for the associated histogram. There are ten histograms generated for each
2860      * combination of: {SSID, BSSID} *{Total, Saved, Open, Saved_or_Open, Passpoint}
2861      * Only performs this count if isFullBand is true, otherwise, increments the partial scan count
2862      */
incrementAvailableNetworksHistograms(List<ScanDetail> scanDetails, boolean isFullBand)2863     public void incrementAvailableNetworksHistograms(List<ScanDetail> scanDetails,
2864             boolean isFullBand) {
2865         synchronized (mLock) {
2866             if (mWifiConfigManager == null || mWifiNetworkSelector == null
2867                     || mPasspointManager == null) {
2868                 return;
2869             }
2870             if (!isFullBand) {
2871                 mWifiLogProto.partialAllSingleScanListenerResults++;
2872                 return;
2873             }
2874             Set<ScanResultMatchInfo> ssids = new HashSet<ScanResultMatchInfo>();
2875             int bssids = 0;
2876             Set<ScanResultMatchInfo> openSsids = new HashSet<ScanResultMatchInfo>();
2877             int openBssids = 0;
2878             Set<ScanResultMatchInfo> savedSsids = new HashSet<ScanResultMatchInfo>();
2879             int savedBssids = 0;
2880             // openOrSavedSsids calculated from union of savedSsids & openSsids
2881             int openOrSavedBssids = 0;
2882             Set<PasspointProvider> savedPasspointProviderProfiles =
2883                     new HashSet<PasspointProvider>();
2884             int savedPasspointProviderBssids = 0;
2885             int passpointR1Aps = 0;
2886             int passpointR2Aps = 0;
2887             int passpointR3Aps = 0;
2888             Map<ANQPNetworkKey, Integer> passpointR1UniqueEss = new HashMap<>();
2889             Map<ANQPNetworkKey, Integer> passpointR2UniqueEss = new HashMap<>();
2890             Map<ANQPNetworkKey, Integer> passpointR3UniqueEss = new HashMap<>();
2891             int supporting80211mcAps = 0;
2892             for (ScanDetail scanDetail : scanDetails) {
2893                 NetworkDetail networkDetail = scanDetail.getNetworkDetail();
2894                 ScanResult scanResult = scanDetail.getScanResult();
2895 
2896                 // statistics to be collected for ALL APs (irrespective of signal power)
2897                 if (networkDetail.is80211McResponderSupport()) {
2898                     supporting80211mcAps++;
2899                 }
2900 
2901                 ScanResultMatchInfo matchInfo = ScanResultMatchInfo.fromScanResult(scanResult);
2902                 List<Pair<PasspointProvider, PasspointMatch>> matchedProviders = null;
2903                 if (networkDetail.isInterworking()) {
2904                     // Try to match provider, but do not allow new ANQP messages. Use cached data.
2905                     matchedProviders = mPasspointManager.matchProvider(scanResult, false);
2906                     if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R1) {
2907                         passpointR1Aps++;
2908                     } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R2) {
2909                         passpointR2Aps++;
2910                     } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R3) {
2911                         passpointR3Aps++;
2912                     }
2913 
2914                     long bssid = 0;
2915                     boolean validBssid = false;
2916                     try {
2917                         bssid = Utils.parseMac(scanResult.BSSID);
2918                         validBssid = true;
2919                     } catch (IllegalArgumentException e) {
2920                         Log.e(TAG,
2921                                 "Invalid BSSID provided in the scan result: " + scanResult.BSSID);
2922                     }
2923                     if (validBssid) {
2924                         ANQPNetworkKey uniqueEss = ANQPNetworkKey.buildKey(scanResult.SSID, bssid,
2925                                 scanResult.hessid, networkDetail.getAnqpDomainID());
2926                         if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R1) {
2927                             Integer countObj = passpointR1UniqueEss.get(uniqueEss);
2928                             int count = countObj == null ? 0 : countObj;
2929                             passpointR1UniqueEss.put(uniqueEss, count + 1);
2930                         } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R2) {
2931                             Integer countObj = passpointR2UniqueEss.get(uniqueEss);
2932                             int count = countObj == null ? 0 : countObj;
2933                             passpointR2UniqueEss.put(uniqueEss, count + 1);
2934                         } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R3) {
2935                             Integer countObj = passpointR3UniqueEss.get(uniqueEss);
2936                             int count = countObj == null ? 0 : countObj;
2937                             passpointR3UniqueEss.put(uniqueEss, count + 1);
2938                         }
2939                     }
2940                 }
2941 
2942                 if (mWifiNetworkSelector.isSignalTooWeak(scanResult)) {
2943                     continue;
2944                 }
2945 
2946                 // statistics to be collected ONLY for those APs with sufficient signal power
2947 
2948                 ssids.add(matchInfo);
2949                 bssids++;
2950                 boolean isOpen = matchInfo.networkType == WifiConfiguration.SECURITY_TYPE_OPEN;
2951                 WifiConfiguration config =
2952                         mWifiConfigManager.getConfiguredNetworkForScanDetail(scanDetail);
2953                 boolean isSaved = (config != null) && !config.isEphemeral()
2954                         && !config.isPasspoint();
2955                 if (isOpen) {
2956                     openSsids.add(matchInfo);
2957                     openBssids++;
2958                 }
2959                 if (isSaved) {
2960                     savedSsids.add(matchInfo);
2961                     savedBssids++;
2962                 }
2963                 if (isOpen || isSaved) {
2964                     openOrSavedBssids++;
2965                     // Calculate openOrSavedSsids union later
2966                 }
2967                 if (matchedProviders != null && !matchedProviders.isEmpty()) {
2968                     for (Pair<PasspointProvider, PasspointMatch> passpointProvider :
2969                             matchedProviders) {
2970                         savedPasspointProviderProfiles.add(passpointProvider.first);
2971                     }
2972                     savedPasspointProviderBssids++;
2973                 }
2974             }
2975             mWifiLogProto.fullBandAllSingleScanListenerResults++;
2976             incrementTotalScanSsids(mTotalSsidsInScanHistogram, ssids.size());
2977             incrementTotalScanResults(mTotalBssidsInScanHistogram, bssids);
2978             incrementSsid(mAvailableOpenSsidsInScanHistogram, openSsids.size());
2979             incrementBssid(mAvailableOpenBssidsInScanHistogram, openBssids);
2980             incrementSsid(mAvailableSavedSsidsInScanHistogram, savedSsids.size());
2981             incrementBssid(mAvailableSavedBssidsInScanHistogram, savedBssids);
2982             openSsids.addAll(savedSsids); // openSsids = Union(openSsids, savedSsids)
2983             incrementSsid(mAvailableOpenOrSavedSsidsInScanHistogram, openSsids.size());
2984             incrementBssid(mAvailableOpenOrSavedBssidsInScanHistogram, openOrSavedBssids);
2985             incrementSsid(mAvailableSavedPasspointProviderProfilesInScanHistogram,
2986                     savedPasspointProviderProfiles.size());
2987             incrementBssid(mAvailableSavedPasspointProviderBssidsInScanHistogram,
2988                     savedPasspointProviderBssids);
2989             incrementTotalPasspointAps(mObservedHotspotR1ApInScanHistogram, passpointR1Aps);
2990             incrementTotalPasspointAps(mObservedHotspotR2ApInScanHistogram, passpointR2Aps);
2991             incrementTotalPasspointAps(mObservedHotspotR3ApInScanHistogram, passpointR3Aps);
2992             incrementTotalUniquePasspointEss(mObservedHotspotR1EssInScanHistogram,
2993                     passpointR1UniqueEss.size());
2994             incrementTotalUniquePasspointEss(mObservedHotspotR2EssInScanHistogram,
2995                     passpointR2UniqueEss.size());
2996             incrementTotalUniquePasspointEss(mObservedHotspotR3EssInScanHistogram,
2997                     passpointR3UniqueEss.size());
2998             for (Integer count : passpointR1UniqueEss.values()) {
2999                 incrementPasspointPerUniqueEss(mObservedHotspotR1ApsPerEssInScanHistogram, count);
3000             }
3001             for (Integer count : passpointR2UniqueEss.values()) {
3002                 incrementPasspointPerUniqueEss(mObservedHotspotR2ApsPerEssInScanHistogram, count);
3003             }
3004             for (Integer count : passpointR3UniqueEss.values()) {
3005                 incrementPasspointPerUniqueEss(mObservedHotspotR3ApsPerEssInScanHistogram, count);
3006             }
3007             increment80211mcAps(mObserved80211mcApInScanHistogram, supporting80211mcAps);
3008         }
3009     }
3010 
3011     /** Increments the occurence of a "Connect to Network" notification. */
incrementConnectToNetworkNotification(String notifierTag, int notificationType)3012     public void incrementConnectToNetworkNotification(String notifierTag, int notificationType) {
3013         synchronized (mLock) {
3014             int count = mConnectToNetworkNotificationCount.get(notificationType);
3015             mConnectToNetworkNotificationCount.put(notificationType, count + 1);
3016         }
3017     }
3018 
3019     /** Increments the occurence of an "Connect to Network" notification user action. */
incrementConnectToNetworkNotificationAction(String notifierTag, int notificationType, int actionType)3020     public void incrementConnectToNetworkNotificationAction(String notifierTag,
3021             int notificationType, int actionType) {
3022         synchronized (mLock) {
3023             int key = notificationType * CONNECT_TO_NETWORK_NOTIFICATION_ACTION_KEY_MULTIPLIER
3024                     + actionType;
3025             int count = mConnectToNetworkNotificationActionCount.get(key);
3026             mConnectToNetworkNotificationActionCount.put(key, count + 1);
3027         }
3028     }
3029 
3030     /**
3031      * Sets the number of SSIDs blacklisted from recommendation by the open network notification
3032      * recommender.
3033      */
setNetworkRecommenderBlacklistSize(String notifierTag, int size)3034     public void setNetworkRecommenderBlacklistSize(String notifierTag, int size) {
3035         synchronized (mLock) {
3036             mOpenNetworkRecommenderBlacklistSize = size;
3037         }
3038     }
3039 
3040     /** Sets if the available network notification feature is enabled. */
setIsWifiNetworksAvailableNotificationEnabled(String notifierTag, boolean enabled)3041     public void setIsWifiNetworksAvailableNotificationEnabled(String notifierTag, boolean enabled) {
3042         synchronized (mLock) {
3043             mIsWifiNetworksAvailableNotificationOn = enabled;
3044         }
3045     }
3046 
3047     /** Increments the occurence of connection attempts that were initiated unsuccessfully */
incrementNumNetworkRecommendationUpdates(String notifierTag)3048     public void incrementNumNetworkRecommendationUpdates(String notifierTag) {
3049         synchronized (mLock) {
3050             mNumOpenNetworkRecommendationUpdates++;
3051         }
3052     }
3053 
3054     /** Increments the occurence of connection attempts that were initiated unsuccessfully */
incrementNumNetworkConnectMessageFailedToSend(String notifierTag)3055     public void incrementNumNetworkConnectMessageFailedToSend(String notifierTag) {
3056         synchronized (mLock) {
3057             mNumOpenNetworkConnectMessageFailedToSend++;
3058         }
3059     }
3060 
3061     /** Log firmware alert related metrics */
logFirmwareAlert(int errorCode)3062     public void logFirmwareAlert(int errorCode) {
3063         incrementAlertReasonCount(errorCode);
3064         logWifiIsUnusableEvent(WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT, errorCode);
3065         addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
3066                 WifiUsabilityStats.TYPE_FIRMWARE_ALERT, errorCode);
3067     }
3068 
3069     public static final String PROTO_DUMP_ARG = "wifiMetricsProto";
3070     public static final String CLEAN_DUMP_ARG = "clean";
3071 
3072     /**
3073      * Dump all WifiMetrics. Collects some metrics from ConfigStore, Settings and WifiManager
3074      * at this time.
3075      *
3076      * @param fd unused
3077      * @param pw PrintWriter for writing dump to
3078      * @param args [wifiMetricsProto [clean]]
3079      */
dump(FileDescriptor fd, PrintWriter pw, String[] args)3080     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
3081         synchronized (mLock) {
3082             consolidateScoringParams();
3083             if (args != null && args.length > 0 && PROTO_DUMP_ARG.equals(args[0])) {
3084                 // Dump serialized WifiLog proto
3085                 consolidateProto();
3086 
3087                 byte[] wifiMetricsProto = WifiMetricsProto.WifiLog.toByteArray(mWifiLogProto);
3088                 String metricsProtoDump = Base64.encodeToString(wifiMetricsProto, Base64.DEFAULT);
3089                 if (args.length > 1 && CLEAN_DUMP_ARG.equals(args[1])) {
3090                     // Output metrics proto bytes (base64) and nothing else
3091                     pw.print(metricsProtoDump);
3092                 } else {
3093                     // Tag the start and end of the metrics proto bytes
3094                     pw.println("WifiMetrics:");
3095                     pw.println(metricsProtoDump);
3096                     pw.println("EndWifiMetrics");
3097                 }
3098                 clear();
3099             } else {
3100                 pw.println("WifiMetrics:");
3101                 pw.println("mConnectionEvents:");
3102                 for (ConnectionEvent event : mConnectionEventList) {
3103                     String eventLine = event.toString();
3104                     if (event == mCurrentConnectionEvent) {
3105                         eventLine += " CURRENTLY OPEN EVENT";
3106                     }
3107                     pw.println(eventLine);
3108                 }
3109                 pw.println("mWifiLogProto.numSavedNetworks=" + mWifiLogProto.numSavedNetworks);
3110                 pw.println("mWifiLogProto.numSavedNetworksWithMacRandomization="
3111                         + mWifiLogProto.numSavedNetworksWithMacRandomization);
3112                 pw.println("mWifiLogProto.numOpenNetworks=" + mWifiLogProto.numOpenNetworks);
3113                 pw.println("mWifiLogProto.numLegacyPersonalNetworks="
3114                         + mWifiLogProto.numLegacyPersonalNetworks);
3115                 pw.println("mWifiLogProto.numLegacyEnterpriseNetworks="
3116                         + mWifiLogProto.numLegacyEnterpriseNetworks);
3117                 pw.println("mWifiLogProto.numEnhancedOpenNetworks="
3118                         + mWifiLogProto.numEnhancedOpenNetworks);
3119                 pw.println("mWifiLogProto.numWpa3PersonalNetworks="
3120                         + mWifiLogProto.numWpa3PersonalNetworks);
3121                 pw.println("mWifiLogProto.numWpa3EnterpriseNetworks="
3122                         + mWifiLogProto.numWpa3EnterpriseNetworks);
3123                 pw.println("mWifiLogProto.numWapiPersonalNetworks="
3124                         + mWifiLogProto.numWapiPersonalNetworks);
3125                 pw.println("mWifiLogProto.numWapiEnterpriseNetworks="
3126                         + mWifiLogProto.numWapiEnterpriseNetworks);
3127                 pw.println("mWifiLogProto.numHiddenNetworks=" + mWifiLogProto.numHiddenNetworks);
3128                 pw.println("mWifiLogProto.numPasspointNetworks="
3129                         + mWifiLogProto.numPasspointNetworks);
3130                 pw.println("mWifiLogProto.isLocationEnabled=" + mWifiLogProto.isLocationEnabled);
3131                 pw.println("mWifiLogProto.isScanningAlwaysEnabled="
3132                         + mWifiLogProto.isScanningAlwaysEnabled);
3133                 pw.println("mWifiLogProto.isVerboseLoggingEnabled="
3134                         + mWifiLogProto.isVerboseLoggingEnabled);
3135                 pw.println("mWifiLogProto.isEnhancedMacRandomizationForceEnabled="
3136                         + mWifiLogProto.isEnhancedMacRandomizationForceEnabled);
3137                 pw.println("mWifiLogProto.isWifiWakeEnabled=" + mWifiLogProto.isWifiWakeEnabled);
3138                 pw.println("mWifiLogProto.numNetworksAddedByUser="
3139                         + mWifiLogProto.numNetworksAddedByUser);
3140                 pw.println("mWifiLogProto.numNetworksAddedByApps="
3141                         + mWifiLogProto.numNetworksAddedByApps);
3142                 pw.println("mWifiLogProto.numNonEmptyScanResults="
3143                         + mWifiLogProto.numNonEmptyScanResults);
3144                 pw.println("mWifiLogProto.numEmptyScanResults="
3145                         + mWifiLogProto.numEmptyScanResults);
3146                 pw.println("mWifiLogProto.numConnecitvityOneshotScans="
3147                         + mWifiLogProto.numConnectivityOneshotScans);
3148                 pw.println("mWifiLogProto.numOneshotScans="
3149                         + mWifiLogProto.numOneshotScans);
3150                 pw.println("mWifiLogProto.numOneshotHasDfsChannelScans="
3151                         + mWifiLogProto.numOneshotHasDfsChannelScans);
3152                 pw.println("mWifiLogProto.numBackgroundScans="
3153                         + mWifiLogProto.numBackgroundScans);
3154                 pw.println("mWifiLogProto.numExternalAppOneshotScanRequests="
3155                         + mWifiLogProto.numExternalAppOneshotScanRequests);
3156                 pw.println("mWifiLogProto.numExternalForegroundAppOneshotScanRequestsThrottled="
3157                         + mWifiLogProto.numExternalForegroundAppOneshotScanRequestsThrottled);
3158                 pw.println("mWifiLogProto.numExternalBackgroundAppOneshotScanRequestsThrottled="
3159                         + mWifiLogProto.numExternalBackgroundAppOneshotScanRequestsThrottled);
3160                 pw.println("mWifiLogProto.meteredNetworkStatsSaved=");
3161                 pw.println(mMeteredNetworkStatsBuilder.toProto(false));
3162                 pw.println("mWifiLogProto.meteredNetworkStatsSuggestion=");
3163                 pw.println(mMeteredNetworkStatsBuilder.toProto(true));
3164                 pw.println("mScanReturnEntries:");
3165                 pw.println("  SCAN_UNKNOWN: " + getScanReturnEntry(
3166                         WifiMetricsProto.WifiLog.SCAN_UNKNOWN));
3167                 pw.println("  SCAN_SUCCESS: " + getScanReturnEntry(
3168                         WifiMetricsProto.WifiLog.SCAN_SUCCESS));
3169                 pw.println("  SCAN_FAILURE_INTERRUPTED: " + getScanReturnEntry(
3170                         WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED));
3171                 pw.println("  SCAN_FAILURE_INVALID_CONFIGURATION: " + getScanReturnEntry(
3172                         WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION));
3173                 pw.println("  FAILURE_WIFI_DISABLED: " + getScanReturnEntry(
3174                         WifiMetricsProto.WifiLog.FAILURE_WIFI_DISABLED));
3175 
3176                 pw.println("mSystemStateEntries: <state><screenOn> : <scansInitiated>");
3177                 pw.println("  WIFI_UNKNOWN       ON: "
3178                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, true));
3179                 pw.println("  WIFI_DISABLED      ON: "
3180                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISABLED, true));
3181                 pw.println("  WIFI_DISCONNECTED  ON: "
3182                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED, true));
3183                 pw.println("  WIFI_ASSOCIATED    ON: "
3184                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, true));
3185                 pw.println("  WIFI_UNKNOWN      OFF: "
3186                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, false));
3187                 pw.println("  WIFI_DISABLED     OFF: "
3188                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISABLED, false));
3189                 pw.println("  WIFI_DISCONNECTED OFF: "
3190                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED, false));
3191                 pw.println("  WIFI_ASSOCIATED   OFF: "
3192                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, false));
3193                 pw.println("mWifiLogProto.numConnectivityWatchdogPnoGood="
3194                         + mWifiLogProto.numConnectivityWatchdogPnoGood);
3195                 pw.println("mWifiLogProto.numConnectivityWatchdogPnoBad="
3196                         + mWifiLogProto.numConnectivityWatchdogPnoBad);
3197                 pw.println("mWifiLogProto.numConnectivityWatchdogBackgroundGood="
3198                         + mWifiLogProto.numConnectivityWatchdogBackgroundGood);
3199                 pw.println("mWifiLogProto.numConnectivityWatchdogBackgroundBad="
3200                         + mWifiLogProto.numConnectivityWatchdogBackgroundBad);
3201                 pw.println("mWifiLogProto.numLastResortWatchdogTriggers="
3202                         + mWifiLogProto.numLastResortWatchdogTriggers);
3203                 pw.println("mWifiLogProto.numLastResortWatchdogBadAssociationNetworksTotal="
3204                         + mWifiLogProto.numLastResortWatchdogBadAssociationNetworksTotal);
3205                 pw.println("mWifiLogProto.numLastResortWatchdogBadAuthenticationNetworksTotal="
3206                         + mWifiLogProto.numLastResortWatchdogBadAuthenticationNetworksTotal);
3207                 pw.println("mWifiLogProto.numLastResortWatchdogBadDhcpNetworksTotal="
3208                         + mWifiLogProto.numLastResortWatchdogBadDhcpNetworksTotal);
3209                 pw.println("mWifiLogProto.numLastResortWatchdogBadOtherNetworksTotal="
3210                         + mWifiLogProto.numLastResortWatchdogBadOtherNetworksTotal);
3211                 pw.println("mWifiLogProto.numLastResortWatchdogAvailableNetworksTotal="
3212                         + mWifiLogProto.numLastResortWatchdogAvailableNetworksTotal);
3213                 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadAssociation="
3214                         + mWifiLogProto.numLastResortWatchdogTriggersWithBadAssociation);
3215                 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadAuthentication="
3216                         + mWifiLogProto.numLastResortWatchdogTriggersWithBadAuthentication);
3217                 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadDhcp="
3218                         + mWifiLogProto.numLastResortWatchdogTriggersWithBadDhcp);
3219                 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadOther="
3220                         + mWifiLogProto.numLastResortWatchdogTriggersWithBadOther);
3221                 pw.println("mWifiLogProto.numLastResortWatchdogSuccesses="
3222                         + mWifiLogProto.numLastResortWatchdogSuccesses);
3223                 pw.println("mWifiLogProto.watchdogTotalConnectionFailureCountAfterTrigger="
3224                         + mWifiLogProto.watchdogTotalConnectionFailureCountAfterTrigger);
3225                 pw.println("mWifiLogProto.watchdogTriggerToConnectionSuccessDurationMs="
3226                         + mWifiLogProto.watchdogTriggerToConnectionSuccessDurationMs);
3227                 pw.println("mWifiLogProto.recordDurationSec="
3228                         + ((mClock.getElapsedSinceBootMillis() / 1000) - mRecordStartTimeSec));
3229 
3230                 try {
3231                     JSONObject rssiMap = new JSONObject();
3232                     for (Map.Entry<Integer, SparseIntArray> entry : mRssiPollCountsMap.entrySet()) {
3233                         int frequency = entry.getKey();
3234                         final SparseIntArray histogram = entry.getValue();
3235                         JSONArray histogramElements = new JSONArray();
3236                         for (int i = MIN_RSSI_POLL; i <= MAX_RSSI_POLL; i++) {
3237                             int count = histogram.get(i);
3238                             if (count == 0) {
3239                                 continue;
3240                             }
3241                             JSONObject histogramElement = new JSONObject();
3242                             histogramElement.put(Integer.toString(i), count);
3243                             histogramElements.put(histogramElement);
3244                         }
3245                         rssiMap.put(Integer.toString(frequency), histogramElements);
3246                     }
3247                     pw.println("mWifiLogProto.rssiPollCount: " + rssiMap.toString());
3248                 } catch (JSONException e) {
3249                     pw.println("JSONException occurred: " + e.getMessage());
3250                 }
3251 
3252                 pw.println("mWifiLogProto.rssiPollDeltaCount: Printing counts for ["
3253                         + MIN_RSSI_DELTA + ", " + MAX_RSSI_DELTA + "]");
3254                 StringBuilder sb = new StringBuilder();
3255                 for (int i = MIN_RSSI_DELTA; i <= MAX_RSSI_DELTA; i++) {
3256                     sb.append(mRssiDeltaCounts.get(i) + " ");
3257                 }
3258                 pw.println("  " + sb.toString());
3259                 pw.println("mWifiLogProto.linkSpeedCounts: ");
3260                 sb.setLength(0);
3261                 for (int i = 0; i < mLinkSpeedCounts.size(); i++) {
3262                     LinkSpeedCount linkSpeedCount = mLinkSpeedCounts.valueAt(i);
3263                     sb.append(linkSpeedCount.linkSpeedMbps).append(":{")
3264                             .append(linkSpeedCount.count).append(", ")
3265                             .append(linkSpeedCount.rssiSumDbm).append(", ")
3266                             .append(linkSpeedCount.rssiSumOfSquaresDbmSq).append("} ");
3267                 }
3268                 if (sb.length() > 0) {
3269                     pw.println(sb.toString());
3270                 }
3271                 pw.print("mWifiLogProto.alertReasonCounts=");
3272                 sb.setLength(0);
3273                 for (int i = WifiLoggerHal.WIFI_ALERT_REASON_MIN;
3274                         i <= WifiLoggerHal.WIFI_ALERT_REASON_MAX; i++) {
3275                     int count = mWifiAlertReasonCounts.get(i);
3276                     if (count > 0) {
3277                         sb.append("(" + i + "," + count + "),");
3278                     }
3279                 }
3280                 if (sb.length() > 1) {
3281                     sb.setLength(sb.length() - 1);  // strip trailing comma
3282                     pw.println(sb.toString());
3283                 } else {
3284                     pw.println("()");
3285                 }
3286                 pw.println("mWifiLogProto.numTotalScanResults="
3287                         + mWifiLogProto.numTotalScanResults);
3288                 pw.println("mWifiLogProto.numOpenNetworkScanResults="
3289                         + mWifiLogProto.numOpenNetworkScanResults);
3290                 pw.println("mWifiLogProto.numLegacyPersonalNetworkScanResults="
3291                         + mWifiLogProto.numLegacyPersonalNetworkScanResults);
3292                 pw.println("mWifiLogProto.numLegacyEnterpriseNetworkScanResults="
3293                         + mWifiLogProto.numLegacyEnterpriseNetworkScanResults);
3294                 pw.println("mWifiLogProto.numEnhancedOpenNetworkScanResults="
3295                         + mWifiLogProto.numEnhancedOpenNetworkScanResults);
3296                 pw.println("mWifiLogProto.numWpa3PersonalNetworkScanResults="
3297                         + mWifiLogProto.numWpa3PersonalNetworkScanResults);
3298                 pw.println("mWifiLogProto.numWpa3EnterpriseNetworkScanResults="
3299                         + mWifiLogProto.numWpa3EnterpriseNetworkScanResults);
3300                 pw.println("mWifiLogProto.numWapiPersonalNetworkScanResults="
3301                         + mWifiLogProto.numWapiPersonalNetworkScanResults);
3302                 pw.println("mWifiLogProto.numWapiEnterpriseNetworkScanResults="
3303                         + mWifiLogProto.numWapiEnterpriseNetworkScanResults);
3304                 pw.println("mWifiLogProto.numHiddenNetworkScanResults="
3305                         + mWifiLogProto.numHiddenNetworkScanResults);
3306                 pw.println("mWifiLogProto.numHotspot2R1NetworkScanResults="
3307                         + mWifiLogProto.numHotspot2R1NetworkScanResults);
3308                 pw.println("mWifiLogProto.numHotspot2R2NetworkScanResults="
3309                         + mWifiLogProto.numHotspot2R2NetworkScanResults);
3310                 pw.println("mWifiLogProto.numHotspot2R3NetworkScanResults="
3311                         + mWifiLogProto.numHotspot2R3NetworkScanResults);
3312                 pw.println("mWifiLogProto.numMboSupportedNetworkScanResults="
3313                         + mWifiLogProto.numMboSupportedNetworkScanResults);
3314                 pw.println("mWifiLogProto.numMboCellularDataAwareNetworkScanResults="
3315                         + mWifiLogProto.numMboCellularDataAwareNetworkScanResults);
3316                 pw.println("mWifiLogProto.numOceSupportedNetworkScanResults="
3317                         + mWifiLogProto.numOceSupportedNetworkScanResults);
3318                 pw.println("mWifiLogProto.numFilsSupportedNetworkScanResults="
3319                         + mWifiLogProto.numFilsSupportedNetworkScanResults);
3320                 pw.println("mWifiLogProto.num11AxNetworkScanResults="
3321                         + mWifiLogProto.num11AxNetworkScanResults);
3322                 pw.println("mWifiLogProto.num6GNetworkScanResults"
3323                         + mWifiLogProto.num6GNetworkScanResults);
3324                 pw.println("mWifiLogProto.numBssidFilteredDueToMboAssocDisallowInd="
3325                         + mWifiLogProto.numBssidFilteredDueToMboAssocDisallowInd);
3326                 pw.println("mWifiLogProto.numConnectToNetworkSupportingMbo="
3327                         + mWifiLogProto.numConnectToNetworkSupportingMbo);
3328                 pw.println("mWifiLogProto.numConnectToNetworkSupportingOce="
3329                         + mWifiLogProto.numConnectToNetworkSupportingOce);
3330                 pw.println("mWifiLogProto.numForceScanDueToSteeringRequest="
3331                         + mWifiLogProto.numForceScanDueToSteeringRequest);
3332                 pw.println("mWifiLogProto.numMboCellularSwitchRequest="
3333                         + mWifiLogProto.numMboCellularSwitchRequest);
3334                 pw.println("mWifiLogProto.numSteeringRequestIncludingMboAssocRetryDelay="
3335                         + mWifiLogProto.numSteeringRequestIncludingMboAssocRetryDelay);
3336                 pw.println("mWifiLogProto.numConnectRequestWithFilsAkm="
3337                         + mWifiLogProto.numConnectRequestWithFilsAkm);
3338                 pw.println("mWifiLogProto.numL2ConnectionThroughFilsAuthentication="
3339                         + mWifiLogProto.numL2ConnectionThroughFilsAuthentication);
3340 
3341                 pw.println("mWifiLogProto.numScans=" + mWifiLogProto.numScans);
3342                 pw.println("mWifiLogProto.WifiScoreCount: [" + MIN_WIFI_SCORE + ", "
3343                         + MAX_WIFI_SCORE + "]");
3344                 for (int i = 0; i <= MAX_WIFI_SCORE; i++) {
3345                     pw.print(mWifiScoreCounts.get(i) + " ");
3346                 }
3347                 pw.println(); // add a line after wifi scores
3348                 pw.println("mWifiLogProto.WifiUsabilityScoreCount: [" + MIN_WIFI_USABILITY_SCORE
3349                         + ", " + MAX_WIFI_USABILITY_SCORE + "]");
3350                 for (int i = MIN_WIFI_USABILITY_SCORE; i <= MAX_WIFI_USABILITY_SCORE; i++) {
3351                     pw.print(mWifiUsabilityScoreCounts.get(i) + " ");
3352                 }
3353                 pw.println(); // add a line after wifi usability scores
3354                 pw.println("mWifiLogProto.SoftApManagerReturnCodeCounts:");
3355                 pw.println("  SUCCESS: " + mSoftApManagerReturnCodeCounts.get(
3356                         WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY));
3357                 pw.println("  FAILED_GENERAL_ERROR: " + mSoftApManagerReturnCodeCounts.get(
3358                         WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR));
3359                 pw.println("  FAILED_NO_CHANNEL: " + mSoftApManagerReturnCodeCounts.get(
3360                         WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL));
3361                 pw.println("  FAILED_UNSUPPORTED_CONFIGURATION: "
3362                         + mSoftApManagerReturnCodeCounts.get(
3363                         WifiMetricsProto.SoftApReturnCodeCount
3364                         .SOFT_AP_FAILED_UNSUPPORTED_CONFIGURATION));
3365                 pw.print("\n");
3366                 pw.println("mWifiLogProto.numHalCrashes="
3367                         + mWifiLogProto.numHalCrashes);
3368                 pw.println("mWifiLogProto.numWificondCrashes="
3369                         + mWifiLogProto.numWificondCrashes);
3370                 pw.println("mWifiLogProto.numSupplicantCrashes="
3371                         + mWifiLogProto.numSupplicantCrashes);
3372                 pw.println("mWifiLogProto.numHostapdCrashes="
3373                         + mWifiLogProto.numHostapdCrashes);
3374                 pw.println("mWifiLogProto.numSetupClientInterfaceFailureDueToHal="
3375                         + mWifiLogProto.numSetupClientInterfaceFailureDueToHal);
3376                 pw.println("mWifiLogProto.numSetupClientInterfaceFailureDueToWificond="
3377                         + mWifiLogProto.numSetupClientInterfaceFailureDueToWificond);
3378                 pw.println("mWifiLogProto.numSetupClientInterfaceFailureDueToSupplicant="
3379                         + mWifiLogProto.numSetupClientInterfaceFailureDueToSupplicant);
3380                 pw.println("mWifiLogProto.numSetupSoftApInterfaceFailureDueToHal="
3381                         + mWifiLogProto.numSetupSoftApInterfaceFailureDueToHal);
3382                 pw.println("mWifiLogProto.numSetupSoftApInterfaceFailureDueToWificond="
3383                         + mWifiLogProto.numSetupSoftApInterfaceFailureDueToWificond);
3384                 pw.println("mWifiLogProto.numSetupSoftApInterfaceFailureDueToHostapd="
3385                         + mWifiLogProto.numSetupSoftApInterfaceFailureDueToHostapd);
3386                 pw.println("StaEventList:");
3387                 for (StaEventWithTime event : mStaEventList) {
3388                     pw.println(event);
3389                 }
3390                 pw.println("UserActionEvents:");
3391                 for (UserActionEventWithTime event : mUserActionEventList) {
3392                     pw.println(event);
3393                 }
3394 
3395                 pw.println("mWifiLogProto.numPasspointProviders="
3396                         + mWifiLogProto.numPasspointProviders);
3397                 pw.println("mWifiLogProto.numPasspointProviderInstallation="
3398                         + mWifiLogProto.numPasspointProviderInstallation);
3399                 pw.println("mWifiLogProto.numPasspointProviderInstallSuccess="
3400                         + mWifiLogProto.numPasspointProviderInstallSuccess);
3401                 pw.println("mWifiLogProto.numPasspointProviderUninstallation="
3402                         + mWifiLogProto.numPasspointProviderUninstallation);
3403                 pw.println("mWifiLogProto.numPasspointProviderUninstallSuccess="
3404                         + mWifiLogProto.numPasspointProviderUninstallSuccess);
3405                 pw.println("mWifiLogProto.numPasspointProvidersSuccessfullyConnected="
3406                         + mWifiLogProto.numPasspointProvidersSuccessfullyConnected);
3407 
3408                 pw.println("mWifiLogProto.installedPasspointProfileTypeForR1:"
3409                         + mInstalledPasspointProfileTypeForR1);
3410                 pw.println("mWifiLogProto.installedPasspointProfileTypeForR2:"
3411                         + mInstalledPasspointProfileTypeForR2);
3412 
3413                 pw.println("mWifiLogProto.passpointProvisionStats.numProvisionSuccess="
3414                             + mNumProvisionSuccess);
3415                 pw.println("mWifiLogProto.passpointProvisionStats.provisionFailureCount:"
3416                             + mPasspointProvisionFailureCounts);
3417 
3418                 pw.println("mWifiLogProto.numRadioModeChangeToMcc="
3419                         + mWifiLogProto.numRadioModeChangeToMcc);
3420                 pw.println("mWifiLogProto.numRadioModeChangeToScc="
3421                         + mWifiLogProto.numRadioModeChangeToScc);
3422                 pw.println("mWifiLogProto.numRadioModeChangeToSbs="
3423                         + mWifiLogProto.numRadioModeChangeToSbs);
3424                 pw.println("mWifiLogProto.numRadioModeChangeToDbs="
3425                         + mWifiLogProto.numRadioModeChangeToDbs);
3426                 pw.println("mWifiLogProto.numSoftApUserBandPreferenceUnsatisfied="
3427                         + mWifiLogProto.numSoftApUserBandPreferenceUnsatisfied);
3428                 pw.println("mTotalSsidsInScanHistogram:"
3429                         + mTotalSsidsInScanHistogram.toString());
3430                 pw.println("mTotalBssidsInScanHistogram:"
3431                         + mTotalBssidsInScanHistogram.toString());
3432                 pw.println("mAvailableOpenSsidsInScanHistogram:"
3433                         + mAvailableOpenSsidsInScanHistogram.toString());
3434                 pw.println("mAvailableOpenBssidsInScanHistogram:"
3435                         + mAvailableOpenBssidsInScanHistogram.toString());
3436                 pw.println("mAvailableSavedSsidsInScanHistogram:"
3437                         + mAvailableSavedSsidsInScanHistogram.toString());
3438                 pw.println("mAvailableSavedBssidsInScanHistogram:"
3439                         + mAvailableSavedBssidsInScanHistogram.toString());
3440                 pw.println("mAvailableOpenOrSavedSsidsInScanHistogram:"
3441                         + mAvailableOpenOrSavedSsidsInScanHistogram.toString());
3442                 pw.println("mAvailableOpenOrSavedBssidsInScanHistogram:"
3443                         + mAvailableOpenOrSavedBssidsInScanHistogram.toString());
3444                 pw.println("mAvailableSavedPasspointProviderProfilesInScanHistogram:"
3445                         + mAvailableSavedPasspointProviderProfilesInScanHistogram.toString());
3446                 pw.println("mAvailableSavedPasspointProviderBssidsInScanHistogram:"
3447                         + mAvailableSavedPasspointProviderBssidsInScanHistogram.toString());
3448                 pw.println("mWifiLogProto.partialAllSingleScanListenerResults="
3449                         + mWifiLogProto.partialAllSingleScanListenerResults);
3450                 pw.println("mWifiLogProto.fullBandAllSingleScanListenerResults="
3451                         + mWifiLogProto.fullBandAllSingleScanListenerResults);
3452                 pw.println("mWifiAwareMetrics:");
3453                 mWifiAwareMetrics.dump(fd, pw, args);
3454                 pw.println("mRttMetrics:");
3455                 mRttMetrics.dump(fd, pw, args);
3456 
3457                 pw.println("mPnoScanMetrics.numPnoScanAttempts="
3458                         + mPnoScanMetrics.numPnoScanAttempts);
3459                 pw.println("mPnoScanMetrics.numPnoScanFailed="
3460                         + mPnoScanMetrics.numPnoScanFailed);
3461                 pw.println("mPnoScanMetrics.numPnoScanStartedOverOffload="
3462                         + mPnoScanMetrics.numPnoScanStartedOverOffload);
3463                 pw.println("mPnoScanMetrics.numPnoScanFailedOverOffload="
3464                         + mPnoScanMetrics.numPnoScanFailedOverOffload);
3465                 pw.println("mPnoScanMetrics.numPnoFoundNetworkEvents="
3466                         + mPnoScanMetrics.numPnoFoundNetworkEvents);
3467 
3468                 pw.println("mWifiLinkLayerUsageStats.loggingDurationMs="
3469                         + mWifiLinkLayerUsageStats.loggingDurationMs);
3470                 pw.println("mWifiLinkLayerUsageStats.radioOnTimeMs="
3471                         + mWifiLinkLayerUsageStats.radioOnTimeMs);
3472                 pw.println("mWifiLinkLayerUsageStats.radioTxTimeMs="
3473                         + mWifiLinkLayerUsageStats.radioTxTimeMs);
3474                 pw.println("mWifiLinkLayerUsageStats.radioRxTimeMs="
3475                         + mWifiLinkLayerUsageStats.radioRxTimeMs);
3476                 pw.println("mWifiLinkLayerUsageStats.radioScanTimeMs="
3477                         + mWifiLinkLayerUsageStats.radioScanTimeMs);
3478                 pw.println("mWifiLinkLayerUsageStats.radioNanScanTimeMs="
3479                         + mWifiLinkLayerUsageStats.radioNanScanTimeMs);
3480                 pw.println("mWifiLinkLayerUsageStats.radioBackgroundScanTimeMs="
3481                         + mWifiLinkLayerUsageStats.radioBackgroundScanTimeMs);
3482                 pw.println("mWifiLinkLayerUsageStats.radioRoamScanTimeMs="
3483                         + mWifiLinkLayerUsageStats.radioRoamScanTimeMs);
3484                 pw.println("mWifiLinkLayerUsageStats.radioPnoScanTimeMs="
3485                         + mWifiLinkLayerUsageStats.radioPnoScanTimeMs);
3486                 pw.println("mWifiLinkLayerUsageStats.radioHs20ScanTimeMs="
3487                         + mWifiLinkLayerUsageStats.radioHs20ScanTimeMs);
3488 
3489                 pw.println("mWifiLogProto.connectToNetworkNotificationCount="
3490                         + mConnectToNetworkNotificationCount.toString());
3491                 pw.println("mWifiLogProto.connectToNetworkNotificationActionCount="
3492                         + mConnectToNetworkNotificationActionCount.toString());
3493                 pw.println("mWifiLogProto.openNetworkRecommenderBlacklistSize="
3494                         + mOpenNetworkRecommenderBlacklistSize);
3495                 pw.println("mWifiLogProto.isWifiNetworksAvailableNotificationOn="
3496                         + mIsWifiNetworksAvailableNotificationOn);
3497                 pw.println("mWifiLogProto.numOpenNetworkRecommendationUpdates="
3498                         + mNumOpenNetworkRecommendationUpdates);
3499                 pw.println("mWifiLogProto.numOpenNetworkConnectMessageFailedToSend="
3500                         + mNumOpenNetworkConnectMessageFailedToSend);
3501 
3502                 pw.println("mWifiLogProto.observedHotspotR1ApInScanHistogram="
3503                         + mObservedHotspotR1ApInScanHistogram);
3504                 pw.println("mWifiLogProto.observedHotspotR2ApInScanHistogram="
3505                         + mObservedHotspotR2ApInScanHistogram);
3506                 pw.println("mWifiLogProto.observedHotspotR3ApInScanHistogram="
3507                         + mObservedHotspotR3ApInScanHistogram);
3508                 pw.println("mWifiLogProto.observedHotspotR1EssInScanHistogram="
3509                         + mObservedHotspotR1EssInScanHistogram);
3510                 pw.println("mWifiLogProto.observedHotspotR2EssInScanHistogram="
3511                         + mObservedHotspotR2EssInScanHistogram);
3512                 pw.println("mWifiLogProto.observedHotspotR3EssInScanHistogram="
3513                         + mObservedHotspotR3EssInScanHistogram);
3514                 pw.println("mWifiLogProto.observedHotspotR1ApsPerEssInScanHistogram="
3515                         + mObservedHotspotR1ApsPerEssInScanHistogram);
3516                 pw.println("mWifiLogProto.observedHotspotR2ApsPerEssInScanHistogram="
3517                         + mObservedHotspotR2ApsPerEssInScanHistogram);
3518                 pw.println("mWifiLogProto.observedHotspotR3ApsPerEssInScanHistogram="
3519                         + mObservedHotspotR3ApsPerEssInScanHistogram);
3520 
3521                 pw.println("mWifiLogProto.observed80211mcSupportingApsInScanHistogram"
3522                         + mObserved80211mcApInScanHistogram);
3523                 pw.println("mWifiLogProto.bssidBlocklistStats:");
3524                 pw.println(mBssidBlocklistStats.toString());
3525 
3526                 pw.println("mSoftApTetheredEvents:");
3527                 for (SoftApConnectedClientsEvent event : mSoftApEventListTethered) {
3528                     StringBuilder eventLine = new StringBuilder();
3529                     eventLine.append("event_type=" + event.eventType);
3530                     eventLine.append(",time_stamp_millis=" + event.timeStampMillis);
3531                     eventLine.append(",num_connected_clients=" + event.numConnectedClients);
3532                     eventLine.append(",channel_frequency=" + event.channelFrequency);
3533                     eventLine.append(",channel_bandwidth=" + event.channelBandwidth);
3534                     eventLine.append(",max_num_clients_setting_in_softap_configuration="
3535                             + event.maxNumClientsSettingInSoftapConfiguration);
3536                     eventLine.append(",max_num_clients_setting_in_softap_capability="
3537                             + event.maxNumClientsSettingInSoftapCapability);
3538                     eventLine.append(",shutdown_timeout_setting_in_softap_configuration="
3539                             + event.shutdownTimeoutSettingInSoftapConfiguration);
3540                     eventLine.append(",default_shutdown_timeout_setting="
3541                             + event.defaultShutdownTimeoutSetting);
3542                     eventLine.append(",client_control_is_enabled=" + event.clientControlIsEnabled);
3543                     pw.println(eventLine.toString());
3544                 }
3545                 pw.println("mSoftApLocalOnlyEvents:");
3546                 for (SoftApConnectedClientsEvent event : mSoftApEventListLocalOnly) {
3547                     StringBuilder eventLine = new StringBuilder();
3548                     eventLine.append("event_type=" + event.eventType);
3549                     eventLine.append(",time_stamp_millis=" + event.timeStampMillis);
3550                     eventLine.append(",num_connected_clients=" + event.numConnectedClients);
3551                     eventLine.append(",channel_frequency=" + event.channelFrequency);
3552                     eventLine.append(",channel_bandwidth=" + event.channelBandwidth);
3553                     eventLine.append(",max_num_clients_setting_in_softap_configuration="
3554                             + event.maxNumClientsSettingInSoftapConfiguration);
3555                     eventLine.append(",max_num_clients_setting_in_softap_capability="
3556                             + event.maxNumClientsSettingInSoftapCapability);
3557                     eventLine.append(",shutdown_timeout_setting_in_softap_configuration="
3558                             + event.shutdownTimeoutSettingInSoftapConfiguration);
3559                     eventLine.append(",default_shutdown_timeout_setting="
3560                             + event.defaultShutdownTimeoutSetting);
3561                     eventLine.append(",client_control_is_enabled=" + event.clientControlIsEnabled);
3562                     pw.println(eventLine.toString());
3563                 }
3564 
3565                 mWifiPowerMetrics.dump(pw);
3566                 mWifiWakeMetrics.dump(pw);
3567 
3568                 pw.println("mWifiLogProto.isMacRandomizationOn="
3569                         + mContext.getResources().getBoolean(
3570                                 R.bool.config_wifi_connected_mac_randomization_supported));
3571                 pw.println("mWifiLogProto.scoreExperimentId=" + mWifiLogProto.scoreExperimentId);
3572                 pw.println("mExperimentValues.wifiIsUnusableLoggingEnabled="
3573                         + mContext.getResources().getBoolean(
3574                                 R.bool.config_wifiIsUnusableEventMetricsEnabled));
3575                 pw.println("mExperimentValues.wifiDataStallMinTxBad="
3576                         + mContext.getResources().getInteger(
3577                                 R.integer.config_wifiDataStallMinTxBad));
3578                 pw.println("mExperimentValues.wifiDataStallMinTxSuccessWithoutRx="
3579                         + mContext.getResources().getInteger(
3580                                 R.integer.config_wifiDataStallMinTxSuccessWithoutRx));
3581                 pw.println("mExperimentValues.linkSpeedCountsLoggingEnabled="
3582                         + mContext.getResources().getBoolean(
3583                                 R.bool.config_wifiLinkSpeedMetricsEnabled));
3584                 pw.println("mExperimentValues.dataStallDurationMs="
3585                         + mExperimentValues.dataStallDurationMs);
3586                 pw.println("mExperimentValues.dataStallTxTputThrKbps="
3587                         + mExperimentValues.dataStallTxTputThrKbps);
3588                 pw.println("mExperimentValues.dataStallRxTputThrKbps="
3589                         + mExperimentValues.dataStallRxTputThrKbps);
3590                 pw.println("mExperimentValues.dataStallTxPerThr="
3591                         + mExperimentValues.dataStallTxPerThr);
3592                 pw.println("mExperimentValues.dataStallCcaLevelThr="
3593                         + mExperimentValues.dataStallCcaLevelThr);
3594                 pw.println("WifiIsUnusableEventList: ");
3595                 for (WifiIsUnusableWithTime event : mWifiIsUnusableList) {
3596                     pw.println(event);
3597                 }
3598                 pw.println("Hardware Version: " + SystemProperties.get("ro.boot.revision", ""));
3599 
3600                 pw.println("mWifiUsabilityStatsEntriesList:");
3601                 for (WifiUsabilityStatsEntry stats : mWifiUsabilityStatsEntriesList) {
3602                     printWifiUsabilityStatsEntry(pw, stats);
3603                 }
3604                 pw.println("mWifiUsabilityStatsList:");
3605                 for (WifiUsabilityStats stats : mWifiUsabilityStatsListGood) {
3606                     pw.println("\nlabel=" + stats.label);
3607                     pw.println("\ntrigger_type=" + stats.triggerType);
3608                     pw.println("\ntime_stamp_ms=" + stats.timeStampMs);
3609                     for (WifiUsabilityStatsEntry entry : stats.stats) {
3610                         printWifiUsabilityStatsEntry(pw, entry);
3611                     }
3612                 }
3613                 for (WifiUsabilityStats stats : mWifiUsabilityStatsListBad) {
3614                     pw.println("\nlabel=" + stats.label);
3615                     pw.println("\ntrigger_type=" + stats.triggerType);
3616                     pw.println("\ntime_stamp_ms=" + stats.timeStampMs);
3617                     for (WifiUsabilityStatsEntry entry : stats.stats) {
3618                         printWifiUsabilityStatsEntry(pw, entry);
3619                     }
3620                 }
3621 
3622                 pw.println("mMobilityStatePnoStatsMap:");
3623                 for (int i = 0; i < mMobilityStatePnoStatsMap.size(); i++) {
3624                     printDeviceMobilityStatePnoScanStats(pw, mMobilityStatePnoStatsMap.valueAt(i));
3625                 }
3626 
3627                 mWifiP2pMetrics.dump(pw);
3628                 pw.println("mDppMetrics:");
3629                 mDppMetrics.dump(pw);
3630 
3631                 pw.println("mWifiConfigStoreReadDurationHistogram:"
3632                         + mWifiConfigStoreReadDurationHistogram.toString());
3633                 pw.println("mWifiConfigStoreWriteDurationHistogram:"
3634                         + mWifiConfigStoreWriteDurationHistogram.toString());
3635 
3636                 pw.println("mLinkProbeSuccessRssiCounts:" + mLinkProbeSuccessRssiCounts);
3637                 pw.println("mLinkProbeFailureRssiCounts:" + mLinkProbeFailureRssiCounts);
3638                 pw.println("mLinkProbeSuccessLinkSpeedCounts:" + mLinkProbeSuccessLinkSpeedCounts);
3639                 pw.println("mLinkProbeFailureLinkSpeedCounts:" + mLinkProbeFailureLinkSpeedCounts);
3640                 pw.println("mLinkProbeSuccessSecondsSinceLastTxSuccessHistogram:"
3641                         + mLinkProbeSuccessSecondsSinceLastTxSuccessHistogram);
3642                 pw.println("mLinkProbeFailureSecondsSinceLastTxSuccessHistogram:"
3643                         + mLinkProbeFailureSecondsSinceLastTxSuccessHistogram);
3644                 pw.println("mLinkProbeSuccessElapsedTimeMsHistogram:"
3645                         + mLinkProbeSuccessElapsedTimeMsHistogram);
3646                 pw.println("mLinkProbeFailureReasonCounts:" + mLinkProbeFailureReasonCounts);
3647                 pw.println("mLinkProbeExperimentProbeCounts:" + mLinkProbeExperimentProbeCounts);
3648 
3649                 pw.println("mNetworkSelectionExperimentPairNumChoicesCounts:"
3650                         + mNetworkSelectionExperimentPairNumChoicesCounts);
3651                 pw.println("mLinkProbeStaEventCount:" + mLinkProbeStaEventCount);
3652 
3653                 pw.println("mWifiNetworkRequestApiLog:\n" + mWifiNetworkRequestApiLog);
3654                 pw.println("mWifiNetworkRequestApiMatchSizeHistogram:\n"
3655                         + mWifiNetworkRequestApiMatchSizeHistogram);
3656                 pw.println("mWifiNetworkSuggestionApiLog:\n" + mWifiNetworkSuggestionApiLog);
3657                 pw.println("mWifiNetworkSuggestionApiMatchSizeHistogram:\n"
3658                         + mWifiNetworkSuggestionApiListSizeHistogram);
3659                 pw.println("mWifiNetworkSuggestionApiAppTypeCounter:\n"
3660                         + mWifiNetworkSuggestionApiAppTypeCounter);
3661                 printUserApprovalSuggestionAppReaction(pw);
3662                 printUserApprovalCarrierReaction(pw);
3663                 pw.println("mNetworkIdToNominatorId:\n" + mNetworkIdToNominatorId);
3664                 pw.println("mWifiLockStats:\n" + mWifiLockStats);
3665                 pw.println("mWifiLockHighPerfAcqDurationSecHistogram:\n"
3666                         + mWifiLockHighPerfAcqDurationSecHistogram);
3667                 pw.println("mWifiLockLowLatencyAcqDurationSecHistogram:\n"
3668                         + mWifiLockLowLatencyAcqDurationSecHistogram);
3669                 pw.println("mWifiLockHighPerfActiveSessionDurationSecHistogram:\n"
3670                         + mWifiLockHighPerfActiveSessionDurationSecHistogram);
3671                 pw.println("mWifiLockLowLatencyActiveSessionDurationSecHistogram:\n"
3672                         + mWifiLockLowLatencyActiveSessionDurationSecHistogram);
3673                 pw.println("mWifiToggleStats:\n" + mWifiToggleStats);
3674                 pw.println("mWifiLogProto.numAddOrUpdateNetworkCalls="
3675                         + mWifiLogProto.numAddOrUpdateNetworkCalls);
3676                 pw.println("mWifiLogProto.numEnableNetworkCalls="
3677                         + mWifiLogProto.numEnableNetworkCalls);
3678 
3679                 pw.println("mWifiLogProto.txLinkSpeedCount2g=" + mTxLinkSpeedCount2g);
3680                 pw.println("mWifiLogProto.txLinkSpeedCount5gLow=" + mTxLinkSpeedCount5gLow);
3681                 pw.println("mWifiLogProto.txLinkSpeedCount5gMid=" + mTxLinkSpeedCount5gMid);
3682                 pw.println("mWifiLogProto.txLinkSpeedCount5gHigh=" + mTxLinkSpeedCount5gHigh);
3683                 pw.println("mWifiLogProto.txLinkSpeedCount6gLow=" + mTxLinkSpeedCount6gLow);
3684                 pw.println("mWifiLogProto.txLinkSpeedCount6gMid=" + mTxLinkSpeedCount6gMid);
3685                 pw.println("mWifiLogProto.txLinkSpeedCount6gHigh=" + mTxLinkSpeedCount6gHigh);
3686 
3687                 pw.println("mWifiLogProto.rxLinkSpeedCount2g=" + mRxLinkSpeedCount2g);
3688                 pw.println("mWifiLogProto.rxLinkSpeedCount5gLow=" + mRxLinkSpeedCount5gLow);
3689                 pw.println("mWifiLogProto.rxLinkSpeedCount5gMid=" + mRxLinkSpeedCount5gMid);
3690                 pw.println("mWifiLogProto.rxLinkSpeedCount5gHigh=" + mRxLinkSpeedCount5gHigh);
3691                 pw.println("mWifiLogProto.rxLinkSpeedCount6gLow=" + mRxLinkSpeedCount6gLow);
3692                 pw.println("mWifiLogProto.rxLinkSpeedCount6gMid=" + mRxLinkSpeedCount6gMid);
3693                 pw.println("mWifiLogProto.rxLinkSpeedCount6gHigh=" + mRxLinkSpeedCount6gHigh);
3694 
3695                 pw.println("mWifiLogProto.numIpRenewalFailure="
3696                         + mWifiLogProto.numIpRenewalFailure);
3697                 pw.println("mWifiLogProto.connectionDurationStats="
3698                         + mConnectionDurationStats.toString());
3699                 pw.println("mWifiLogProto.isExternalWifiScorerOn="
3700                         + mWifiLogProto.isExternalWifiScorerOn);
3701                 pw.println("mWifiLogProto.wifiOffMetrics="
3702                         + mWifiOffMetrics.toString());
3703                 pw.println("mWifiLogProto.softApConfigLimitationMetrics="
3704                         + mSoftApConfigLimitationMetrics.toString());
3705                 pw.println("mChannelUtilizationHistogram2G:\n"
3706                         + mChannelUtilizationHistogram2G);
3707                 pw.println("mChannelUtilizationHistogramAbove2G:\n"
3708                         + mChannelUtilizationHistogramAbove2G);
3709                 pw.println("mTxThroughputMbpsHistogram2G:\n"
3710                         + mTxThroughputMbpsHistogram2G);
3711                 pw.println("mRxThroughputMbpsHistogram2G:\n"
3712                         + mRxThroughputMbpsHistogram2G);
3713                 pw.println("mTxThroughputMbpsHistogramAbove2G:\n"
3714                         + mTxThroughputMbpsHistogramAbove2G);
3715                 pw.println("mRxThroughputMbpsHistogramAbove2G:\n"
3716                         + mRxThroughputMbpsHistogramAbove2G);
3717                 pw.println("mCarrierWifiMetrics:\n"
3718                         + mCarrierWifiMetrics);
3719 
3720                 dumpInitPartialScanMetrics(pw);
3721             }
3722         }
3723     }
3724 
dumpInitPartialScanMetrics(PrintWriter pw)3725     private void dumpInitPartialScanMetrics(PrintWriter pw) {
3726         pw.println("mInitPartialScanTotalCount:\n" + mInitPartialScanTotalCount);
3727         pw.println("mInitPartialScanSuccessCount:\n" + mInitPartialScanSuccessCount);
3728         pw.println("mInitPartialScanFailureCount:\n" + mInitPartialScanFailureCount);
3729         pw.println("mInitPartialScanSuccessHistogram:\n" + mInitPartialScanSuccessHistogram);
3730         pw.println("mInitPartialScanFailureHistogram:\n" + mInitPartialScanFailureHistogram);
3731     }
3732 
printWifiUsabilityStatsEntry(PrintWriter pw, WifiUsabilityStatsEntry entry)3733     private void printWifiUsabilityStatsEntry(PrintWriter pw, WifiUsabilityStatsEntry entry) {
3734         StringBuilder line = new StringBuilder();
3735         line.append("timestamp_ms=" + entry.timeStampMs);
3736         line.append(",rssi=" + entry.rssi);
3737         line.append(",link_speed_mbps=" + entry.linkSpeedMbps);
3738         line.append(",total_tx_success=" + entry.totalTxSuccess);
3739         line.append(",total_tx_retries=" + entry.totalTxRetries);
3740         line.append(",total_tx_bad=" + entry.totalTxBad);
3741         line.append(",total_rx_success=" + entry.totalRxSuccess);
3742         line.append(",total_radio_on_time_ms=" + entry.totalRadioOnTimeMs);
3743         line.append(",total_radio_tx_time_ms=" + entry.totalRadioTxTimeMs);
3744         line.append(",total_radio_rx_time_ms=" + entry.totalRadioRxTimeMs);
3745         line.append(",total_scan_time_ms=" + entry.totalScanTimeMs);
3746         line.append(",total_nan_scan_time_ms=" + entry.totalNanScanTimeMs);
3747         line.append(",total_background_scan_time_ms=" + entry.totalBackgroundScanTimeMs);
3748         line.append(",total_roam_scan_time_ms=" + entry.totalRoamScanTimeMs);
3749         line.append(",total_pno_scan_time_ms=" + entry.totalPnoScanTimeMs);
3750         line.append(",total_hotspot_2_scan_time_ms=" + entry.totalHotspot2ScanTimeMs);
3751         line.append(",wifi_score=" + entry.wifiScore);
3752         line.append(",wifi_usability_score=" + entry.wifiUsabilityScore);
3753         line.append(",seq_num_to_framework=" + entry.seqNumToFramework);
3754         line.append(",prediction_horizon_sec=" + entry.predictionHorizonSec);
3755         line.append(",total_cca_busy_freq_time_ms=" + entry.totalCcaBusyFreqTimeMs);
3756         line.append(",total_radio_on_freq_time_ms=" + entry.totalRadioOnFreqTimeMs);
3757         line.append(",total_beacon_rx=" + entry.totalBeaconRx);
3758         line.append(",probe_status_since_last_update=" + entry.probeStatusSinceLastUpdate);
3759         line.append(",probe_elapsed_time_ms_since_last_update="
3760                 + entry.probeElapsedTimeSinceLastUpdateMs);
3761         line.append(",probe_mcs_rate_since_last_update=" + entry.probeMcsRateSinceLastUpdate);
3762         line.append(",rx_link_speed_mbps=" + entry.rxLinkSpeedMbps);
3763         line.append(",seq_num_inside_framework=" + entry.seqNumInsideFramework);
3764         line.append(",is_same_bssid_and_freq=" + entry.isSameBssidAndFreq);
3765         line.append(",device_mobility_state=" + entry.deviceMobilityState);
3766         pw.println(line.toString());
3767     }
3768 
printDeviceMobilityStatePnoScanStats(PrintWriter pw, DeviceMobilityStatePnoScanStats stats)3769     private void printDeviceMobilityStatePnoScanStats(PrintWriter pw,
3770             DeviceMobilityStatePnoScanStats stats) {
3771         StringBuilder line = new StringBuilder();
3772         line.append("device_mobility_state=" + stats.deviceMobilityState);
3773         line.append(",num_times_entered_state=" + stats.numTimesEnteredState);
3774         line.append(",total_duration_ms=" + stats.totalDurationMs);
3775         line.append(",pno_duration_ms=" + stats.pnoDurationMs);
3776         pw.println(line.toString());
3777     }
3778 
printUserApprovalSuggestionAppReaction(PrintWriter pw)3779     private void printUserApprovalSuggestionAppReaction(PrintWriter pw) {
3780         pw.println("mUserApprovalSuggestionAppUiUserReaction:");
3781         for (UserReaction event : mUserApprovalSuggestionAppUiReactionList) {
3782             pw.println(event);
3783         }
3784     }
3785 
printUserApprovalCarrierReaction(PrintWriter pw)3786     private void printUserApprovalCarrierReaction(PrintWriter pw) {
3787         pw.println("mUserApprovalCarrierUiUserReaction:");
3788         for (UserReaction event : mUserApprovalCarrierUiReactionList) {
3789             pw.println(event);
3790         }
3791     }
3792 
3793     /**
3794      * Update various counts of saved network types
3795      * @param networks List of WifiConfigurations representing all saved networks, must not be null
3796      */
updateSavedNetworks(List<WifiConfiguration> networks)3797     public void updateSavedNetworks(List<WifiConfiguration> networks) {
3798         synchronized (mLock) {
3799             mWifiLogProto.numSavedNetworks = networks.size();
3800             mWifiLogProto.numSavedNetworksWithMacRandomization = 0;
3801             mWifiLogProto.numOpenNetworks = 0;
3802             mWifiLogProto.numLegacyPersonalNetworks = 0;
3803             mWifiLogProto.numLegacyEnterpriseNetworks = 0;
3804             mWifiLogProto.numEnhancedOpenNetworks = 0;
3805             mWifiLogProto.numWpa3PersonalNetworks = 0;
3806             mWifiLogProto.numWpa3EnterpriseNetworks = 0;
3807             mWifiLogProto.numWapiPersonalNetworks = 0;
3808             mWifiLogProto.numWapiEnterpriseNetworks = 0;
3809             mWifiLogProto.numNetworksAddedByUser = 0;
3810             mWifiLogProto.numNetworksAddedByApps = 0;
3811             mWifiLogProto.numHiddenNetworks = 0;
3812             mWifiLogProto.numPasspointNetworks = 0;
3813 
3814             for (WifiConfiguration config : networks) {
3815                 if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)) {
3816                     mWifiLogProto.numOpenNetworks++;
3817                 } else if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.OWE)) {
3818                     mWifiLogProto.numEnhancedOpenNetworks++;
3819                 } else if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WAPI_PSK)) {
3820                     mWifiLogProto.numWapiPersonalNetworks++;
3821                 } else if (config.isEnterprise()) {
3822                     if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SUITE_B_192)) {
3823                         mWifiLogProto.numWpa3EnterpriseNetworks++;
3824                     } else if (config.allowedKeyManagement.get(
3825                             WifiConfiguration.KeyMgmt.WAPI_CERT)) {
3826                         mWifiLogProto.numWapiEnterpriseNetworks++;
3827                     } else {
3828                         mWifiLogProto.numLegacyEnterpriseNetworks++;
3829                     }
3830                 } else {
3831                     if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SAE)) {
3832                         mWifiLogProto.numWpa3PersonalNetworks++;
3833                     } else {
3834                         mWifiLogProto.numLegacyPersonalNetworks++;
3835                     }
3836                 }
3837                 mWifiLogProto.numNetworksAddedByApps++;
3838                 if (config.hiddenSSID) {
3839                     mWifiLogProto.numHiddenNetworks++;
3840                 }
3841                 if (config.isPasspoint()) {
3842                     mWifiLogProto.numPasspointNetworks++;
3843                 }
3844                 if (config.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_PERSISTENT) {
3845                     mWifiLogProto.numSavedNetworksWithMacRandomization++;
3846                 }
3847             }
3848         }
3849     }
3850 
3851     /**
3852      * Update metrics for saved Passpoint profiles.
3853      *
3854      * @param numSavedProfiles The number of saved Passpoint profiles
3855      * @param numConnectedProfiles The number of saved Passpoint profiles that have ever resulted
3856      *                             in a successful network connection
3857      */
updateSavedPasspointProfiles(int numSavedProfiles, int numConnectedProfiles)3858     public void updateSavedPasspointProfiles(int numSavedProfiles, int numConnectedProfiles) {
3859         synchronized (mLock) {
3860             mWifiLogProto.numPasspointProviders = numSavedProfiles;
3861             mWifiLogProto.numPasspointProvidersSuccessfullyConnected = numConnectedProfiles;
3862         }
3863     }
3864 
3865     /**
3866      * Update number of times for type of saved Passpoint profile.
3867      *
3868      * @param providers Passpoint providers installed on the device.
3869      */
updateSavedPasspointProfilesInfo( Map<String, PasspointProvider> providers)3870     public void updateSavedPasspointProfilesInfo(
3871             Map<String, PasspointProvider> providers) {
3872         int passpointType;
3873         int eapType;
3874         PasspointConfiguration config;
3875         synchronized (mLock) {
3876             mInstalledPasspointProfileTypeForR1.clear();
3877             mInstalledPasspointProfileTypeForR2.clear();
3878             for (Map.Entry<String, PasspointProvider> entry : providers.entrySet()) {
3879                 config = entry.getValue().getConfig();
3880                 if (config.getCredential().getUserCredential() != null) {
3881                     eapType = EAPConstants.EAP_TTLS;
3882                 } else if (config.getCredential().getCertCredential() != null) {
3883                     eapType = EAPConstants.EAP_TLS;
3884                 } else if (config.getCredential().getSimCredential() != null) {
3885                     eapType = config.getCredential().getSimCredential().getEapType();
3886                 } else {
3887                     eapType = -1;
3888                 }
3889                 switch (eapType) {
3890                     case EAPConstants.EAP_TLS:
3891                         passpointType = WifiMetricsProto.PasspointProfileTypeCount.TYPE_EAP_TLS;
3892                         break;
3893                     case EAPConstants.EAP_TTLS:
3894                         passpointType = WifiMetricsProto.PasspointProfileTypeCount.TYPE_EAP_TTLS;
3895                         break;
3896                     case EAPConstants.EAP_SIM:
3897                         passpointType = WifiMetricsProto.PasspointProfileTypeCount.TYPE_EAP_SIM;
3898                         break;
3899                     case EAPConstants.EAP_AKA:
3900                         passpointType = WifiMetricsProto.PasspointProfileTypeCount.TYPE_EAP_AKA;
3901                         break;
3902                     case EAPConstants.EAP_AKA_PRIME:
3903                         passpointType =
3904                                 WifiMetricsProto.PasspointProfileTypeCount.TYPE_EAP_AKA_PRIME;
3905                         break;
3906                     default:
3907                         passpointType = WifiMetricsProto.PasspointProfileTypeCount.TYPE_UNKNOWN;
3908 
3909                 }
3910                 if (config.validateForR2()) {
3911                     mInstalledPasspointProfileTypeForR2.increment(passpointType);
3912                 } else {
3913                     mInstalledPasspointProfileTypeForR1.increment(passpointType);
3914                 }
3915             }
3916         }
3917     }
3918 
3919     /**
3920      * Increment initial partial scan count
3921      */
incrementInitialPartialScanCount()3922     public void incrementInitialPartialScanCount() {
3923         synchronized (mLock) {
3924             mInitPartialScanTotalCount++;
3925         }
3926     }
3927 
3928     /**
3929      * Report of initial partial scan
3930      * @param channelCount number of channels used in this scan
3931      * @param status true if scan resulted in a network connection attempt, false otherwise
3932      */
reportInitialPartialScan(int channelCount, boolean status)3933     public void reportInitialPartialScan(int channelCount, boolean status) {
3934         synchronized (mLock) {
3935             if (status) {
3936                 mInitPartialScanSuccessCount++;
3937                 mInitPartialScanSuccessHistogram.increment(channelCount);
3938             } else {
3939                 mInitPartialScanFailureCount++;
3940                 mInitPartialScanFailureHistogram.increment(channelCount);
3941             }
3942         }
3943     }
3944 
3945     /**
3946      * Put all metrics that were being tracked separately into mWifiLogProto
3947      */
consolidateProto()3948     private void consolidateProto() {
3949         List<WifiMetricsProto.RssiPollCount> rssis = new ArrayList<>();
3950         synchronized (mLock) {
3951             int connectionEventCount = mConnectionEventList.size();
3952             // Exclude the current active un-ended connection event
3953             if (mCurrentConnectionEvent != null) {
3954                 connectionEventCount--;
3955             }
3956             mWifiLogProto.connectionEvent =
3957                     new WifiMetricsProto.ConnectionEvent[connectionEventCount];
3958             for (int i = 0; i < connectionEventCount; i++) {
3959                 mWifiLogProto.connectionEvent[i] = mConnectionEventList.get(i).mConnectionEvent;
3960             }
3961 
3962             //Convert the SparseIntArray of scanReturnEntry integers into ScanReturnEntry proto list
3963             mWifiLogProto.scanReturnEntries =
3964                     new WifiMetricsProto.WifiLog.ScanReturnEntry[mScanReturnEntries.size()];
3965             for (int i = 0; i < mScanReturnEntries.size(); i++) {
3966                 mWifiLogProto.scanReturnEntries[i] = new WifiMetricsProto.WifiLog.ScanReturnEntry();
3967                 mWifiLogProto.scanReturnEntries[i].scanReturnCode = mScanReturnEntries.keyAt(i);
3968                 mWifiLogProto.scanReturnEntries[i].scanResultsCount = mScanReturnEntries.valueAt(i);
3969             }
3970 
3971             // Convert the SparseIntArray of systemStateEntry into WifiSystemStateEntry proto list
3972             // This one is slightly more complex, as the Sparse are indexed with:
3973             //     key: wifiState * 2 + isScreenOn, value: wifiStateCount
3974             mWifiLogProto.wifiSystemStateEntries =
3975                     new WifiMetricsProto.WifiLog
3976                     .WifiSystemStateEntry[mWifiSystemStateEntries.size()];
3977             for (int i = 0; i < mWifiSystemStateEntries.size(); i++) {
3978                 mWifiLogProto.wifiSystemStateEntries[i] =
3979                         new WifiMetricsProto.WifiLog.WifiSystemStateEntry();
3980                 mWifiLogProto.wifiSystemStateEntries[i].wifiState =
3981                         mWifiSystemStateEntries.keyAt(i) / 2;
3982                 mWifiLogProto.wifiSystemStateEntries[i].wifiStateCount =
3983                         mWifiSystemStateEntries.valueAt(i);
3984                 mWifiLogProto.wifiSystemStateEntries[i].isScreenOn =
3985                         (mWifiSystemStateEntries.keyAt(i) % 2) > 0;
3986             }
3987             mWifiLogProto.recordDurationSec = (int) ((mClock.getElapsedSinceBootMillis() / 1000)
3988                     - mRecordStartTimeSec);
3989 
3990             /**
3991              * Convert the SparseIntArrays of RSSI poll rssi, counts, and frequency to the
3992              * proto's repeated IntKeyVal array.
3993              */
3994             for (Map.Entry<Integer, SparseIntArray> entry : mRssiPollCountsMap.entrySet()) {
3995                 int frequency = entry.getKey();
3996                 SparseIntArray histogram = entry.getValue();
3997                 for (int i = 0; i < histogram.size(); i++) {
3998                     WifiMetricsProto.RssiPollCount keyVal = new WifiMetricsProto.RssiPollCount();
3999                     keyVal.rssi = histogram.keyAt(i);
4000                     keyVal.count = histogram.valueAt(i);
4001                     keyVal.frequency = frequency;
4002                     rssis.add(keyVal);
4003                 }
4004             }
4005             mWifiLogProto.rssiPollRssiCount = rssis.toArray(mWifiLogProto.rssiPollRssiCount);
4006 
4007             /**
4008              * Convert the SparseIntArray of RSSI delta rssi's and counts to the proto's repeated
4009              * IntKeyVal array.
4010              */
4011             mWifiLogProto.rssiPollDeltaCount =
4012                     new WifiMetricsProto.RssiPollCount[mRssiDeltaCounts.size()];
4013             for (int i = 0; i < mRssiDeltaCounts.size(); i++) {
4014                 mWifiLogProto.rssiPollDeltaCount[i] = new WifiMetricsProto.RssiPollCount();
4015                 mWifiLogProto.rssiPollDeltaCount[i].rssi = mRssiDeltaCounts.keyAt(i);
4016                 mWifiLogProto.rssiPollDeltaCount[i].count = mRssiDeltaCounts.valueAt(i);
4017             }
4018 
4019             /**
4020              * Add LinkSpeedCount objects from mLinkSpeedCounts to proto.
4021              */
4022             mWifiLogProto.linkSpeedCounts =
4023                     new WifiMetricsProto.LinkSpeedCount[mLinkSpeedCounts.size()];
4024             for (int i = 0; i < mLinkSpeedCounts.size(); i++) {
4025                 mWifiLogProto.linkSpeedCounts[i] = mLinkSpeedCounts.valueAt(i);
4026             }
4027 
4028             /**
4029              * Convert the SparseIntArray of alert reasons and counts to the proto's repeated
4030              * IntKeyVal array.
4031              */
4032             mWifiLogProto.alertReasonCount =
4033                     new WifiMetricsProto.AlertReasonCount[mWifiAlertReasonCounts.size()];
4034             for (int i = 0; i < mWifiAlertReasonCounts.size(); i++) {
4035                 mWifiLogProto.alertReasonCount[i] = new WifiMetricsProto.AlertReasonCount();
4036                 mWifiLogProto.alertReasonCount[i].reason = mWifiAlertReasonCounts.keyAt(i);
4037                 mWifiLogProto.alertReasonCount[i].count = mWifiAlertReasonCounts.valueAt(i);
4038             }
4039 
4040             /**
4041             *  Convert the SparseIntArray of Wifi Score and counts to proto's repeated
4042             * IntKeyVal array.
4043             */
4044             mWifiLogProto.wifiScoreCount =
4045                     new WifiMetricsProto.WifiScoreCount[mWifiScoreCounts.size()];
4046             for (int score = 0; score < mWifiScoreCounts.size(); score++) {
4047                 mWifiLogProto.wifiScoreCount[score] = new WifiMetricsProto.WifiScoreCount();
4048                 mWifiLogProto.wifiScoreCount[score].score = mWifiScoreCounts.keyAt(score);
4049                 mWifiLogProto.wifiScoreCount[score].count = mWifiScoreCounts.valueAt(score);
4050             }
4051 
4052             /**
4053              * Convert the SparseIntArray of Wifi Usability Score and counts to proto's repeated
4054              * IntKeyVal array.
4055              */
4056             mWifiLogProto.wifiUsabilityScoreCount =
4057                 new WifiMetricsProto.WifiUsabilityScoreCount[mWifiUsabilityScoreCounts.size()];
4058             for (int scoreIdx = 0; scoreIdx < mWifiUsabilityScoreCounts.size(); scoreIdx++) {
4059                 mWifiLogProto.wifiUsabilityScoreCount[scoreIdx] =
4060                     new WifiMetricsProto.WifiUsabilityScoreCount();
4061                 mWifiLogProto.wifiUsabilityScoreCount[scoreIdx].score =
4062                     mWifiUsabilityScoreCounts.keyAt(scoreIdx);
4063                 mWifiLogProto.wifiUsabilityScoreCount[scoreIdx].count =
4064                     mWifiUsabilityScoreCounts.valueAt(scoreIdx);
4065             }
4066 
4067             /**
4068              * Convert the SparseIntArray of SoftAp Return codes and counts to proto's repeated
4069              * IntKeyVal array.
4070              */
4071             int codeCounts = mSoftApManagerReturnCodeCounts.size();
4072             mWifiLogProto.softApReturnCode = new WifiMetricsProto.SoftApReturnCodeCount[codeCounts];
4073             for (int sapCode = 0; sapCode < codeCounts; sapCode++) {
4074                 mWifiLogProto.softApReturnCode[sapCode] =
4075                         new WifiMetricsProto.SoftApReturnCodeCount();
4076                 mWifiLogProto.softApReturnCode[sapCode].startResult =
4077                         mSoftApManagerReturnCodeCounts.keyAt(sapCode);
4078                 mWifiLogProto.softApReturnCode[sapCode].count =
4079                         mSoftApManagerReturnCodeCounts.valueAt(sapCode);
4080             }
4081 
4082             /**
4083              * Convert StaEventList to array of StaEvents
4084              */
4085             mWifiLogProto.staEventList = new StaEvent[mStaEventList.size()];
4086             for (int i = 0; i < mStaEventList.size(); i++) {
4087                 mWifiLogProto.staEventList[i] = mStaEventList.get(i).staEvent;
4088             }
4089             mWifiLogProto.userActionEvents = new UserActionEvent[mUserActionEventList.size()];
4090             for (int i = 0; i < mUserActionEventList.size(); i++) {
4091                 mWifiLogProto.userActionEvents[i] = mUserActionEventList.get(i).toProto();
4092             }
4093             mWifiLogProto.totalSsidsInScanHistogram =
4094                     makeNumConnectableNetworksBucketArray(mTotalSsidsInScanHistogram);
4095             mWifiLogProto.totalBssidsInScanHistogram =
4096                     makeNumConnectableNetworksBucketArray(mTotalBssidsInScanHistogram);
4097             mWifiLogProto.availableOpenSsidsInScanHistogram =
4098                     makeNumConnectableNetworksBucketArray(mAvailableOpenSsidsInScanHistogram);
4099             mWifiLogProto.availableOpenBssidsInScanHistogram =
4100                     makeNumConnectableNetworksBucketArray(mAvailableOpenBssidsInScanHistogram);
4101             mWifiLogProto.availableSavedSsidsInScanHistogram =
4102                     makeNumConnectableNetworksBucketArray(mAvailableSavedSsidsInScanHistogram);
4103             mWifiLogProto.availableSavedBssidsInScanHistogram =
4104                     makeNumConnectableNetworksBucketArray(mAvailableSavedBssidsInScanHistogram);
4105             mWifiLogProto.availableOpenOrSavedSsidsInScanHistogram =
4106                     makeNumConnectableNetworksBucketArray(
4107                     mAvailableOpenOrSavedSsidsInScanHistogram);
4108             mWifiLogProto.availableOpenOrSavedBssidsInScanHistogram =
4109                     makeNumConnectableNetworksBucketArray(
4110                     mAvailableOpenOrSavedBssidsInScanHistogram);
4111             mWifiLogProto.availableSavedPasspointProviderProfilesInScanHistogram =
4112                     makeNumConnectableNetworksBucketArray(
4113                     mAvailableSavedPasspointProviderProfilesInScanHistogram);
4114             mWifiLogProto.availableSavedPasspointProviderBssidsInScanHistogram =
4115                     makeNumConnectableNetworksBucketArray(
4116                     mAvailableSavedPasspointProviderBssidsInScanHistogram);
4117             mWifiLogProto.wifiAwareLog = mWifiAwareMetrics.consolidateProto();
4118             mWifiLogProto.wifiRttLog = mRttMetrics.consolidateProto();
4119 
4120             mWifiLogProto.pnoScanMetrics = mPnoScanMetrics;
4121             mWifiLogProto.wifiLinkLayerUsageStats = mWifiLinkLayerUsageStats;
4122 
4123             /**
4124              * Convert the SparseIntArray of "Connect to Network" notification types and counts to
4125              * proto's repeated IntKeyVal array.
4126              */
4127             ConnectToNetworkNotificationAndActionCount[] notificationCountArray =
4128                     new ConnectToNetworkNotificationAndActionCount[
4129                             mConnectToNetworkNotificationCount.size()];
4130             for (int i = 0; i < mConnectToNetworkNotificationCount.size(); i++) {
4131                 ConnectToNetworkNotificationAndActionCount keyVal =
4132                         new ConnectToNetworkNotificationAndActionCount();
4133                 keyVal.notification = mConnectToNetworkNotificationCount.keyAt(i);
4134                 keyVal.recommender =
4135                         ConnectToNetworkNotificationAndActionCount.RECOMMENDER_OPEN;
4136                 keyVal.count = mConnectToNetworkNotificationCount.valueAt(i);
4137                 notificationCountArray[i] = keyVal;
4138             }
4139             mWifiLogProto.connectToNetworkNotificationCount = notificationCountArray;
4140 
4141             /**
4142              * Convert the SparseIntArray of "Connect to Network" notification types and counts to
4143              * proto's repeated IntKeyVal array.
4144              */
4145             ConnectToNetworkNotificationAndActionCount[] notificationActionCountArray =
4146                     new ConnectToNetworkNotificationAndActionCount[
4147                             mConnectToNetworkNotificationActionCount.size()];
4148             for (int i = 0; i < mConnectToNetworkNotificationActionCount.size(); i++) {
4149                 ConnectToNetworkNotificationAndActionCount keyVal =
4150                         new ConnectToNetworkNotificationAndActionCount();
4151                 int k = mConnectToNetworkNotificationActionCount.keyAt(i);
4152                 keyVal.notification =  k / CONNECT_TO_NETWORK_NOTIFICATION_ACTION_KEY_MULTIPLIER;
4153                 keyVal.action = k % CONNECT_TO_NETWORK_NOTIFICATION_ACTION_KEY_MULTIPLIER;
4154                 keyVal.recommender =
4155                         ConnectToNetworkNotificationAndActionCount.RECOMMENDER_OPEN;
4156                 keyVal.count = mConnectToNetworkNotificationActionCount.valueAt(i);
4157                 notificationActionCountArray[i] = keyVal;
4158             }
4159 
4160             mWifiLogProto.installedPasspointProfileTypeForR1 =
4161                     convertPasspointProfilesToProto(mInstalledPasspointProfileTypeForR1);
4162             mWifiLogProto.installedPasspointProfileTypeForR2 =
4163                     convertPasspointProfilesToProto(mInstalledPasspointProfileTypeForR2);
4164 
4165             mWifiLogProto.connectToNetworkNotificationActionCount = notificationActionCountArray;
4166 
4167             mWifiLogProto.openNetworkRecommenderBlacklistSize =
4168                     mOpenNetworkRecommenderBlacklistSize;
4169             mWifiLogProto.isWifiNetworksAvailableNotificationOn =
4170                     mIsWifiNetworksAvailableNotificationOn;
4171             mWifiLogProto.numOpenNetworkRecommendationUpdates =
4172                     mNumOpenNetworkRecommendationUpdates;
4173             mWifiLogProto.numOpenNetworkConnectMessageFailedToSend =
4174                     mNumOpenNetworkConnectMessageFailedToSend;
4175 
4176             mWifiLogProto.observedHotspotR1ApsInScanHistogram =
4177                     makeNumConnectableNetworksBucketArray(mObservedHotspotR1ApInScanHistogram);
4178             mWifiLogProto.observedHotspotR2ApsInScanHistogram =
4179                     makeNumConnectableNetworksBucketArray(mObservedHotspotR2ApInScanHistogram);
4180             mWifiLogProto.observedHotspotR3ApsInScanHistogram =
4181                 makeNumConnectableNetworksBucketArray(mObservedHotspotR3ApInScanHistogram);
4182             mWifiLogProto.observedHotspotR1EssInScanHistogram =
4183                     makeNumConnectableNetworksBucketArray(mObservedHotspotR1EssInScanHistogram);
4184             mWifiLogProto.observedHotspotR2EssInScanHistogram =
4185                     makeNumConnectableNetworksBucketArray(mObservedHotspotR2EssInScanHistogram);
4186             mWifiLogProto.observedHotspotR3EssInScanHistogram =
4187                     makeNumConnectableNetworksBucketArray(mObservedHotspotR3EssInScanHistogram);
4188             mWifiLogProto.observedHotspotR1ApsPerEssInScanHistogram =
4189                     makeNumConnectableNetworksBucketArray(
4190                             mObservedHotspotR1ApsPerEssInScanHistogram);
4191             mWifiLogProto.observedHotspotR2ApsPerEssInScanHistogram =
4192                     makeNumConnectableNetworksBucketArray(
4193                             mObservedHotspotR2ApsPerEssInScanHistogram);
4194             mWifiLogProto.observedHotspotR3ApsPerEssInScanHistogram =
4195                 makeNumConnectableNetworksBucketArray(
4196                     mObservedHotspotR3ApsPerEssInScanHistogram);
4197 
4198             mWifiLogProto.observed80211McSupportingApsInScanHistogram =
4199                     makeNumConnectableNetworksBucketArray(mObserved80211mcApInScanHistogram);
4200 
4201             if (mSoftApEventListTethered.size() > 0) {
4202                 mWifiLogProto.softApConnectedClientsEventsTethered =
4203                         mSoftApEventListTethered.toArray(
4204                         mWifiLogProto.softApConnectedClientsEventsTethered);
4205             }
4206             if (mSoftApEventListLocalOnly.size() > 0) {
4207                 mWifiLogProto.softApConnectedClientsEventsLocalOnly =
4208                         mSoftApEventListLocalOnly.toArray(
4209                         mWifiLogProto.softApConnectedClientsEventsLocalOnly);
4210             }
4211 
4212             mWifiLogProto.wifiPowerStats = mWifiPowerMetrics.buildProto();
4213             mWifiLogProto.wifiRadioUsage = mWifiPowerMetrics.buildWifiRadioUsageProto();
4214             mWifiLogProto.wifiWakeStats = mWifiWakeMetrics.buildProto();
4215             mWifiLogProto.isMacRandomizationOn = mContext.getResources().getBoolean(
4216                     R.bool.config_wifi_connected_mac_randomization_supported);
4217             mExperimentValues.wifiIsUnusableLoggingEnabled = mContext.getResources().getBoolean(
4218                     R.bool.config_wifiIsUnusableEventMetricsEnabled);
4219             mExperimentValues.linkSpeedCountsLoggingEnabled = mContext.getResources().getBoolean(
4220                     R.bool.config_wifiLinkSpeedMetricsEnabled);
4221             mExperimentValues.wifiDataStallMinTxBad = mContext.getResources().getInteger(
4222                     R.integer.config_wifiDataStallMinTxBad);
4223             mExperimentValues.wifiDataStallMinTxSuccessWithoutRx =
4224                     mContext.getResources().getInteger(
4225                             R.integer.config_wifiDataStallMinTxSuccessWithoutRx);
4226             mWifiLogProto.experimentValues = mExperimentValues;
4227             mWifiLogProto.wifiIsUnusableEventList =
4228                     new WifiIsUnusableEvent[mWifiIsUnusableList.size()];
4229             for (int i = 0; i < mWifiIsUnusableList.size(); i++) {
4230                 mWifiLogProto.wifiIsUnusableEventList[i] = mWifiIsUnusableList.get(i).event;
4231             }
4232             mWifiLogProto.hardwareRevision = SystemProperties.get("ro.boot.revision", "");
4233 
4234             // Postprocessing on WifiUsabilityStats to upload an equal number of LABEL_GOOD and
4235             // LABEL_BAD WifiUsabilityStats
4236             final int numUsabilityStats = Math.min(
4237                     Math.min(mWifiUsabilityStatsListBad.size(),
4238                             mWifiUsabilityStatsListGood.size()),
4239                     MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD);
4240             LinkedList<WifiUsabilityStats> usabilityStatsGoodCopy =
4241                     new LinkedList<>(mWifiUsabilityStatsListGood);
4242             LinkedList<WifiUsabilityStats> usabilityStatsBadCopy =
4243                     new LinkedList<>(mWifiUsabilityStatsListBad);
4244             mWifiLogProto.wifiUsabilityStatsList = new WifiUsabilityStats[numUsabilityStats * 2];
4245             for (int i = 0; i < numUsabilityStats; i++) {
4246                 mWifiLogProto.wifiUsabilityStatsList[2 * i] = usabilityStatsGoodCopy.remove(
4247                         mRand.nextInt(usabilityStatsGoodCopy.size()));
4248                 mWifiLogProto.wifiUsabilityStatsList[2 * i + 1] = usabilityStatsBadCopy.remove(
4249                         mRand.nextInt(usabilityStatsBadCopy.size()));
4250             }
4251             mWifiLogProto.mobilityStatePnoStatsList =
4252                     new DeviceMobilityStatePnoScanStats[mMobilityStatePnoStatsMap.size()];
4253             for (int i = 0; i < mMobilityStatePnoStatsMap.size(); i++) {
4254                 mWifiLogProto.mobilityStatePnoStatsList[i] = mMobilityStatePnoStatsMap.valueAt(i);
4255             }
4256             mWifiLogProto.wifiP2PStats = mWifiP2pMetrics.consolidateProto();
4257             mWifiLogProto.wifiDppLog = mDppMetrics.consolidateProto();
4258             mWifiLogProto.wifiConfigStoreIo = new WifiMetricsProto.WifiConfigStoreIO();
4259             mWifiLogProto.wifiConfigStoreIo.readDurations =
4260                     makeWifiConfigStoreIODurationBucketArray(mWifiConfigStoreReadDurationHistogram);
4261             mWifiLogProto.wifiConfigStoreIo.writeDurations =
4262                     makeWifiConfigStoreIODurationBucketArray(
4263                             mWifiConfigStoreWriteDurationHistogram);
4264 
4265             LinkProbeStats linkProbeStats = new LinkProbeStats();
4266             linkProbeStats.successRssiCounts = mLinkProbeSuccessRssiCounts.toProto();
4267             linkProbeStats.failureRssiCounts = mLinkProbeFailureRssiCounts.toProto();
4268             linkProbeStats.successLinkSpeedCounts = mLinkProbeSuccessLinkSpeedCounts.toProto();
4269             linkProbeStats.failureLinkSpeedCounts = mLinkProbeFailureLinkSpeedCounts.toProto();
4270             linkProbeStats.successSecondsSinceLastTxSuccessHistogram =
4271                     mLinkProbeSuccessSecondsSinceLastTxSuccessHistogram.toProto();
4272             linkProbeStats.failureSecondsSinceLastTxSuccessHistogram =
4273                     mLinkProbeFailureSecondsSinceLastTxSuccessHistogram.toProto();
4274             linkProbeStats.successElapsedTimeMsHistogram =
4275                     mLinkProbeSuccessElapsedTimeMsHistogram.toProto();
4276             linkProbeStats.failureReasonCounts = mLinkProbeFailureReasonCounts.toProto(
4277                     LinkProbeFailureReasonCount.class,
4278                     (reason, count) -> {
4279                         LinkProbeFailureReasonCount c = new LinkProbeFailureReasonCount();
4280                         c.failureReason = linkProbeFailureReasonToProto(reason);
4281                         c.count = count;
4282                         return c;
4283                     });
4284             linkProbeStats.experimentProbeCounts = mLinkProbeExperimentProbeCounts.toProto(
4285                     ExperimentProbeCounts.class,
4286                     (experimentId, probeCount) -> {
4287                         ExperimentProbeCounts c = new ExperimentProbeCounts();
4288                         c.experimentId = experimentId;
4289                         c.probeCount = probeCount;
4290                         return c;
4291                     });
4292             mWifiLogProto.linkProbeStats = linkProbeStats;
4293 
4294             mWifiLogProto.networkSelectionExperimentDecisionsList =
4295                     makeNetworkSelectionExperimentDecisionsList();
4296 
4297             mWifiNetworkRequestApiLog.networkMatchSizeHistogram =
4298                     mWifiNetworkRequestApiMatchSizeHistogram.toProto();
4299             mWifiLogProto.wifiNetworkRequestApiLog = mWifiNetworkRequestApiLog;
4300 
4301             mWifiNetworkSuggestionApiLog.networkListSizeHistogram =
4302                     mWifiNetworkSuggestionApiListSizeHistogram.toProto();
4303             mWifiNetworkSuggestionApiLog.appCountPerType =
4304                     mWifiNetworkSuggestionApiAppTypeCounter.toProto(SuggestionAppCount.class,
4305                             (key, count) -> {
4306                                 SuggestionAppCount entry = new SuggestionAppCount();
4307                                 entry.appType = key;
4308                                 entry.count = count;
4309                                 return entry;
4310                             });
4311             mWifiLogProto.wifiNetworkSuggestionApiLog = mWifiNetworkSuggestionApiLog;
4312 
4313             UserReactionToApprovalUiEvent events = new UserReactionToApprovalUiEvent();
4314             events.userApprovalAppUiReaction = mUserApprovalSuggestionAppUiReactionList
4315                     .toArray(new UserReaction[0]);
4316             events.userApprovalCarrierUiReaction = mUserApprovalCarrierUiReactionList
4317                     .toArray(new UserReaction[0]);
4318             mWifiLogProto.userReactionToApprovalUiEvent = events;
4319 
4320             mWifiLockStats.highPerfLockAcqDurationSecHistogram =
4321                     mWifiLockHighPerfAcqDurationSecHistogram.toProto();
4322 
4323             mWifiLockStats.lowLatencyLockAcqDurationSecHistogram =
4324                     mWifiLockLowLatencyAcqDurationSecHistogram.toProto();
4325 
4326             mWifiLockStats.highPerfActiveSessionDurationSecHistogram =
4327                     mWifiLockHighPerfActiveSessionDurationSecHistogram.toProto();
4328 
4329             mWifiLockStats.lowLatencyActiveSessionDurationSecHistogram =
4330                     mWifiLockLowLatencyActiveSessionDurationSecHistogram.toProto();
4331 
4332             mWifiLogProto.wifiLockStats = mWifiLockStats;
4333             mWifiLogProto.wifiToggleStats = mWifiToggleStats;
4334 
4335             /**
4336              * Convert the SparseIntArray of passpoint provision failure code
4337              * and counts to the proto's repeated IntKeyVal array.
4338              */
4339             mWifiLogProto.passpointProvisionStats = new PasspointProvisionStats();
4340             mWifiLogProto.passpointProvisionStats.numProvisionSuccess = mNumProvisionSuccess;
4341             mWifiLogProto.passpointProvisionStats.provisionFailureCount =
4342                     mPasspointProvisionFailureCounts.toProto(ProvisionFailureCount.class,
4343                             (key, count) -> {
4344                                 ProvisionFailureCount entry = new ProvisionFailureCount();
4345                                 entry.failureCode = key;
4346                                 entry.count = count;
4347                                 return entry;
4348                             });
4349             // 'G' is due to that 1st Letter after _ becomes capital during protobuff compilation
4350             mWifiLogProto.txLinkSpeedCount2G = mTxLinkSpeedCount2g.toProto();
4351             mWifiLogProto.txLinkSpeedCount5GLow = mTxLinkSpeedCount5gLow.toProto();
4352             mWifiLogProto.txLinkSpeedCount5GMid = mTxLinkSpeedCount5gMid.toProto();
4353             mWifiLogProto.txLinkSpeedCount5GHigh = mTxLinkSpeedCount5gHigh.toProto();
4354             mWifiLogProto.txLinkSpeedCount6GLow = mTxLinkSpeedCount6gLow.toProto();
4355             mWifiLogProto.txLinkSpeedCount6GMid = mTxLinkSpeedCount6gMid.toProto();
4356             mWifiLogProto.txLinkSpeedCount6GHigh = mTxLinkSpeedCount6gHigh.toProto();
4357 
4358             mWifiLogProto.rxLinkSpeedCount2G = mRxLinkSpeedCount2g.toProto();
4359             mWifiLogProto.rxLinkSpeedCount5GLow = mRxLinkSpeedCount5gLow.toProto();
4360             mWifiLogProto.rxLinkSpeedCount5GMid = mRxLinkSpeedCount5gMid.toProto();
4361             mWifiLogProto.rxLinkSpeedCount5GHigh = mRxLinkSpeedCount5gHigh.toProto();
4362             mWifiLogProto.rxLinkSpeedCount6GLow = mRxLinkSpeedCount6gLow.toProto();
4363             mWifiLogProto.rxLinkSpeedCount6GMid = mRxLinkSpeedCount6gMid.toProto();
4364             mWifiLogProto.rxLinkSpeedCount6GHigh = mRxLinkSpeedCount6gHigh.toProto();
4365 
4366             HealthMonitorMetrics healthMonitorMetrics = mWifiHealthMonitor.buildProto();
4367             if (healthMonitorMetrics != null) {
4368                 mWifiLogProto.healthMonitorMetrics = healthMonitorMetrics;
4369             }
4370             mWifiLogProto.bssidBlocklistStats = mBssidBlocklistStats.toProto();
4371             mWifiLogProto.connectionDurationStats = mConnectionDurationStats.toProto();
4372             mWifiLogProto.wifiOffMetrics = mWifiOffMetrics.toProto();
4373             mWifiLogProto.softApConfigLimitationMetrics = mSoftApConfigLimitationMetrics.toProto();
4374             mWifiLogProto.channelUtilizationHistogram =
4375                     new WifiMetricsProto.ChannelUtilizationHistogram();
4376             mWifiLogProto.channelUtilizationHistogram.utilization2G =
4377                     mChannelUtilizationHistogram2G.toProto();
4378             mWifiLogProto.channelUtilizationHistogram.utilizationAbove2G =
4379                     mChannelUtilizationHistogramAbove2G.toProto();
4380             mWifiLogProto.throughputMbpsHistogram =
4381                     new WifiMetricsProto.ThroughputMbpsHistogram();
4382             mWifiLogProto.throughputMbpsHistogram.tx2G =
4383                     mTxThroughputMbpsHistogram2G.toProto();
4384             mWifiLogProto.throughputMbpsHistogram.txAbove2G =
4385                     mTxThroughputMbpsHistogramAbove2G.toProto();
4386             mWifiLogProto.throughputMbpsHistogram.rx2G =
4387                     mRxThroughputMbpsHistogram2G.toProto();
4388             mWifiLogProto.throughputMbpsHistogram.rxAbove2G =
4389                     mRxThroughputMbpsHistogramAbove2G.toProto();
4390             mWifiLogProto.meteredNetworkStatsSaved = mMeteredNetworkStatsBuilder.toProto(false);
4391             mWifiLogProto.meteredNetworkStatsSuggestion = mMeteredNetworkStatsBuilder.toProto(true);
4392 
4393             InitPartialScanStats initialPartialScanStats = new InitPartialScanStats();
4394             initialPartialScanStats.numScans = mInitPartialScanTotalCount;
4395             initialPartialScanStats.numSuccessScans = mInitPartialScanSuccessCount;
4396             initialPartialScanStats.numFailureScans = mInitPartialScanFailureCount;
4397             initialPartialScanStats.successfulScanChannelCountHistogram =
4398                     mInitPartialScanSuccessHistogram.toProto();
4399             initialPartialScanStats.failedScanChannelCountHistogram =
4400                     mInitPartialScanFailureHistogram.toProto();
4401             mWifiLogProto.initPartialScanStats = initialPartialScanStats;
4402             mWifiLogProto.carrierWifiMetrics = mCarrierWifiMetrics.toProto();
4403             mWifiLogProto.mainlineModuleVersion = mWifiHealthMonitor.getWifiStackVersion();
4404 
4405         }
4406     }
4407 
linkProbeFailureReasonToProto(int reason)4408     private static int linkProbeFailureReasonToProto(int reason) {
4409         switch (reason) {
4410             case WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED:
4411                 return LinkProbeStats.LINK_PROBE_FAILURE_REASON_MCS_UNSUPPORTED;
4412             case WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_NO_ACK:
4413                 return LinkProbeStats.LINK_PROBE_FAILURE_REASON_NO_ACK;
4414             case WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_TIMEOUT:
4415                 return LinkProbeStats.LINK_PROBE_FAILURE_REASON_TIMEOUT;
4416             case WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_ALREADY_STARTED:
4417                 return LinkProbeStats.LINK_PROBE_FAILURE_REASON_ALREADY_STARTED;
4418             default:
4419                 return LinkProbeStats.LINK_PROBE_FAILURE_REASON_UNKNOWN;
4420         }
4421     }
4422 
makeNetworkSelectionExperimentDecisionsList()4423     private NetworkSelectionExperimentDecisions[] makeNetworkSelectionExperimentDecisionsList() {
4424         NetworkSelectionExperimentDecisions[] results = new NetworkSelectionExperimentDecisions[
4425                 mNetworkSelectionExperimentPairNumChoicesCounts.size()];
4426         int i = 0;
4427         for (Map.Entry<Pair<Integer, Integer>, NetworkSelectionExperimentResults> entry :
4428                 mNetworkSelectionExperimentPairNumChoicesCounts.entrySet()) {
4429             NetworkSelectionExperimentDecisions result = new NetworkSelectionExperimentDecisions();
4430             result.experiment1Id = entry.getKey().first;
4431             result.experiment2Id = entry.getKey().second;
4432             result.sameSelectionNumChoicesCounter =
4433                     entry.getValue().sameSelectionNumChoicesCounter.toProto();
4434             result.differentSelectionNumChoicesCounter =
4435                     entry.getValue().differentSelectionNumChoicesCounter.toProto();
4436             results[i] = result;
4437             i++;
4438         }
4439         return results;
4440     }
4441 
4442     /** Sets the scoring experiment id to current value */
consolidateScoringParams()4443     private void consolidateScoringParams() {
4444         synchronized (mLock) {
4445             if (mScoringParams != null) {
4446                 int experimentIdentifier = mScoringParams.getExperimentIdentifier();
4447                 if (experimentIdentifier == 0) {
4448                     mWifiLogProto.scoreExperimentId = "";
4449                 } else {
4450                     mWifiLogProto.scoreExperimentId = "x" + experimentIdentifier;
4451                 }
4452             }
4453         }
4454     }
4455 
makeNumConnectableNetworksBucketArray( SparseIntArray sia)4456     private WifiMetricsProto.NumConnectableNetworksBucket[] makeNumConnectableNetworksBucketArray(
4457             SparseIntArray sia) {
4458         WifiMetricsProto.NumConnectableNetworksBucket[] array =
4459                 new WifiMetricsProto.NumConnectableNetworksBucket[sia.size()];
4460         for (int i = 0; i < sia.size(); i++) {
4461             WifiMetricsProto.NumConnectableNetworksBucket keyVal =
4462                     new WifiMetricsProto.NumConnectableNetworksBucket();
4463             keyVal.numConnectableNetworks = sia.keyAt(i);
4464             keyVal.count = sia.valueAt(i);
4465             array[i] = keyVal;
4466         }
4467         return array;
4468     }
4469 
4470     private WifiMetricsProto.WifiConfigStoreIO.DurationBucket[]
makeWifiConfigStoreIODurationBucketArray(SparseIntArray sia)4471             makeWifiConfigStoreIODurationBucketArray(SparseIntArray sia) {
4472         MetricsUtils.GenericBucket[] genericBuckets =
4473                 MetricsUtils.linearHistogramToGenericBuckets(sia,
4474                         WIFI_CONFIG_STORE_IO_DURATION_BUCKET_RANGES_MS);
4475         WifiMetricsProto.WifiConfigStoreIO.DurationBucket[] array =
4476                 new WifiMetricsProto.WifiConfigStoreIO.DurationBucket[genericBuckets.length];
4477         try {
4478             for (int i = 0; i < genericBuckets.length; i++) {
4479                 array[i] = new WifiMetricsProto.WifiConfigStoreIO.DurationBucket();
4480                 array[i].rangeStartMs = toIntExact(genericBuckets[i].start);
4481                 array[i].rangeEndMs = toIntExact(genericBuckets[i].end);
4482                 array[i].count = genericBuckets[i].count;
4483             }
4484         } catch (ArithmeticException e) {
4485             // Return empty array on any overflow errors.
4486             array = new WifiMetricsProto.WifiConfigStoreIO.DurationBucket[0];
4487         }
4488         return array;
4489     }
4490 
4491     /**
4492      * Clear all WifiMetrics, except for currentConnectionEvent and Open Network Notification
4493      * feature enabled state, blacklist size.
4494      */
clear()4495     private void clear() {
4496         synchronized (mLock) {
4497             mConnectionEventList.clear();
4498             if (mCurrentConnectionEvent != null) {
4499                 mConnectionEventList.add(mCurrentConnectionEvent);
4500             }
4501             mScanReturnEntries.clear();
4502             mWifiSystemStateEntries.clear();
4503             mRecordStartTimeSec = mClock.getElapsedSinceBootMillis() / 1000;
4504             mRssiPollCountsMap.clear();
4505             mRssiDeltaCounts.clear();
4506             mLinkSpeedCounts.clear();
4507             mTxLinkSpeedCount2g.clear();
4508             mTxLinkSpeedCount5gLow.clear();
4509             mTxLinkSpeedCount5gMid.clear();
4510             mTxLinkSpeedCount5gHigh.clear();
4511             mTxLinkSpeedCount6gLow.clear();
4512             mTxLinkSpeedCount6gMid.clear();
4513             mTxLinkSpeedCount6gHigh.clear();
4514             mRxLinkSpeedCount2g.clear();
4515             mRxLinkSpeedCount5gLow.clear();
4516             mRxLinkSpeedCount5gMid.clear();
4517             mRxLinkSpeedCount5gHigh.clear();
4518             mRxLinkSpeedCount6gLow.clear();
4519             mRxLinkSpeedCount6gMid.clear();
4520             mRxLinkSpeedCount6gHigh.clear();
4521             mWifiAlertReasonCounts.clear();
4522             mWifiScoreCounts.clear();
4523             mWifiUsabilityScoreCounts.clear();
4524             mWifiLogProto.clear();
4525             mScanResultRssiTimestampMillis = -1;
4526             mSoftApManagerReturnCodeCounts.clear();
4527             mStaEventList.clear();
4528             mUserActionEventList.clear();
4529             mWifiAwareMetrics.clear();
4530             mRttMetrics.clear();
4531             mTotalSsidsInScanHistogram.clear();
4532             mTotalBssidsInScanHistogram.clear();
4533             mAvailableOpenSsidsInScanHistogram.clear();
4534             mAvailableOpenBssidsInScanHistogram.clear();
4535             mAvailableSavedSsidsInScanHistogram.clear();
4536             mAvailableSavedBssidsInScanHistogram.clear();
4537             mAvailableOpenOrSavedSsidsInScanHistogram.clear();
4538             mAvailableOpenOrSavedBssidsInScanHistogram.clear();
4539             mAvailableSavedPasspointProviderProfilesInScanHistogram.clear();
4540             mAvailableSavedPasspointProviderBssidsInScanHistogram.clear();
4541             mPnoScanMetrics.clear();
4542             mWifiLinkLayerUsageStats.clear();
4543             mConnectToNetworkNotificationCount.clear();
4544             mConnectToNetworkNotificationActionCount.clear();
4545             mNumOpenNetworkRecommendationUpdates = 0;
4546             mNumOpenNetworkConnectMessageFailedToSend = 0;
4547             mObservedHotspotR1ApInScanHistogram.clear();
4548             mObservedHotspotR2ApInScanHistogram.clear();
4549             mObservedHotspotR3ApInScanHistogram.clear();
4550             mObservedHotspotR1EssInScanHistogram.clear();
4551             mObservedHotspotR2EssInScanHistogram.clear();
4552             mObservedHotspotR3EssInScanHistogram.clear();
4553             mObservedHotspotR1ApsPerEssInScanHistogram.clear();
4554             mObservedHotspotR2ApsPerEssInScanHistogram.clear();
4555             mObservedHotspotR3ApsPerEssInScanHistogram.clear();
4556             mSoftApEventListTethered.clear();
4557             mSoftApEventListLocalOnly.clear();
4558             mWifiWakeMetrics.clear();
4559             mObserved80211mcApInScanHistogram.clear();
4560             mWifiIsUnusableList.clear();
4561             mInstalledPasspointProfileTypeForR1.clear();
4562             mInstalledPasspointProfileTypeForR2.clear();
4563             mWifiUsabilityStatsListGood.clear();
4564             mWifiUsabilityStatsListBad.clear();
4565             mWifiUsabilityStatsEntriesList.clear();
4566             mMobilityStatePnoStatsMap.clear();
4567             mWifiP2pMetrics.clear();
4568             mDppMetrics.clear();
4569             mWifiUsabilityStatsCounter = 0;
4570             mLastBssid = null;
4571             mLastFrequency = -1;
4572             mSeqNumInsideFramework = 0;
4573             mLastWifiUsabilityScore = -1;
4574             mLastWifiUsabilityScoreNoReset = -1;
4575             mLastPredictionHorizonSec = -1;
4576             mLastPredictionHorizonSecNoReset = -1;
4577             mSeqNumToFramework = -1;
4578             mProbeStatusSinceLastUpdate =
4579                     android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE;
4580             mProbeElapsedTimeSinceLastUpdateMs = -1;
4581             mProbeMcsRateSinceLastUpdate = -1;
4582             mScoreBreachLowTimeMillis = -1;
4583             mMeteredNetworkStatsBuilder.clear();
4584             mWifiConfigStoreReadDurationHistogram.clear();
4585             mWifiConfigStoreWriteDurationHistogram.clear();
4586             mLinkProbeSuccessRssiCounts.clear();
4587             mLinkProbeFailureRssiCounts.clear();
4588             mLinkProbeSuccessLinkSpeedCounts.clear();
4589             mLinkProbeFailureLinkSpeedCounts.clear();
4590             mLinkProbeSuccessSecondsSinceLastTxSuccessHistogram.clear();
4591             mLinkProbeFailureSecondsSinceLastTxSuccessHistogram.clear();
4592             mLinkProbeSuccessElapsedTimeMsHistogram.clear();
4593             mLinkProbeFailureReasonCounts.clear();
4594             mLinkProbeExperimentProbeCounts.clear();
4595             mLinkProbeStaEventCount = 0;
4596             mNetworkSelectionExperimentPairNumChoicesCounts.clear();
4597             mWifiNetworkSuggestionApiLog.clear();
4598             mWifiNetworkRequestApiMatchSizeHistogram.clear();
4599             mWifiNetworkSuggestionApiListSizeHistogram.clear();
4600             mWifiNetworkSuggestionApiAppTypeCounter.clear();
4601             mUserApprovalSuggestionAppUiReactionList.clear();
4602             mUserApprovalCarrierUiReactionList.clear();
4603             mWifiLockHighPerfAcqDurationSecHistogram.clear();
4604             mWifiLockLowLatencyAcqDurationSecHistogram.clear();
4605             mWifiLockHighPerfActiveSessionDurationSecHistogram.clear();
4606             mWifiLockLowLatencyActiveSessionDurationSecHistogram.clear();
4607             mWifiLockStats.clear();
4608             mWifiToggleStats.clear();
4609             mChannelUtilizationHistogram2G.clear();
4610             mChannelUtilizationHistogramAbove2G.clear();
4611             mTxThroughputMbpsHistogram2G.clear();
4612             mRxThroughputMbpsHistogram2G.clear();
4613             mTxThroughputMbpsHistogramAbove2G.clear();
4614             mRxThroughputMbpsHistogramAbove2G.clear();
4615             mPasspointProvisionFailureCounts.clear();
4616             mNumProvisionSuccess = 0;
4617             mBssidBlocklistStats = new BssidBlocklistStats();
4618             mConnectionDurationStats.clear();
4619             mWifiLogProto.isExternalWifiScorerOn = false;
4620             mWifiOffMetrics.clear();
4621             mSoftApConfigLimitationMetrics.clear();
4622             //Initial partial scan metrics
4623             mInitPartialScanTotalCount = 0;
4624             mInitPartialScanSuccessCount = 0;
4625             mInitPartialScanFailureCount = 0;
4626             mInitPartialScanSuccessHistogram.clear();
4627             mInitPartialScanFailureHistogram.clear();
4628             mCarrierWifiMetrics.clear();
4629         }
4630     }
4631 
4632     /**
4633      *  Set screen state (On/Off)
4634      */
setScreenState(boolean screenOn)4635     public void setScreenState(boolean screenOn) {
4636         synchronized (mLock) {
4637             mScreenOn = screenOn;
4638         }
4639     }
4640 
4641     /**
4642      *  Set wifi state (WIFI_UNKNOWN, WIFI_DISABLED, WIFI_DISCONNECTED, WIFI_ASSOCIATED)
4643      */
setWifiState(int wifiState)4644     public void setWifiState(int wifiState) {
4645         synchronized (mLock) {
4646             mWifiState = wifiState;
4647             mWifiWins = (wifiState == WifiMetricsProto.WifiLog.WIFI_ASSOCIATED);
4648             mWifiWinsUsabilityScore = (wifiState == WifiMetricsProto.WifiLog.WIFI_ASSOCIATED);
4649         }
4650     }
4651 
4652     /**
4653      * Message handler for interesting WifiMonitor messages. Generates StaEvents
4654      */
processMessage(Message msg)4655     private void processMessage(Message msg) {
4656         StaEvent event = new StaEvent();
4657         boolean logEvent = true;
4658         switch (msg.what) {
4659             case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
4660                 event.type = StaEvent.TYPE_ASSOCIATION_REJECTION_EVENT;
4661                 event.associationTimedOut = msg.arg1 > 0 ? true : false;
4662                 event.status = msg.arg2;
4663                 break;
4664             case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
4665                 event.type = StaEvent.TYPE_AUTHENTICATION_FAILURE_EVENT;
4666                 switch (msg.arg1) {
4667                     case WifiManager.ERROR_AUTH_FAILURE_NONE:
4668                         event.authFailureReason = StaEvent.AUTH_FAILURE_NONE;
4669                         break;
4670                     case WifiManager.ERROR_AUTH_FAILURE_TIMEOUT:
4671                         event.authFailureReason = StaEvent.AUTH_FAILURE_TIMEOUT;
4672                         break;
4673                     case WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD:
4674                         event.authFailureReason = StaEvent.AUTH_FAILURE_WRONG_PSWD;
4675                         break;
4676                     case WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE:
4677                         event.authFailureReason = StaEvent.AUTH_FAILURE_EAP_FAILURE;
4678                         break;
4679                     default:
4680                         break;
4681                 }
4682                 break;
4683             case WifiMonitor.NETWORK_CONNECTION_EVENT:
4684                 event.type = StaEvent.TYPE_NETWORK_CONNECTION_EVENT;
4685                 break;
4686             case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
4687                 event.type = StaEvent.TYPE_NETWORK_DISCONNECTION_EVENT;
4688                 event.reason = msg.arg2;
4689                 event.localGen = msg.arg1 == 0 ? false : true;
4690                 break;
4691             case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
4692                 logEvent = false;
4693                 StateChangeResult stateChangeResult = (StateChangeResult) msg.obj;
4694                 mSupplicantStateChangeBitmask |= supplicantStateToBit(stateChangeResult.state);
4695                 break;
4696             case WifiMonitor.ASSOCIATED_BSSID_EVENT:
4697                 event.type = StaEvent.TYPE_CMD_ASSOCIATED_BSSID;
4698                 break;
4699             case WifiMonitor.TARGET_BSSID_EVENT:
4700                 event.type = StaEvent.TYPE_CMD_TARGET_BSSID;
4701                 break;
4702             default:
4703                 return;
4704         }
4705         if (logEvent) {
4706             addStaEvent(event);
4707         }
4708     }
4709     /**
4710      * Log a StaEvent from ClientModeImpl. The StaEvent must not be one of the supplicant
4711      * generated event types, which are logged through 'sendMessage'
4712      * @param type StaEvent.EventType describing the event
4713      */
logStaEvent(int type)4714     public void logStaEvent(int type) {
4715         logStaEvent(type, StaEvent.DISCONNECT_UNKNOWN, null);
4716     }
4717     /**
4718      * Log a StaEvent from ClientModeImpl. The StaEvent must not be one of the supplicant
4719      * generated event types, which are logged through 'sendMessage'
4720      * @param type StaEvent.EventType describing the event
4721      * @param config WifiConfiguration for a framework initiated connection attempt
4722      */
logStaEvent(int type, WifiConfiguration config)4723     public void logStaEvent(int type, WifiConfiguration config) {
4724         logStaEvent(type, StaEvent.DISCONNECT_UNKNOWN, config);
4725     }
4726     /**
4727      * Log a StaEvent from ClientModeImpl. The StaEvent must not be one of the supplicant
4728      * generated event types, which are logged through 'sendMessage'
4729      * @param type StaEvent.EventType describing the event
4730      * @param frameworkDisconnectReason StaEvent.FrameworkDisconnectReason explaining why framework
4731      *                                  initiated a FRAMEWORK_DISCONNECT
4732      */
logStaEvent(int type, int frameworkDisconnectReason)4733     public void logStaEvent(int type, int frameworkDisconnectReason) {
4734         logStaEvent(type, frameworkDisconnectReason, null);
4735     }
4736     /**
4737      * Log a StaEvent from ClientModeImpl. The StaEvent must not be one of the supplicant
4738      * generated event types, which are logged through 'sendMessage'
4739      * @param type StaEvent.EventType describing the event
4740      * @param frameworkDisconnectReason StaEvent.FrameworkDisconnectReason explaining why framework
4741      *                                  initiated a FRAMEWORK_DISCONNECT
4742      * @param config WifiConfiguration for a framework initiated connection attempt
4743      */
logStaEvent(int type, int frameworkDisconnectReason, WifiConfiguration config)4744     public void logStaEvent(int type, int frameworkDisconnectReason, WifiConfiguration config) {
4745         switch (type) {
4746             case StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL:
4747             case StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST:
4748             case StaEvent.TYPE_CMD_IP_REACHABILITY_LOST:
4749             case StaEvent.TYPE_CMD_START_CONNECT:
4750             case StaEvent.TYPE_CMD_START_ROAM:
4751             case StaEvent.TYPE_CONNECT_NETWORK:
4752             case StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK:
4753             case StaEvent.TYPE_FRAMEWORK_DISCONNECT:
4754             case StaEvent.TYPE_SCORE_BREACH:
4755             case StaEvent.TYPE_MAC_CHANGE:
4756             case StaEvent.TYPE_WIFI_ENABLED:
4757             case StaEvent.TYPE_WIFI_DISABLED:
4758             case StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH:
4759                 break;
4760             default:
4761                 Log.e(TAG, "Unknown StaEvent:" + type);
4762                 return;
4763         }
4764         StaEvent event = new StaEvent();
4765         event.type = type;
4766         if (frameworkDisconnectReason != StaEvent.DISCONNECT_UNKNOWN) {
4767             event.frameworkDisconnectReason = frameworkDisconnectReason;
4768         }
4769         event.configInfo = createConfigInfo(config);
4770         addStaEvent(event);
4771     }
4772 
addStaEvent(StaEvent staEvent)4773     private void addStaEvent(StaEvent staEvent) {
4774         staEvent.startTimeMillis = mClock.getElapsedSinceBootMillis();
4775         staEvent.lastRssi = mLastPollRssi;
4776         staEvent.lastFreq = mLastPollFreq;
4777         staEvent.lastLinkSpeed = mLastPollLinkSpeed;
4778         staEvent.supplicantStateChangesBitmask = mSupplicantStateChangeBitmask;
4779         staEvent.lastScore = mLastScore;
4780         staEvent.lastWifiUsabilityScore = mLastWifiUsabilityScore;
4781         staEvent.lastPredictionHorizonSec = mLastPredictionHorizonSec;
4782         staEvent.mobileTxBytes = mFacade.getMobileTxBytes();
4783         staEvent.mobileRxBytes = mFacade.getMobileRxBytes();
4784         staEvent.totalTxBytes = mFacade.getTotalTxBytes();
4785         staEvent.totalRxBytes = mFacade.getTotalRxBytes();
4786         staEvent.screenOn = mScreenOn;
4787         if (mWifiDataStall != null) {
4788             staEvent.isCellularDataAvailable = mWifiDataStall.isCellularDataAvailable();
4789         }
4790         mSupplicantStateChangeBitmask = 0;
4791         mLastPollRssi = -127;
4792         mLastPollFreq = -1;
4793         mLastPollLinkSpeed = -1;
4794         mLastPollRxLinkSpeed = -1;
4795         mLastScore = -1;
4796         mLastWifiUsabilityScore = -1;
4797         mLastPredictionHorizonSec = -1;
4798         synchronized (mLock) {
4799             mStaEventList.add(new StaEventWithTime(staEvent, mClock.getWallClockMillis()));
4800             // Prune StaEventList if it gets too long
4801             if (mStaEventList.size() > MAX_STA_EVENTS) mStaEventList.remove();
4802         }
4803     }
4804 
createConfigInfo(WifiConfiguration config)4805     private ConfigInfo createConfigInfo(WifiConfiguration config) {
4806         if (config == null) return null;
4807         ConfigInfo info = new ConfigInfo();
4808         info.allowedKeyManagement = bitSetToInt(config.allowedKeyManagement);
4809         info.allowedProtocols = bitSetToInt(config.allowedProtocols);
4810         info.allowedAuthAlgorithms = bitSetToInt(config.allowedAuthAlgorithms);
4811         info.allowedPairwiseCiphers = bitSetToInt(config.allowedPairwiseCiphers);
4812         info.allowedGroupCiphers = bitSetToInt(config.allowedGroupCiphers);
4813         info.hiddenSsid = config.hiddenSSID;
4814         info.isPasspoint = config.isPasspoint();
4815         info.isEphemeral = config.isEphemeral();
4816         info.hasEverConnected = config.getNetworkSelectionStatus().hasEverConnected();
4817         ScanResult candidate = config.getNetworkSelectionStatus().getCandidate();
4818         if (candidate != null) {
4819             info.scanRssi = candidate.level;
4820             info.scanFreq = candidate.frequency;
4821         }
4822         return info;
4823     }
4824 
getHandler()4825     public Handler getHandler() {
4826         return mHandler;
4827     }
4828 
getWifiAwareMetrics()4829     public WifiAwareMetrics getWifiAwareMetrics() {
4830         return mWifiAwareMetrics;
4831     }
4832 
getWakeupMetrics()4833     public WifiWakeMetrics getWakeupMetrics() {
4834         return mWifiWakeMetrics;
4835     }
4836 
getRttMetrics()4837     public RttMetrics getRttMetrics() {
4838         return mRttMetrics;
4839     }
4840 
4841     // Rather than generate a StaEvent for each SUPPLICANT_STATE_CHANGE, cache these in a bitmask
4842     // and attach it to the next event which is generated.
4843     private int mSupplicantStateChangeBitmask = 0;
4844 
4845     /**
4846      * Converts a SupplicantState value to a single bit, with position defined by
4847      * {@code StaEvent.SupplicantState}
4848      */
supplicantStateToBit(SupplicantState state)4849     public static int supplicantStateToBit(SupplicantState state) {
4850         switch(state) {
4851             case DISCONNECTED:
4852                 return 1 << StaEvent.STATE_DISCONNECTED;
4853             case INTERFACE_DISABLED:
4854                 return 1 << StaEvent.STATE_INTERFACE_DISABLED;
4855             case INACTIVE:
4856                 return 1 << StaEvent.STATE_INACTIVE;
4857             case SCANNING:
4858                 return 1 << StaEvent.STATE_SCANNING;
4859             case AUTHENTICATING:
4860                 return 1 << StaEvent.STATE_AUTHENTICATING;
4861             case ASSOCIATING:
4862                 return 1 << StaEvent.STATE_ASSOCIATING;
4863             case ASSOCIATED:
4864                 return 1 << StaEvent.STATE_ASSOCIATED;
4865             case FOUR_WAY_HANDSHAKE:
4866                 return 1 << StaEvent.STATE_FOUR_WAY_HANDSHAKE;
4867             case GROUP_HANDSHAKE:
4868                 return 1 << StaEvent.STATE_GROUP_HANDSHAKE;
4869             case COMPLETED:
4870                 return 1 << StaEvent.STATE_COMPLETED;
4871             case DORMANT:
4872                 return 1 << StaEvent.STATE_DORMANT;
4873             case UNINITIALIZED:
4874                 return 1 << StaEvent.STATE_UNINITIALIZED;
4875             case INVALID:
4876                 return 1 << StaEvent.STATE_INVALID;
4877             default:
4878                 Log.wtf(TAG, "Got unknown supplicant state: " + state.ordinal());
4879                 return 0;
4880         }
4881     }
4882 
supplicantStateChangesBitmaskToString(int mask)4883     private static String supplicantStateChangesBitmaskToString(int mask) {
4884         StringBuilder sb = new StringBuilder();
4885         sb.append("supplicantStateChangeEvents: {");
4886         if ((mask & (1 << StaEvent.STATE_DISCONNECTED)) > 0) sb.append(" DISCONNECTED");
4887         if ((mask & (1 << StaEvent.STATE_INTERFACE_DISABLED)) > 0) sb.append(" INTERFACE_DISABLED");
4888         if ((mask & (1 << StaEvent.STATE_INACTIVE)) > 0) sb.append(" INACTIVE");
4889         if ((mask & (1 << StaEvent.STATE_SCANNING)) > 0) sb.append(" SCANNING");
4890         if ((mask & (1 << StaEvent.STATE_AUTHENTICATING)) > 0) sb.append(" AUTHENTICATING");
4891         if ((mask & (1 << StaEvent.STATE_ASSOCIATING)) > 0) sb.append(" ASSOCIATING");
4892         if ((mask & (1 << StaEvent.STATE_ASSOCIATED)) > 0) sb.append(" ASSOCIATED");
4893         if ((mask & (1 << StaEvent.STATE_FOUR_WAY_HANDSHAKE)) > 0) sb.append(" FOUR_WAY_HANDSHAKE");
4894         if ((mask & (1 << StaEvent.STATE_GROUP_HANDSHAKE)) > 0) sb.append(" GROUP_HANDSHAKE");
4895         if ((mask & (1 << StaEvent.STATE_COMPLETED)) > 0) sb.append(" COMPLETED");
4896         if ((mask & (1 << StaEvent.STATE_DORMANT)) > 0) sb.append(" DORMANT");
4897         if ((mask & (1 << StaEvent.STATE_UNINITIALIZED)) > 0) sb.append(" UNINITIALIZED");
4898         if ((mask & (1 << StaEvent.STATE_INVALID)) > 0) sb.append(" INVALID");
4899         sb.append(" }");
4900         return sb.toString();
4901     }
4902 
4903     /**
4904      * Returns a human readable string from a Sta Event. Only adds information relevant to the event
4905      * type.
4906      */
staEventToString(StaEvent event)4907     public static String staEventToString(StaEvent event) {
4908         if (event == null) return "<NULL>";
4909         StringBuilder sb = new StringBuilder();
4910         switch (event.type) {
4911             case StaEvent.TYPE_ASSOCIATION_REJECTION_EVENT:
4912                 sb.append("ASSOCIATION_REJECTION_EVENT")
4913                         .append(" timedOut=").append(event.associationTimedOut)
4914                         .append(" status=").append(event.status).append(":")
4915                         .append(ISupplicantStaIfaceCallback.StatusCode.toString(event.status));
4916                 break;
4917             case StaEvent.TYPE_AUTHENTICATION_FAILURE_EVENT:
4918                 sb.append("AUTHENTICATION_FAILURE_EVENT reason=").append(event.authFailureReason)
4919                         .append(":").append(authFailureReasonToString(event.authFailureReason));
4920                 break;
4921             case StaEvent.TYPE_NETWORK_CONNECTION_EVENT:
4922                 sb.append("NETWORK_CONNECTION_EVENT");
4923                 break;
4924             case StaEvent.TYPE_NETWORK_DISCONNECTION_EVENT:
4925                 sb.append("NETWORK_DISCONNECTION_EVENT")
4926                         .append(" local_gen=").append(event.localGen)
4927                         .append(" reason=").append(event.reason).append(":")
4928                         .append(ISupplicantStaIfaceCallback.ReasonCode.toString(
4929                                 (event.reason >= 0 ? event.reason : -1 * event.reason)));
4930                 break;
4931             case StaEvent.TYPE_CMD_ASSOCIATED_BSSID:
4932                 sb.append("CMD_ASSOCIATED_BSSID");
4933                 break;
4934             case StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL:
4935                 sb.append("CMD_IP_CONFIGURATION_SUCCESSFUL");
4936                 break;
4937             case StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST:
4938                 sb.append("CMD_IP_CONFIGURATION_LOST");
4939                 break;
4940             case StaEvent.TYPE_CMD_IP_REACHABILITY_LOST:
4941                 sb.append("CMD_IP_REACHABILITY_LOST");
4942                 break;
4943             case StaEvent.TYPE_CMD_TARGET_BSSID:
4944                 sb.append("CMD_TARGET_BSSID");
4945                 break;
4946             case StaEvent.TYPE_CMD_START_CONNECT:
4947                 sb.append("CMD_START_CONNECT");
4948                 break;
4949             case StaEvent.TYPE_CMD_START_ROAM:
4950                 sb.append("CMD_START_ROAM");
4951                 break;
4952             case StaEvent.TYPE_CONNECT_NETWORK:
4953                 sb.append("CONNECT_NETWORK");
4954                 break;
4955             case StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK:
4956                 sb.append("NETWORK_AGENT_VALID_NETWORK");
4957                 break;
4958             case StaEvent.TYPE_FRAMEWORK_DISCONNECT:
4959                 sb.append("FRAMEWORK_DISCONNECT")
4960                         .append(" reason=")
4961                         .append(frameworkDisconnectReasonToString(event.frameworkDisconnectReason));
4962                 break;
4963             case StaEvent.TYPE_SCORE_BREACH:
4964                 sb.append("SCORE_BREACH");
4965                 break;
4966             case StaEvent.TYPE_MAC_CHANGE:
4967                 sb.append("MAC_CHANGE");
4968                 break;
4969             case StaEvent.TYPE_WIFI_ENABLED:
4970                 sb.append("WIFI_ENABLED");
4971                 break;
4972             case StaEvent.TYPE_WIFI_DISABLED:
4973                 sb.append("WIFI_DISABLED");
4974                 break;
4975             case StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH:
4976                 sb.append("WIFI_USABILITY_SCORE_BREACH");
4977                 break;
4978             case StaEvent.TYPE_LINK_PROBE:
4979                 sb.append("LINK_PROBE");
4980                 sb.append(" linkProbeWasSuccess=").append(event.linkProbeWasSuccess);
4981                 if (event.linkProbeWasSuccess) {
4982                     sb.append(" linkProbeSuccessElapsedTimeMs=")
4983                             .append(event.linkProbeSuccessElapsedTimeMs);
4984                 } else {
4985                     sb.append(" linkProbeFailureReason=").append(event.linkProbeFailureReason);
4986                 }
4987                 break;
4988             default:
4989                 sb.append("UNKNOWN " + event.type + ":");
4990                 break;
4991         }
4992         if (event.lastRssi != -127) sb.append(" lastRssi=").append(event.lastRssi);
4993         if (event.lastFreq != -1) sb.append(" lastFreq=").append(event.lastFreq);
4994         if (event.lastLinkSpeed != -1) sb.append(" lastLinkSpeed=").append(event.lastLinkSpeed);
4995         if (event.lastScore != -1) sb.append(" lastScore=").append(event.lastScore);
4996         if (event.lastWifiUsabilityScore != -1) {
4997             sb.append(" lastWifiUsabilityScore=").append(event.lastWifiUsabilityScore);
4998             sb.append(" lastPredictionHorizonSec=").append(event.lastPredictionHorizonSec);
4999         }
5000         if (event.mobileTxBytes > 0) sb.append(" mobileTxBytes=").append(event.mobileTxBytes);
5001         if (event.mobileRxBytes > 0) sb.append(" mobileRxBytes=").append(event.mobileRxBytes);
5002         if (event.totalTxBytes > 0) sb.append(" totalTxBytes=").append(event.totalTxBytes);
5003         if (event.totalRxBytes > 0) sb.append(" totalRxBytes=").append(event.totalRxBytes);
5004         sb.append(" screenOn=").append(event.screenOn);
5005         sb.append(" cellularData=").append(event.isCellularDataAvailable);
5006         if (event.supplicantStateChangesBitmask != 0) {
5007             sb.append(", ").append(supplicantStateChangesBitmaskToString(
5008                     event.supplicantStateChangesBitmask));
5009         }
5010         if (event.configInfo != null) {
5011             sb.append(", ").append(configInfoToString(event.configInfo));
5012         }
5013 
5014         return sb.toString();
5015     }
5016 
authFailureReasonToString(int authFailureReason)5017     private static String authFailureReasonToString(int authFailureReason) {
5018         switch (authFailureReason) {
5019             case StaEvent.AUTH_FAILURE_NONE:
5020                 return "ERROR_AUTH_FAILURE_NONE";
5021             case StaEvent.AUTH_FAILURE_TIMEOUT:
5022                 return "ERROR_AUTH_FAILURE_TIMEOUT";
5023             case StaEvent.AUTH_FAILURE_WRONG_PSWD:
5024                 return "ERROR_AUTH_FAILURE_WRONG_PSWD";
5025             case StaEvent.AUTH_FAILURE_EAP_FAILURE:
5026                 return "ERROR_AUTH_FAILURE_EAP_FAILURE";
5027             default:
5028                 return "";
5029         }
5030     }
5031 
frameworkDisconnectReasonToString(int frameworkDisconnectReason)5032     private static String frameworkDisconnectReasonToString(int frameworkDisconnectReason) {
5033         switch (frameworkDisconnectReason) {
5034             case StaEvent.DISCONNECT_API:
5035                 return "DISCONNECT_API";
5036             case StaEvent.DISCONNECT_GENERIC:
5037                 return "DISCONNECT_GENERIC";
5038             case StaEvent.DISCONNECT_UNWANTED:
5039                 return "DISCONNECT_UNWANTED";
5040             case StaEvent.DISCONNECT_ROAM_WATCHDOG_TIMER:
5041                 return "DISCONNECT_ROAM_WATCHDOG_TIMER";
5042             case StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST:
5043                 return "DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST";
5044             case StaEvent.DISCONNECT_RESET_SIM_NETWORKS:
5045                 return "DISCONNECT_RESET_SIM_NETWORKS";
5046             default:
5047                 return "DISCONNECT_UNKNOWN=" + frameworkDisconnectReason;
5048         }
5049     }
5050 
configInfoToString(ConfigInfo info)5051     private static String configInfoToString(ConfigInfo info) {
5052         StringBuilder sb = new StringBuilder();
5053         sb.append("ConfigInfo:")
5054                 .append(" allowed_key_management=").append(info.allowedKeyManagement)
5055                 .append(" allowed_protocols=").append(info.allowedProtocols)
5056                 .append(" allowed_auth_algorithms=").append(info.allowedAuthAlgorithms)
5057                 .append(" allowed_pairwise_ciphers=").append(info.allowedPairwiseCiphers)
5058                 .append(" allowed_group_ciphers=").append(info.allowedGroupCiphers)
5059                 .append(" hidden_ssid=").append(info.hiddenSsid)
5060                 .append(" is_passpoint=").append(info.isPasspoint)
5061                 .append(" is_ephemeral=").append(info.isEphemeral)
5062                 .append(" has_ever_connected=").append(info.hasEverConnected)
5063                 .append(" scan_rssi=").append(info.scanRssi)
5064                 .append(" scan_freq=").append(info.scanFreq);
5065         return sb.toString();
5066     }
5067 
5068     /**
5069      * Converts the first 31 bits of a BitSet to a little endian int
5070      */
bitSetToInt(BitSet bits)5071     private static int bitSetToInt(BitSet bits) {
5072         int value = 0;
5073         int nBits = bits.length() < 31 ? bits.length() : 31;
5074         for (int i = 0; i < nBits; i++) {
5075             value += bits.get(i) ? (1 << i) : 0;
5076         }
5077         return value;
5078     }
5079     private void incrementSsid(SparseIntArray sia, int element) {
5080         increment(sia, Math.min(element, MAX_CONNECTABLE_SSID_NETWORK_BUCKET));
5081     }
5082     private void incrementBssid(SparseIntArray sia, int element) {
5083         increment(sia, Math.min(element, MAX_CONNECTABLE_BSSID_NETWORK_BUCKET));
5084     }
5085     private void incrementTotalScanResults(SparseIntArray sia, int element) {
5086         increment(sia, Math.min(element, MAX_TOTAL_SCAN_RESULTS_BUCKET));
5087     }
5088     private void incrementTotalScanSsids(SparseIntArray sia, int element) {
5089         increment(sia, Math.min(element, MAX_TOTAL_SCAN_RESULT_SSIDS_BUCKET));
5090     }
5091     private void incrementTotalPasspointAps(SparseIntArray sia, int element) {
5092         increment(sia, Math.min(element, MAX_TOTAL_PASSPOINT_APS_BUCKET));
5093     }
5094     private void incrementTotalUniquePasspointEss(SparseIntArray sia, int element) {
5095         increment(sia, Math.min(element, MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET));
5096     }
5097     private void incrementPasspointPerUniqueEss(SparseIntArray sia, int element) {
5098         increment(sia, Math.min(element, MAX_PASSPOINT_APS_PER_UNIQUE_ESS_BUCKET));
5099     }
5100     private void increment80211mcAps(SparseIntArray sia, int element) {
5101         increment(sia, Math.min(element, MAX_TOTAL_80211MC_APS_BUCKET));
5102     }
5103     private void increment(SparseIntArray sia, int element) {
5104         int count = sia.get(element);
5105         sia.put(element, count + 1);
5106     }
5107 
5108     private static class StaEventWithTime {
5109         public StaEvent staEvent;
5110         public long wallClockMillis;
5111 
5112         StaEventWithTime(StaEvent event, long wallClockMillis) {
5113             staEvent = event;
5114             this.wallClockMillis = wallClockMillis;
5115         }
5116 
5117         public String toString() {
5118             StringBuilder sb = new StringBuilder();
5119             Calendar c = Calendar.getInstance();
5120             c.setTimeInMillis(wallClockMillis);
5121             if (wallClockMillis != 0) {
5122                 sb.append(String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c));
5123             } else {
5124                 sb.append("                  ");
5125             }
5126             sb.append(" ").append(staEventToString(staEvent));
5127             return sb.toString();
5128         }
5129     }
5130 
5131     private LinkedList<WifiIsUnusableWithTime> mWifiIsUnusableList =
5132             new LinkedList<WifiIsUnusableWithTime>();
5133     private long mTxScucessDelta = 0;
5134     private long mTxRetriesDelta = 0;
5135     private long mTxBadDelta = 0;
5136     private long mRxSuccessDelta = 0;
5137     private long mLlStatsUpdateTimeDelta = 0;
5138     private long mLlStatsLastUpdateTime = 0;
5139     private int mLastScoreNoReset = -1;
5140     private long mLastDataStallTime = Long.MIN_VALUE;
5141 
5142     private static class WifiIsUnusableWithTime {
5143         public WifiIsUnusableEvent event;
5144         public long wallClockMillis;
5145 
5146         WifiIsUnusableWithTime(WifiIsUnusableEvent event, long wallClockMillis) {
5147             this.event = event;
5148             this.wallClockMillis = wallClockMillis;
5149         }
5150 
5151         public String toString() {
5152             if (event == null) return "<NULL>";
5153             StringBuilder sb = new StringBuilder();
5154             if (wallClockMillis != 0) {
5155                 Calendar c = Calendar.getInstance();
5156                 c.setTimeInMillis(wallClockMillis);
5157                 sb.append(String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c));
5158             } else {
5159                 sb.append("                  ");
5160             }
5161             sb.append(" ");
5162 
5163             switch(event.type) {
5164                 case WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX:
5165                     sb.append("DATA_STALL_BAD_TX");
5166                     break;
5167                 case WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX:
5168                     sb.append("DATA_STALL_TX_WITHOUT_RX");
5169                     break;
5170                 case WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH:
5171                     sb.append("DATA_STALL_BOTH");
5172                     break;
5173                 case WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT:
5174                     sb.append("FIRMWARE_ALERT");
5175                     break;
5176                 case WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST:
5177                     sb.append("IP_REACHABILITY_LOST");
5178                     break;
5179                 default:
5180                     sb.append("UNKNOWN " + event.type);
5181                     break;
5182             }
5183 
5184             sb.append(" lastScore=").append(event.lastScore);
5185             sb.append(" txSuccessDelta=").append(event.txSuccessDelta);
5186             sb.append(" txRetriesDelta=").append(event.txRetriesDelta);
5187             sb.append(" txBadDelta=").append(event.txBadDelta);
5188             sb.append(" rxSuccessDelta=").append(event.rxSuccessDelta);
5189             sb.append(" packetUpdateTimeDelta=").append(event.packetUpdateTimeDelta)
5190                     .append("ms");
5191             if (event.firmwareAlertCode != -1) {
5192                 sb.append(" firmwareAlertCode=").append(event.firmwareAlertCode);
5193             }
5194             sb.append(" lastWifiUsabilityScore=").append(event.lastWifiUsabilityScore);
5195             sb.append(" lastPredictionHorizonSec=").append(event.lastPredictionHorizonSec);
5196             sb.append(" screenOn=").append(event.screenOn);
5197             sb.append(" mobileTxBytes=").append(event.mobileTxBytes);
5198             sb.append(" mobileRxBytes=").append(event.mobileRxBytes);
5199             sb.append(" totalTxBytes=").append(event.totalTxBytes);
5200             sb.append(" totalRxBytes=").append(event.totalRxBytes);
5201             return sb.toString();
5202         }
5203     }
5204 
5205     /**
5206      * Converts MeteredOverride enum to UserActionEvent type.
5207      * @param value
5208      */
5209     public static int convertMeteredOverrideEnumToUserActionEventType(@MeteredOverride int value) {
5210         int result = UserActionEvent.EVENT_UNKNOWN;
5211         switch(value) {
5212             case WifiConfiguration.METERED_OVERRIDE_NONE:
5213                 result = UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_AUTO;
5214                 break;
5215             case WifiConfiguration.METERED_OVERRIDE_METERED:
5216                 result = UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_METERED;
5217                 break;
5218             case WifiConfiguration.METERED_OVERRIDE_NOT_METERED:
5219                 result = UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_UNMETERED;
5220                 break;
5221         }
5222         return result;
5223     }
5224 
5225     static class MeteredNetworkStatsBuilder {
5226         // A map from network identifier to MeteredDetail
5227         Map<String, MeteredDetail> mNetworkMap = new ArrayMap<>();
5228 
5229         void put(WifiConfiguration config, boolean detectedAsMetered) {
5230             MeteredDetail meteredDetail = new MeteredDetail();
5231             boolean isMetered = detectedAsMetered;
5232             if (config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_METERED) {
5233                 isMetered = true;
5234             } else if (config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_NOT_METERED) {
5235                 isMetered = false;
5236             }
5237             meteredDetail.isMetered = isMetered;
5238             meteredDetail.isMeteredOverrideSet = config.meteredOverride
5239                     != WifiConfiguration.METERED_OVERRIDE_NONE;
5240             meteredDetail.isFromSuggestion = config.fromWifiNetworkSuggestion;
5241             mNetworkMap.put(config.getKey(), meteredDetail);
5242         }
5243 
5244         void clear() {
5245             mNetworkMap.clear();
5246         }
5247 
5248         MeteredNetworkStats toProto(boolean isFromSuggestion) {
5249             MeteredNetworkStats result = new MeteredNetworkStats();
5250             for (MeteredDetail meteredDetail : mNetworkMap.values()) {
5251                 if (meteredDetail.isFromSuggestion != isFromSuggestion) {
5252                     continue;
5253                 }
5254                 if (meteredDetail.isMetered) {
5255                     result.numMetered++;
5256                 } else {
5257                     result.numUnmetered++;
5258                 }
5259                 if (meteredDetail.isMeteredOverrideSet) {
5260                     if (meteredDetail.isMetered) {
5261                         result.numOverrideMetered++;
5262                     } else {
5263                         result.numOverrideUnmetered++;
5264                     }
5265                 }
5266             }
5267             return result;
5268         }
5269 
5270         static class MeteredDetail {
5271             public boolean isMetered;
5272             public boolean isMeteredOverrideSet;
5273             public boolean isFromSuggestion;
5274         }
5275     }
5276 
5277     /**
5278      * Add metered information of this network.
5279      * @param config WifiConfiguration representing the netework.
5280      * @param detectedAsMetered is the network detected as metered.
5281      */
5282     public void addMeteredStat(WifiConfiguration config, boolean detectedAsMetered) {
5283         synchronized (mLock) {
5284             if (config == null) {
5285                 return;
5286             }
5287             mMeteredNetworkStatsBuilder.put(config, detectedAsMetered);
5288         }
5289     }
5290     /**
5291      * Logs a UserActionEvent without a target network.
5292      * @param eventType the type of user action (one of WifiMetricsProto.UserActionEvent.EventType)
5293      */
5294     public void logUserActionEvent(int eventType) {
5295         logUserActionEvent(eventType, -1);
5296     }
5297 
5298     /**
5299      * Logs a UserActionEvent which has a target network.
5300      * @param eventType the type of user action (one of WifiMetricsProto.UserActionEvent.EventType)
5301      * @param networkId networkId of the target network.
5302      */
5303     public void logUserActionEvent(int eventType, int networkId) {
5304         synchronized (mLock) {
5305             mUserActionEventList.add(new UserActionEventWithTime(eventType, networkId));
5306             if (mUserActionEventList.size() > MAX_USER_ACTION_EVENTS) {
5307                 mUserActionEventList.remove();
5308             }
5309         }
5310     }
5311 
5312     /**
5313      * Logs a UserActionEvent, directly specifying the target network's properties.
5314      * @param eventType the type of user action (one of WifiMetricsProto.UserActionEvent.EventType)
5315      * @param isEphemeral true if the target network is ephemeral.
5316      * @param isPasspoint true if the target network is passpoint.
5317      */
5318     public void logUserActionEvent(int eventType, boolean isEphemeral, boolean isPasspoint) {
5319         synchronized (mLock) {
5320             TargetNetworkInfo networkInfo = new TargetNetworkInfo();
5321             networkInfo.isEphemeral = isEphemeral;
5322             networkInfo.isPasspoint = isPasspoint;
5323             mUserActionEventList.add(new UserActionEventWithTime(eventType, networkInfo));
5324             if (mUserActionEventList.size() > MAX_USER_ACTION_EVENTS) {
5325                 mUserActionEventList.remove();
5326             }
5327         }
5328     }
5329 
5330     /**
5331      * Update the difference between the last two WifiLinkLayerStats for WifiIsUnusableEvent
5332      */
5333     public void updateWifiIsUnusableLinkLayerStats(long txSuccessDelta, long txRetriesDelta,
5334             long txBadDelta, long rxSuccessDelta, long updateTimeDelta) {
5335         mTxScucessDelta = txSuccessDelta;
5336         mTxRetriesDelta = txRetriesDelta;
5337         mTxBadDelta = txBadDelta;
5338         mRxSuccessDelta = rxSuccessDelta;
5339         mLlStatsUpdateTimeDelta = updateTimeDelta;
5340         mLlStatsLastUpdateTime = mClock.getElapsedSinceBootMillis();
5341     }
5342 
5343     /**
5344      * Clear the saved difference between the last two WifiLinkLayerStats
5345      */
5346     public void resetWifiIsUnusableLinkLayerStats() {
5347         mTxScucessDelta = 0;
5348         mTxRetriesDelta = 0;
5349         mTxBadDelta = 0;
5350         mRxSuccessDelta = 0;
5351         mLlStatsUpdateTimeDelta = 0;
5352         mLlStatsLastUpdateTime = 0;
5353         mLastDataStallTime = Long.MIN_VALUE;
5354     }
5355 
5356     /**
5357      * Log a WifiIsUnusableEvent
5358      * @param triggerType WifiIsUnusableEvent.type describing the event
5359      */
5360     public void logWifiIsUnusableEvent(int triggerType) {
5361         logWifiIsUnusableEvent(triggerType, -1);
5362     }
5363 
5364     /**
5365      * Log a WifiIsUnusableEvent
5366      * @param triggerType WifiIsUnusableEvent.type describing the event
5367      * @param firmwareAlertCode WifiIsUnusableEvent.firmwareAlertCode for firmware alert code
5368      */
5369     public void logWifiIsUnusableEvent(int triggerType, int firmwareAlertCode) {
5370         mScoreBreachLowTimeMillis = -1;
5371         if (!mContext.getResources().getBoolean(R.bool.config_wifiIsUnusableEventMetricsEnabled)) {
5372             return;
5373         }
5374 
5375         long currentBootTime = mClock.getElapsedSinceBootMillis();
5376         switch (triggerType) {
5377             case WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX:
5378             case WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX:
5379             case WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH:
5380                 // Have a time-based throttle for generating WifiIsUnusableEvent from data stalls
5381                 if (currentBootTime < mLastDataStallTime + MIN_DATA_STALL_WAIT_MS) {
5382                     return;
5383                 }
5384                 mLastDataStallTime = currentBootTime;
5385                 break;
5386             case WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT:
5387                 break;
5388             case WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST:
5389                 break;
5390             default:
5391                 Log.e(TAG, "Unknown WifiIsUnusableEvent: " + triggerType);
5392                 return;
5393         }
5394 
5395         WifiIsUnusableEvent event = new WifiIsUnusableEvent();
5396         event.type = triggerType;
5397         if (triggerType == WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT) {
5398             event.firmwareAlertCode = firmwareAlertCode;
5399         }
5400         event.startTimeMillis = currentBootTime;
5401         event.lastScore = mLastScoreNoReset;
5402         event.lastWifiUsabilityScore = mLastWifiUsabilityScoreNoReset;
5403         event.lastPredictionHorizonSec = mLastPredictionHorizonSecNoReset;
5404         event.txSuccessDelta = mTxScucessDelta;
5405         event.txRetriesDelta = mTxRetriesDelta;
5406         event.txBadDelta = mTxBadDelta;
5407         event.rxSuccessDelta = mRxSuccessDelta;
5408         event.packetUpdateTimeDelta = mLlStatsUpdateTimeDelta;
5409         event.lastLinkLayerStatsUpdateTime = mLlStatsLastUpdateTime;
5410         event.screenOn = mScreenOn;
5411         event.mobileTxBytes = mFacade.getMobileTxBytes();
5412         event.mobileRxBytes = mFacade.getMobileRxBytes();
5413         event.totalTxBytes = mFacade.getTotalTxBytes();
5414         event.totalRxBytes = mFacade.getTotalRxBytes();
5415 
5416         mWifiIsUnusableList.add(new WifiIsUnusableWithTime(event, mClock.getWallClockMillis()));
5417         if (mWifiIsUnusableList.size() > MAX_UNUSABLE_EVENTS) {
5418             mWifiIsUnusableList.removeFirst();
5419         }
5420     }
5421 
5422     /**
5423      * Extract data from |info| and |stats| to build a WifiUsabilityStatsEntry and then adds it
5424      * into an internal ring buffer.
5425      * @param info
5426      * @param stats
5427      */
5428     public void updateWifiUsabilityStatsEntries(WifiInfo info, WifiLinkLayerStats stats) {
5429         synchronized (mLock) {
5430             if (info == null) {
5431                 return;
5432             }
5433             if (stats == null) {
5434                 // For devices lacking vendor hal, fill in the parts that we can
5435                 stats = new WifiLinkLayerStats();
5436                 stats.timeStampInMs = mClock.getElapsedSinceBootMillis();
5437                 stats.txmpdu_be = info.txSuccess;
5438                 stats.retries_be = info.txRetries;
5439                 stats.lostmpdu_be = info.txBad;
5440                 stats.rxmpdu_be = info.rxSuccess;
5441             }
5442             WifiUsabilityStatsEntry wifiUsabilityStatsEntry =
5443                     mWifiUsabilityStatsEntriesList.size()
5444                     < MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE
5445                     ? new WifiUsabilityStatsEntry() : mWifiUsabilityStatsEntriesList.remove();
5446             wifiUsabilityStatsEntry.timeStampMs = stats.timeStampInMs;
5447             wifiUsabilityStatsEntry.totalTxSuccess = stats.txmpdu_be + stats.txmpdu_bk
5448                     + stats.txmpdu_vi + stats.txmpdu_vo;
5449             wifiUsabilityStatsEntry.totalTxRetries = stats.retries_be + stats.retries_bk
5450                     + stats.retries_vi + stats.retries_vo;
5451             wifiUsabilityStatsEntry.totalTxBad = stats.lostmpdu_be + stats.lostmpdu_bk
5452                     + stats.lostmpdu_vi + stats.lostmpdu_vo;
5453             wifiUsabilityStatsEntry.totalRxSuccess = stats.rxmpdu_be + stats.rxmpdu_bk
5454                     + stats.rxmpdu_vi + stats.rxmpdu_vo;
5455             wifiUsabilityStatsEntry.totalRadioOnTimeMs = stats.on_time;
5456             wifiUsabilityStatsEntry.totalRadioTxTimeMs = stats.tx_time;
5457             wifiUsabilityStatsEntry.totalRadioRxTimeMs = stats.rx_time;
5458             wifiUsabilityStatsEntry.totalScanTimeMs = stats.on_time_scan;
5459             wifiUsabilityStatsEntry.totalNanScanTimeMs = stats.on_time_nan_scan;
5460             wifiUsabilityStatsEntry.totalBackgroundScanTimeMs = stats.on_time_background_scan;
5461             wifiUsabilityStatsEntry.totalRoamScanTimeMs = stats.on_time_roam_scan;
5462             wifiUsabilityStatsEntry.totalPnoScanTimeMs = stats.on_time_pno_scan;
5463             wifiUsabilityStatsEntry.totalHotspot2ScanTimeMs = stats.on_time_hs20_scan;
5464             wifiUsabilityStatsEntry.rssi = info.getRssi();
5465             wifiUsabilityStatsEntry.linkSpeedMbps = info.getLinkSpeed();
5466             WifiLinkLayerStats.ChannelStats statsMap =
5467                     stats.channelStatsMap.get(info.getFrequency());
5468             if (statsMap != null) {
5469                 wifiUsabilityStatsEntry.totalRadioOnFreqTimeMs = statsMap.radioOnTimeMs;
5470                 wifiUsabilityStatsEntry.totalCcaBusyFreqTimeMs = statsMap.ccaBusyTimeMs;
5471             }
5472             wifiUsabilityStatsEntry.totalBeaconRx = stats.beacon_rx;
5473 
5474             boolean isSameBssidAndFreq = mLastBssid == null || mLastFrequency == -1
5475                     || (mLastBssid.equals(info.getBSSID())
5476                     && mLastFrequency == info.getFrequency());
5477             mLastBssid = info.getBSSID();
5478             mLastFrequency = info.getFrequency();
5479             wifiUsabilityStatsEntry.wifiScore = mLastScoreNoReset;
5480             wifiUsabilityStatsEntry.wifiUsabilityScore = mLastWifiUsabilityScoreNoReset;
5481             wifiUsabilityStatsEntry.seqNumToFramework = mSeqNumToFramework;
5482             wifiUsabilityStatsEntry.predictionHorizonSec = mLastPredictionHorizonSecNoReset;
5483             switch (mProbeStatusSinceLastUpdate) {
5484                 case android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE:
5485                     wifiUsabilityStatsEntry.probeStatusSinceLastUpdate =
5486                             WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE;
5487                     break;
5488                 case android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS:
5489                     wifiUsabilityStatsEntry.probeStatusSinceLastUpdate =
5490                             WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS;
5491                     break;
5492                 case android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE:
5493                     wifiUsabilityStatsEntry.probeStatusSinceLastUpdate =
5494                             WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE;
5495                     break;
5496                 default:
5497                     wifiUsabilityStatsEntry.probeStatusSinceLastUpdate =
5498                             WifiUsabilityStatsEntry.PROBE_STATUS_UNKNOWN;
5499                     Log.e(TAG, "Unknown link probe status: " + mProbeStatusSinceLastUpdate);
5500             }
5501             wifiUsabilityStatsEntry.probeElapsedTimeSinceLastUpdateMs =
5502                     mProbeElapsedTimeSinceLastUpdateMs;
5503             wifiUsabilityStatsEntry.probeMcsRateSinceLastUpdate = mProbeMcsRateSinceLastUpdate;
5504             wifiUsabilityStatsEntry.rxLinkSpeedMbps = info.getRxLinkSpeedMbps();
5505             wifiUsabilityStatsEntry.isSameBssidAndFreq = isSameBssidAndFreq;
5506             wifiUsabilityStatsEntry.seqNumInsideFramework = mSeqNumInsideFramework;
5507             wifiUsabilityStatsEntry.deviceMobilityState = mCurrentDeviceMobilityState;
5508 
5509             mWifiUsabilityStatsEntriesList.add(wifiUsabilityStatsEntry);
5510             mWifiUsabilityStatsCounter++;
5511             if (mWifiUsabilityStatsCounter >= NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD) {
5512                 addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_GOOD,
5513                         WifiUsabilityStats.TYPE_UNKNOWN, -1);
5514             }
5515             if (mScoreBreachLowTimeMillis != -1) {
5516                 long elapsedTime =  mClock.getElapsedSinceBootMillis() - mScoreBreachLowTimeMillis;
5517                 if (elapsedTime >= MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS) {
5518                     mScoreBreachLowTimeMillis = -1;
5519                     if (elapsedTime <= VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS) {
5520                         addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_GOOD,
5521                                 WifiUsabilityStats.TYPE_UNKNOWN, -1);
5522                     }
5523                 }
5524             }
5525 
5526             // Invoke Wifi usability stats listener.
5527             sendWifiUsabilityStats(mSeqNumInsideFramework, isSameBssidAndFreq,
5528                     createNewWifiUsabilityStatsEntryParcelable(wifiUsabilityStatsEntry));
5529 
5530             mSeqNumInsideFramework++;
5531             mProbeStatusSinceLastUpdate =
5532                     android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE;
5533             mProbeElapsedTimeSinceLastUpdateMs = -1;
5534             mProbeMcsRateSinceLastUpdate = -1;
5535         }
5536     }
5537 
5538     /**
5539      * Send Wifi usability stats.
5540      * @param seqNum
5541      * @param isSameBssidAndFreq
5542      * @param statsEntry
5543      */
5544     private void sendWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq,
5545             android.net.wifi.WifiUsabilityStatsEntry statsEntry) {
5546         for (IOnWifiUsabilityStatsListener listener : mOnWifiUsabilityListeners.getCallbacks()) {
5547             try {
5548                 listener.onWifiUsabilityStats(seqNum, isSameBssidAndFreq, statsEntry);
5549             } catch (RemoteException e) {
5550                 Log.e(TAG, "Unable to invoke Wifi usability stats entry listener "
5551                         + listener, e);
5552             }
5553         }
5554     }
5555 
5556     private android.net.wifi.WifiUsabilityStatsEntry createNewWifiUsabilityStatsEntryParcelable(
5557             WifiUsabilityStatsEntry s) {
5558         int probeStatus;
5559         switch (s.probeStatusSinceLastUpdate) {
5560             case WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE:
5561                 probeStatus = android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE;
5562                 break;
5563             case WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS:
5564                 probeStatus = android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS;
5565                 break;
5566             case WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE:
5567                 probeStatus = android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE;
5568                 break;
5569             default:
5570                 probeStatus = android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_UNKNOWN;
5571                 Log.e(TAG, "Unknown link probe status: " + s.probeStatusSinceLastUpdate);
5572         }
5573         // TODO: remove the following hardcoded values once if they are removed from public API
5574         return new android.net.wifi.WifiUsabilityStatsEntry(s.timeStampMs, s.rssi,
5575                 s.linkSpeedMbps, s.totalTxSuccess, s.totalTxRetries,
5576                 s.totalTxBad, s.totalRxSuccess, s.totalRadioOnTimeMs,
5577                 s.totalRadioTxTimeMs, s.totalRadioRxTimeMs, s.totalScanTimeMs,
5578                 s.totalNanScanTimeMs, s.totalBackgroundScanTimeMs, s.totalRoamScanTimeMs,
5579                 s.totalPnoScanTimeMs, s.totalHotspot2ScanTimeMs, s.totalCcaBusyFreqTimeMs,
5580                 s.totalRadioOnFreqTimeMs, s.totalBeaconRx, probeStatus,
5581                 s.probeElapsedTimeSinceLastUpdateMs, s.probeMcsRateSinceLastUpdate,
5582                 s.rxLinkSpeedMbps, 0, 0, 0, false
5583         );
5584     }
5585 
5586     private WifiUsabilityStatsEntry createNewWifiUsabilityStatsEntry(WifiUsabilityStatsEntry s) {
5587         WifiUsabilityStatsEntry out = new WifiUsabilityStatsEntry();
5588         out.timeStampMs = s.timeStampMs;
5589         out.totalTxSuccess = s.totalTxSuccess;
5590         out.totalTxRetries = s.totalTxRetries;
5591         out.totalTxBad = s.totalTxBad;
5592         out.totalRxSuccess = s.totalRxSuccess;
5593         out.totalRadioOnTimeMs = s.totalRadioOnTimeMs;
5594         out.totalRadioTxTimeMs = s.totalRadioTxTimeMs;
5595         out.totalRadioRxTimeMs = s.totalRadioRxTimeMs;
5596         out.totalScanTimeMs = s.totalScanTimeMs;
5597         out.totalNanScanTimeMs = s.totalNanScanTimeMs;
5598         out.totalBackgroundScanTimeMs = s.totalBackgroundScanTimeMs;
5599         out.totalRoamScanTimeMs = s.totalRoamScanTimeMs;
5600         out.totalPnoScanTimeMs = s.totalPnoScanTimeMs;
5601         out.totalHotspot2ScanTimeMs = s.totalHotspot2ScanTimeMs;
5602         out.rssi = s.rssi;
5603         out.linkSpeedMbps = s.linkSpeedMbps;
5604         out.totalCcaBusyFreqTimeMs = s.totalCcaBusyFreqTimeMs;
5605         out.totalRadioOnFreqTimeMs = s.totalRadioOnFreqTimeMs;
5606         out.totalBeaconRx = s.totalBeaconRx;
5607         out.wifiScore = s.wifiScore;
5608         out.wifiUsabilityScore = s.wifiUsabilityScore;
5609         out.seqNumToFramework = s.seqNumToFramework;
5610         out.predictionHorizonSec = s.predictionHorizonSec;
5611         out.probeStatusSinceLastUpdate = s.probeStatusSinceLastUpdate;
5612         out.probeElapsedTimeSinceLastUpdateMs = s.probeElapsedTimeSinceLastUpdateMs;
5613         out.probeMcsRateSinceLastUpdate = s.probeMcsRateSinceLastUpdate;
5614         out.rxLinkSpeedMbps = s.rxLinkSpeedMbps;
5615         out.isSameBssidAndFreq = s.isSameBssidAndFreq;
5616         out.seqNumInsideFramework = s.seqNumInsideFramework;
5617         out.deviceMobilityState = s.deviceMobilityState;
5618         return out;
5619     }
5620 
5621     private WifiUsabilityStats createWifiUsabilityStatsWithLabel(int label, int triggerType,
5622             int firmwareAlertCode) {
5623         WifiUsabilityStats wifiUsabilityStats = new WifiUsabilityStats();
5624         wifiUsabilityStats.label = label;
5625         wifiUsabilityStats.triggerType = triggerType;
5626         wifiUsabilityStats.firmwareAlertCode = firmwareAlertCode;
5627         wifiUsabilityStats.timeStampMs = mClock.getElapsedSinceBootMillis();
5628         wifiUsabilityStats.stats =
5629                 new WifiUsabilityStatsEntry[mWifiUsabilityStatsEntriesList.size()];
5630         for (int i = 0; i < mWifiUsabilityStatsEntriesList.size(); i++) {
5631             wifiUsabilityStats.stats[i] =
5632                     createNewWifiUsabilityStatsEntry(mWifiUsabilityStatsEntriesList.get(i));
5633         }
5634         return wifiUsabilityStats;
5635     }
5636 
5637     /**
5638      * Label the current snapshot of WifiUsabilityStatsEntrys and save the labeled data in memory.
5639      * @param label WifiUsabilityStats.LABEL_GOOD or WifiUsabilityStats.LABEL_BAD
5640      * @param triggerType what event triggers WifiUsabilityStats
5641      * @param firmwareAlertCode the firmware alert code when the stats was triggered by a
5642      *        firmware alert
5643      */
5644     public void addToWifiUsabilityStatsList(int label, int triggerType, int firmwareAlertCode) {
5645         synchronized (mLock) {
5646             if (mWifiUsabilityStatsEntriesList.isEmpty() || !mScreenOn) {
5647                 return;
5648             }
5649             if (label == WifiUsabilityStats.LABEL_GOOD) {
5650                 // Only add a good event if at least |MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS|
5651                 // has passed.
5652                 if (mWifiUsabilityStatsListGood.isEmpty()
5653                         || mWifiUsabilityStatsListGood.getLast().stats[mWifiUsabilityStatsListGood
5654                         .getLast().stats.length - 1].timeStampMs
5655                         + MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS
5656                         < mWifiUsabilityStatsEntriesList.getLast().timeStampMs) {
5657                     while (mWifiUsabilityStatsListGood.size()
5658                             >= MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE) {
5659                         mWifiUsabilityStatsListGood.remove(
5660                                 mRand.nextInt(mWifiUsabilityStatsListGood.size()));
5661                     }
5662                     mWifiUsabilityStatsListGood.add(
5663                             createWifiUsabilityStatsWithLabel(label, triggerType,
5664                                     firmwareAlertCode));
5665                 }
5666             } else {
5667                 // Only add a bad event if at least |MIN_DATA_STALL_WAIT_MS|
5668                 // has passed.
5669                 mScoreBreachLowTimeMillis = -1;
5670                 if (mWifiUsabilityStatsListBad.isEmpty()
5671                         || (mWifiUsabilityStatsListBad.getLast().stats[mWifiUsabilityStatsListBad
5672                         .getLast().stats.length - 1].timeStampMs
5673                         + MIN_DATA_STALL_WAIT_MS
5674                         < mWifiUsabilityStatsEntriesList.getLast().timeStampMs)) {
5675                     while (mWifiUsabilityStatsListBad.size()
5676                             >= MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE) {
5677                         mWifiUsabilityStatsListBad.remove(
5678                                 mRand.nextInt(mWifiUsabilityStatsListBad.size()));
5679                     }
5680                     mWifiUsabilityStatsListBad.add(
5681                             createWifiUsabilityStatsWithLabel(label, triggerType,
5682                                     firmwareAlertCode));
5683                 }
5684             }
5685             mWifiUsabilityStatsCounter = 0;
5686             mWifiUsabilityStatsEntriesList.clear();
5687         }
5688     }
5689 
5690     private DeviceMobilityStatePnoScanStats getOrCreateDeviceMobilityStatePnoScanStats(
5691             @DeviceMobilityState int deviceMobilityState) {
5692         DeviceMobilityStatePnoScanStats stats = mMobilityStatePnoStatsMap.get(deviceMobilityState);
5693         if (stats == null) {
5694             stats = new DeviceMobilityStatePnoScanStats();
5695             stats.deviceMobilityState = deviceMobilityState;
5696             stats.numTimesEnteredState = 0;
5697             stats.totalDurationMs = 0;
5698             stats.pnoDurationMs = 0;
5699             mMobilityStatePnoStatsMap.put(deviceMobilityState, stats);
5700         }
5701         return stats;
5702     }
5703 
5704     /**
5705      * Updates the current device mobility state's total duration. This method should be called
5706      * before entering a new device mobility state.
5707      */
5708     private void updateCurrentMobilityStateTotalDuration(long now) {
5709         DeviceMobilityStatePnoScanStats stats =
5710                 getOrCreateDeviceMobilityStatePnoScanStats(mCurrentDeviceMobilityState);
5711         stats.totalDurationMs += now - mCurrentDeviceMobilityStateStartMs;
5712         mCurrentDeviceMobilityStateStartMs = now;
5713     }
5714 
5715     /**
5716      * Convert the IntCounter of passpoint profile types and counts to proto's
5717      * repeated IntKeyVal array.
5718      *
5719      * @param passpointProfileTypes passpoint profile types and counts.
5720      */
5721     private PasspointProfileTypeCount[] convertPasspointProfilesToProto(
5722                 IntCounter passpointProfileTypes) {
5723         return passpointProfileTypes.toProto(PasspointProfileTypeCount.class, (key, count) -> {
5724             PasspointProfileTypeCount entry = new PasspointProfileTypeCount();
5725             entry.eapMethodType = key;
5726             entry.count = count;
5727             return entry;
5728         });
5729     }
5730 
5731     /**
5732      * Reports that the device entered a new mobility state.
5733      *
5734      * @param newState the new device mobility state.
5735      */
5736     public void enterDeviceMobilityState(@DeviceMobilityState int newState) {
5737         synchronized (mLock) {
5738             long now = mClock.getElapsedSinceBootMillis();
5739             updateCurrentMobilityStateTotalDuration(now);
5740 
5741             if (newState == mCurrentDeviceMobilityState) return;
5742 
5743             mCurrentDeviceMobilityState = newState;
5744             DeviceMobilityStatePnoScanStats stats =
5745                     getOrCreateDeviceMobilityStatePnoScanStats(mCurrentDeviceMobilityState);
5746             stats.numTimesEnteredState++;
5747         }
5748     }
5749 
5750     /**
5751      * Logs the start of a PNO scan.
5752      */
5753     public void logPnoScanStart() {
5754         synchronized (mLock) {
5755             long now = mClock.getElapsedSinceBootMillis();
5756             mCurrentDeviceMobilityStatePnoScanStartMs = now;
5757             updateCurrentMobilityStateTotalDuration(now);
5758         }
5759     }
5760 
5761     /**
5762      * Logs the end of a PNO scan. This is attributed to the current device mobility state, as
5763      * logged by {@link #enterDeviceMobilityState(int)}. Thus, if the mobility state changes during
5764      * a PNO scan, one should call {@link #logPnoScanStop()}, {@link #enterDeviceMobilityState(int)}
5765      * , then {@link #logPnoScanStart()} so that the portion of PNO scan before the mobility state
5766      * change can be correctly attributed to the previous mobility state.
5767      */
5768     public void logPnoScanStop() {
5769         synchronized (mLock) {
5770             if (mCurrentDeviceMobilityStatePnoScanStartMs < 0) {
5771                 Log.e(TAG, "Called WifiMetrics#logPNoScanStop() without calling "
5772                         + "WifiMetrics#logPnoScanStart() first!");
5773                 return;
5774             }
5775             DeviceMobilityStatePnoScanStats stats =
5776                     getOrCreateDeviceMobilityStatePnoScanStats(mCurrentDeviceMobilityState);
5777             long now = mClock.getElapsedSinceBootMillis();
5778             stats.pnoDurationMs += now - mCurrentDeviceMobilityStatePnoScanStartMs;
5779             mCurrentDeviceMobilityStatePnoScanStartMs = -1;
5780             updateCurrentMobilityStateTotalDuration(now);
5781         }
5782     }
5783 
5784     /**
5785      * Add a new listener for Wi-Fi usability stats handling.
5786      */
5787     public void addOnWifiUsabilityListener(IBinder binder, IOnWifiUsabilityStatsListener listener,
5788             int listenerIdentifier) {
5789         if (!mOnWifiUsabilityListeners.add(binder, listener, listenerIdentifier)) {
5790             Log.e(TAG, "Failed to add listener");
5791             return;
5792         }
5793         if (DBG) {
5794             Log.v(TAG, "Adding listener. Num listeners: "
5795                     + mOnWifiUsabilityListeners.getNumCallbacks());
5796         }
5797     }
5798 
5799     /**
5800      * Remove an existing listener for Wi-Fi usability stats handling.
5801      */
5802     public void removeOnWifiUsabilityListener(int listenerIdentifier) {
5803         mOnWifiUsabilityListeners.remove(listenerIdentifier);
5804         if (DBG) {
5805             Log.v(TAG, "Removing listener. Num listeners: "
5806                     + mOnWifiUsabilityListeners.getNumCallbacks());
5807         }
5808     }
5809 
5810     /**
5811      * Updates the Wi-Fi usability score and increments occurence of a particular Wifi usability
5812      * score passed in from outside framework. Scores are bounded within
5813      * [MIN_WIFI_USABILITY_SCORE, MAX_WIFI_USABILITY_SCORE].
5814      *
5815      * Also records events when the Wifi usability score breaches significant thresholds.
5816      *
5817      * @param seqNum Sequence number of the Wi-Fi usability score.
5818      * @param score The Wi-Fi usability score.
5819      * @param predictionHorizonSec Prediction horizon of the Wi-Fi usability score.
5820      */
5821     public void incrementWifiUsabilityScoreCount(int seqNum, int score, int predictionHorizonSec) {
5822         if (score < MIN_WIFI_USABILITY_SCORE || score > MAX_WIFI_USABILITY_SCORE) {
5823             return;
5824         }
5825         synchronized (mLock) {
5826             mSeqNumToFramework = seqNum;
5827             mLastWifiUsabilityScore = score;
5828             mLastWifiUsabilityScoreNoReset = score;
5829             mWifiUsabilityScoreCounts.put(score, mWifiUsabilityScoreCounts.get(score) + 1);
5830             mLastPredictionHorizonSec = predictionHorizonSec;
5831             mLastPredictionHorizonSecNoReset = predictionHorizonSec;
5832 
5833             boolean wifiWins = mWifiWinsUsabilityScore;
5834             if (score > LOW_WIFI_USABILITY_SCORE) {
5835                 wifiWins = true;
5836             } else if (score < LOW_WIFI_USABILITY_SCORE) {
5837                 wifiWins = false;
5838             }
5839 
5840             if (wifiWins != mWifiWinsUsabilityScore) {
5841                 mWifiWinsUsabilityScore = wifiWins;
5842                 StaEvent event = new StaEvent();
5843                 event.type = StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH;
5844                 addStaEvent(event);
5845                 // Only record the first score breach by checking whether mScoreBreachLowTimeMillis
5846                 // has been set to -1
5847                 if (!wifiWins && mScoreBreachLowTimeMillis == -1) {
5848                     mScoreBreachLowTimeMillis = mClock.getElapsedSinceBootMillis();
5849                 }
5850             }
5851         }
5852     }
5853 
5854     /**
5855      * Reports stats for a successful link probe.
5856      *
5857      * @param timeSinceLastTxSuccessMs At {@code startTimestampMs}, the number of milliseconds since
5858      *                                 the last Tx success (according to
5859      *                                 {@link WifiInfo#txSuccess}).
5860      * @param rssi The Rx RSSI at {@code startTimestampMs}.
5861      * @param linkSpeed The Tx link speed in Mbps at {@code startTimestampMs}.
5862      * @param elapsedTimeMs The number of milliseconds between when the command to transmit the
5863      *                      probe was sent to the driver and when the driver responded that the
5864      *                      probe was ACKed. Note: this number should be correlated with the number
5865      *                      of retries that the driver attempted before the probe was ACKed.
5866      */
5867     public void logLinkProbeSuccess(long timeSinceLastTxSuccessMs,
5868             int rssi, int linkSpeed, int elapsedTimeMs) {
5869         synchronized (mLock) {
5870             mProbeStatusSinceLastUpdate =
5871                     android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS;
5872             mProbeElapsedTimeSinceLastUpdateMs = elapsedTimeMs;
5873 
5874             mLinkProbeSuccessSecondsSinceLastTxSuccessHistogram.increment(
5875                     (int) (timeSinceLastTxSuccessMs / 1000));
5876             mLinkProbeSuccessRssiCounts.increment(rssi);
5877             mLinkProbeSuccessLinkSpeedCounts.increment(linkSpeed);
5878             mLinkProbeSuccessElapsedTimeMsHistogram.increment(elapsedTimeMs);
5879 
5880             if (mLinkProbeStaEventCount < MAX_LINK_PROBE_STA_EVENTS) {
5881                 StaEvent event = new StaEvent();
5882                 event.type = StaEvent.TYPE_LINK_PROBE;
5883                 event.linkProbeWasSuccess = true;
5884                 event.linkProbeSuccessElapsedTimeMs = elapsedTimeMs;
5885                 addStaEvent(event);
5886             }
5887             mLinkProbeStaEventCount++;
5888         }
5889     }
5890 
5891     /**
5892      * Reports stats for an unsuccessful link probe.
5893      *
5894      * @param timeSinceLastTxSuccessMs At {@code startTimestampMs}, the number of milliseconds since
5895      *                                 the last Tx success (according to
5896      *                                 {@link WifiInfo#txSuccess}).
5897      * @param rssi The Rx RSSI at {@code startTimestampMs}.
5898      * @param linkSpeed The Tx link speed in Mbps at {@code startTimestampMs}.
5899      * @param reason The error code for the failure. See
5900      * {@link WifiNl80211Manager.SendMgmtFrameError}.
5901      */
5902     public void logLinkProbeFailure(long timeSinceLastTxSuccessMs,
5903             int rssi, int linkSpeed, int reason) {
5904         synchronized (mLock) {
5905             mProbeStatusSinceLastUpdate =
5906                     android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE;
5907             mProbeElapsedTimeSinceLastUpdateMs = Integer.MAX_VALUE;
5908 
5909             mLinkProbeFailureSecondsSinceLastTxSuccessHistogram.increment(
5910                     (int) (timeSinceLastTxSuccessMs / 1000));
5911             mLinkProbeFailureRssiCounts.increment(rssi);
5912             mLinkProbeFailureLinkSpeedCounts.increment(linkSpeed);
5913             mLinkProbeFailureReasonCounts.increment(reason);
5914 
5915             if (mLinkProbeStaEventCount < MAX_LINK_PROBE_STA_EVENTS) {
5916                 StaEvent event = new StaEvent();
5917                 event.type = StaEvent.TYPE_LINK_PROBE;
5918                 event.linkProbeWasSuccess = false;
5919                 event.linkProbeFailureReason = linkProbeFailureReasonToProto(reason);
5920                 addStaEvent(event);
5921             }
5922             mLinkProbeStaEventCount++;
5923         }
5924     }
5925 
5926     /**
5927      * Increments the number of probes triggered by the experiment `experimentId`.
5928      */
5929     public void incrementLinkProbeExperimentProbeCount(String experimentId) {
5930         synchronized (mLock) {
5931             mLinkProbeExperimentProbeCounts.increment(experimentId);
5932         }
5933     }
5934 
5935     /**
5936      * Update wifi config store read duration.
5937      *
5938      * @param timeMs Time it took to complete the operation, in milliseconds
5939      */
5940     public void noteWifiConfigStoreReadDuration(int timeMs) {
5941         synchronized (mLock) {
5942             MetricsUtils.addValueToLinearHistogram(timeMs, mWifiConfigStoreReadDurationHistogram,
5943                     WIFI_CONFIG_STORE_IO_DURATION_BUCKET_RANGES_MS);
5944         }
5945     }
5946 
5947     /**
5948      * Update wifi config store write duration.
5949      *
5950      * @param timeMs Time it took to complete the operation, in milliseconds
5951      */
5952     public void noteWifiConfigStoreWriteDuration(int timeMs) {
5953         synchronized (mLock) {
5954             MetricsUtils.addValueToLinearHistogram(timeMs, mWifiConfigStoreWriteDurationHistogram,
5955                     WIFI_CONFIG_STORE_IO_DURATION_BUCKET_RANGES_MS);
5956         }
5957     }
5958 
5959     /**
5960      * Logs the decision of a network selection algorithm when compared against another network
5961      * selection algorithm.
5962      *
5963      * @param experiment1Id ID of one experiment
5964      * @param experiment2Id ID of the other experiment
5965      * @param isSameDecision did the 2 experiments make the same decision?
5966      * @param numNetworkChoices the number of non-null network choices there were, where the null
5967      *                          choice is not selecting any network
5968      */
5969     public void logNetworkSelectionDecision(int experiment1Id, int experiment2Id,
5970             boolean isSameDecision, int numNetworkChoices) {
5971         if (numNetworkChoices < 0) {
5972             Log.e(TAG, "numNetworkChoices cannot be negative!");
5973             return;
5974         }
5975         if (experiment1Id == experiment2Id) {
5976             Log.e(TAG, "comparing the same experiment id: " + experiment1Id);
5977             return;
5978         }
5979 
5980         Pair<Integer, Integer> key = new Pair<>(experiment1Id, experiment2Id);
5981         synchronized (mLock) {
5982             NetworkSelectionExperimentResults results =
5983                     mNetworkSelectionExperimentPairNumChoicesCounts
5984                             .computeIfAbsent(key, k -> new NetworkSelectionExperimentResults());
5985 
5986             IntCounter counter = isSameDecision
5987                     ? results.sameSelectionNumChoicesCounter
5988                     : results.differentSelectionNumChoicesCounter;
5989 
5990             counter.increment(numNetworkChoices);
5991         }
5992     }
5993 
5994     /** Increment number of network request API usage stats */
5995     public void incrementNetworkRequestApiNumRequest() {
5996         synchronized (mLock) {
5997             mWifiNetworkRequestApiLog.numRequest++;
5998         }
5999     }
6000 
6001     /** Add to the network request API match size histogram */
6002     public void incrementNetworkRequestApiMatchSizeHistogram(int matchSize) {
6003         synchronized (mLock) {
6004             mWifiNetworkRequestApiMatchSizeHistogram.increment(matchSize);
6005         }
6006     }
6007 
6008     /** Increment number of connection success via network request API */
6009     public void incrementNetworkRequestApiNumConnectSuccess() {
6010         synchronized (mLock) {
6011             mWifiNetworkRequestApiLog.numConnectSuccess++;
6012         }
6013     }
6014 
6015     /** Increment number of requests that bypassed user approval via network request API */
6016     public void incrementNetworkRequestApiNumUserApprovalBypass() {
6017         synchronized (mLock) {
6018             mWifiNetworkRequestApiLog.numUserApprovalBypass++;
6019         }
6020     }
6021 
6022     /** Increment number of requests that user rejected via network request API */
6023     public void incrementNetworkRequestApiNumUserReject() {
6024         synchronized (mLock) {
6025             mWifiNetworkRequestApiLog.numUserReject++;
6026         }
6027     }
6028 
6029     /** Increment number of requests from unique apps via network request API */
6030     public void incrementNetworkRequestApiNumApps() {
6031         synchronized (mLock) {
6032             mWifiNetworkRequestApiLog.numApps++;
6033         }
6034     }
6035 
6036     /** Increment number of network suggestion API modification by app stats */
6037     public void incrementNetworkSuggestionApiNumModification() {
6038         synchronized (mLock) {
6039             mWifiNetworkSuggestionApiLog.numModification++;
6040         }
6041     }
6042 
6043     /** Increment number of connection success via network suggestion API */
6044     public void incrementNetworkSuggestionApiNumConnectSuccess() {
6045         synchronized (mLock) {
6046             mWifiNetworkSuggestionApiLog.numConnectSuccess++;
6047         }
6048     }
6049 
6050     /** Increment number of connection failure via network suggestion API */
6051     public void incrementNetworkSuggestionApiNumConnectFailure() {
6052         synchronized (mLock) {
6053             mWifiNetworkSuggestionApiLog.numConnectFailure++;
6054         }
6055     }
6056 
6057     /** Increment number of user revoke suggestion permission. Including from settings or
6058      * disallowed from UI.
6059      */
6060     public void incrementNetworkSuggestionUserRevokePermission() {
6061         synchronized (mLock) {
6062             mWifiNetworkSuggestionApiLog.userRevokeAppSuggestionPermission++;
6063         }
6064     }
6065 
6066     /** Clear and set the latest network suggestion API max list size histogram */
6067     public void noteNetworkSuggestionApiListSizeHistogram(List<Integer> listSizes) {
6068         synchronized (mLock) {
6069             mWifiNetworkSuggestionApiListSizeHistogram.clear();
6070             for (Integer listSize : listSizes) {
6071                 mWifiNetworkSuggestionApiListSizeHistogram.increment(listSize);
6072             }
6073         }
6074     }
6075 
6076     /** Increment number of app add suggestion with different privilege */
6077     public void incrementNetworkSuggestionApiUsageNumOfAppInType(int appType) {
6078         int typeCode;
6079         synchronized (mLock) {
6080             switch (appType) {
6081                 case WifiNetworkSuggestionsManager.APP_TYPE_CARRIER_PRIVILEGED:
6082                     typeCode = WifiNetworkSuggestionApiLog.TYPE_CARRIER_PRIVILEGED;
6083                     break;
6084                 case WifiNetworkSuggestionsManager.APP_TYPE_NETWORK_PROVISIONING:
6085                     typeCode = WifiNetworkSuggestionApiLog.TYPE_NETWORK_PROVISIONING;
6086                     break;
6087                 case WifiNetworkSuggestionsManager.APP_TYPE_NON_PRIVILEGED:
6088                     typeCode = WifiNetworkSuggestionApiLog.TYPE_NON_PRIVILEGED;
6089                     break;
6090                 default:
6091                     typeCode = WifiNetworkSuggestionApiLog.TYPE_UNKNOWN;
6092             }
6093             mWifiNetworkSuggestionApiAppTypeCounter.increment(typeCode);
6094         }
6095     }
6096 
6097     /** Add user action to the approval suggestion app UI */
6098     public void addUserApprovalSuggestionAppUiReaction(@WifiNetworkSuggestionsManager.UserActionCode
6099             int actionType, boolean isDialog) {
6100         int actionCode;
6101         switch (actionType) {
6102             case WifiNetworkSuggestionsManager.ACTION_USER_ALLOWED_APP:
6103                 actionCode = UserReactionToApprovalUiEvent.ACTION_ALLOWED;
6104                 break;
6105             case WifiNetworkSuggestionsManager.ACTION_USER_DISALLOWED_APP:
6106                 actionCode = UserReactionToApprovalUiEvent.ACTION_DISALLOWED;
6107                 break;
6108             case WifiNetworkSuggestionsManager.ACTION_USER_DISMISS:
6109                 actionCode = UserReactionToApprovalUiEvent.ACTION_DISMISS;
6110                 break;
6111             default:
6112                 actionCode = UserReactionToApprovalUiEvent.ACTION_UNKNOWN;
6113         }
6114         UserReaction event = new UserReaction();
6115         event.userAction = actionCode;
6116         event.isDialog = isDialog;
6117         synchronized (mLock) {
6118             mUserApprovalSuggestionAppUiReactionList.add(event);
6119         }
6120     }
6121 
6122     /** Add user action to the approval Carrier Imsi protection exemption UI */
6123     public void addUserApprovalCarrierUiReaction(@WifiCarrierInfoManager.UserActionCode
6124             int actionType, boolean isDialog) {
6125         int actionCode;
6126         switch (actionType) {
6127             case WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER:
6128                 actionCode = UserReactionToApprovalUiEvent.ACTION_ALLOWED;
6129                 break;
6130             case WifiCarrierInfoManager.ACTION_USER_DISALLOWED_CARRIER:
6131                 actionCode = UserReactionToApprovalUiEvent.ACTION_DISALLOWED;
6132                 break;
6133             case WifiCarrierInfoManager.ACTION_USER_DISMISS:
6134                 actionCode = UserReactionToApprovalUiEvent.ACTION_DISMISS;
6135                 break;
6136             default:
6137                 actionCode = UserReactionToApprovalUiEvent.ACTION_UNKNOWN;
6138         }
6139         UserReaction event = new UserReaction();
6140         event.userAction = actionCode;
6141         event.isDialog = isDialog;
6142 
6143         synchronized (mLock) {
6144             mUserApprovalCarrierUiReactionList.add(event);
6145         }
6146     }
6147 
6148     /**
6149      * Sets the nominator for a network (i.e. which entity made the suggestion to connect)
6150      * @param networkId the ID of the network, from its {@link WifiConfiguration}
6151      * @param nominatorId the entity that made the suggestion to connect to this network,
6152      *                    from {@link WifiMetricsProto.ConnectionEvent.ConnectionNominator}
6153      */
6154     public void setNominatorForNetwork(int networkId, int nominatorId) {
6155         synchronized (mLock) {
6156             if (networkId == WifiConfiguration.INVALID_NETWORK_ID) return;
6157             mNetworkIdToNominatorId.put(networkId, nominatorId);
6158         }
6159     }
6160 
6161     /**
6162      * Sets the numeric CandidateScorer id.
6163      */
6164     public void setNetworkSelectorExperimentId(int expId) {
6165         synchronized (mLock) {
6166             mNetworkSelectorExperimentId = expId;
6167         }
6168     }
6169 
6170     /** Add a WifiLock acqusition session */
6171     public void addWifiLockAcqSession(int lockType, long duration) {
6172         switch (lockType) {
6173             case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
6174                 mWifiLockHighPerfAcqDurationSecHistogram.increment((int) (duration / 1000));
6175                 break;
6176 
6177             case WifiManager.WIFI_MODE_FULL_LOW_LATENCY:
6178                 mWifiLockLowLatencyAcqDurationSecHistogram.increment((int) (duration / 1000));
6179                 break;
6180 
6181             default:
6182                 Log.e(TAG, "addWifiLockAcqSession: Invalid lock type: " + lockType);
6183                 break;
6184         }
6185     }
6186 
6187     /** Add a WifiLock active session */
6188     public void addWifiLockActiveSession(int lockType, long duration) {
6189         switch (lockType) {
6190             case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
6191                 mWifiLockStats.highPerfActiveTimeMs += duration;
6192                 mWifiLockHighPerfActiveSessionDurationSecHistogram.increment(
6193                         (int) (duration / 1000));
6194                 break;
6195 
6196             case WifiManager.WIFI_MODE_FULL_LOW_LATENCY:
6197                 mWifiLockStats.lowLatencyActiveTimeMs += duration;
6198                 mWifiLockLowLatencyActiveSessionDurationSecHistogram.increment(
6199                         (int) (duration / 1000));
6200                 break;
6201 
6202             default:
6203                 Log.e(TAG, "addWifiLockActiveSession: Invalid lock type: " + lockType);
6204                 break;
6205         }
6206     }
6207 
6208     /** Increments metrics counting number of addOrUpdateNetwork calls. **/
6209     public void incrementNumAddOrUpdateNetworkCalls() {
6210         synchronized (mLock) {
6211             mWifiLogProto.numAddOrUpdateNetworkCalls++;
6212         }
6213     }
6214 
6215     /** Increments metrics counting number of enableNetwork calls. **/
6216     public void incrementNumEnableNetworkCalls() {
6217         synchronized (mLock) {
6218             mWifiLogProto.numEnableNetworkCalls++;
6219         }
6220     }
6221 
6222     /** Add to WifiToggleStats **/
6223     public void incrementNumWifiToggles(boolean isPrivileged, boolean enable) {
6224         synchronized (mLock) {
6225             if (isPrivileged && enable) {
6226                 mWifiToggleStats.numToggleOnPrivileged++;
6227             } else if (isPrivileged && !enable) {
6228                 mWifiToggleStats.numToggleOffPrivileged++;
6229             } else if (!isPrivileged && enable) {
6230                 mWifiToggleStats.numToggleOnNormal++;
6231             } else {
6232                 mWifiToggleStats.numToggleOffNormal++;
6233             }
6234         }
6235     }
6236 
6237     /**
6238      * Increment number of passpoint provision failure
6239      * @param failureCode indicates error condition
6240      */
6241     public void incrementPasspointProvisionFailure(int failureCode) {
6242         int provisionFailureCode;
6243         synchronized (mLock) {
6244             switch (failureCode) {
6245                 case ProvisioningCallback.OSU_FAILURE_AP_CONNECTION:
6246                     provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_AP_CONNECTION;
6247                     break;
6248                 case ProvisioningCallback.OSU_FAILURE_SERVER_URL_INVALID:
6249                     provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_SERVER_URL_INVALID;
6250                     break;
6251                 case ProvisioningCallback.OSU_FAILURE_SERVER_CONNECTION:
6252                     provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_SERVER_CONNECTION;
6253                     break;
6254                 case ProvisioningCallback.OSU_FAILURE_SERVER_VALIDATION:
6255                     provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_SERVER_VALIDATION;
6256                     break;
6257                 case ProvisioningCallback.OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION:
6258                     provisionFailureCode = PasspointProvisionStats
6259                             .OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION;
6260                     break;
6261                 case ProvisioningCallback.OSU_FAILURE_PROVISIONING_ABORTED:
6262                     provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_PROVISIONING_ABORTED;
6263                     break;
6264                 case ProvisioningCallback.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE:
6265                     provisionFailureCode = PasspointProvisionStats
6266                             .OSU_FAILURE_PROVISIONING_NOT_AVAILABLE;
6267                     break;
6268                 case ProvisioningCallback.OSU_FAILURE_INVALID_URL_FORMAT_FOR_OSU:
6269                     provisionFailureCode = PasspointProvisionStats
6270                             .OSU_FAILURE_INVALID_URL_FORMAT_FOR_OSU;
6271                     break;
6272                 case ProvisioningCallback.OSU_FAILURE_UNEXPECTED_COMMAND_TYPE:
6273                     provisionFailureCode = PasspointProvisionStats
6274                             .OSU_FAILURE_UNEXPECTED_COMMAND_TYPE;
6275                     break;
6276                 case ProvisioningCallback.OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE:
6277                     provisionFailureCode = PasspointProvisionStats
6278                             .OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE;
6279                     break;
6280                 case ProvisioningCallback.OSU_FAILURE_SOAP_MESSAGE_EXCHANGE:
6281                     provisionFailureCode = PasspointProvisionStats
6282                             .OSU_FAILURE_SOAP_MESSAGE_EXCHANGE;
6283                     break;
6284                 case ProvisioningCallback.OSU_FAILURE_START_REDIRECT_LISTENER:
6285                     provisionFailureCode = PasspointProvisionStats
6286                             .OSU_FAILURE_START_REDIRECT_LISTENER;
6287                     break;
6288                 case ProvisioningCallback.OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER:
6289                     provisionFailureCode = PasspointProvisionStats
6290                             .OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER;
6291                     break;
6292                 case ProvisioningCallback.OSU_FAILURE_NO_OSU_ACTIVITY_FOUND:
6293                     provisionFailureCode = PasspointProvisionStats
6294                             .OSU_FAILURE_NO_OSU_ACTIVITY_FOUND;
6295                     break;
6296                 case ProvisioningCallback.OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS:
6297                     provisionFailureCode = PasspointProvisionStats
6298                             .OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS;
6299                     break;
6300                 case ProvisioningCallback.OSU_FAILURE_NO_PPS_MO:
6301                     provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_NO_PPS_MO;
6302                     break;
6303                 case ProvisioningCallback.OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE:
6304                     provisionFailureCode = PasspointProvisionStats
6305                             .OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE;
6306                     break;
6307                 case ProvisioningCallback.OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE:
6308                     provisionFailureCode = PasspointProvisionStats
6309                             .OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE;
6310                     break;
6311                 case ProvisioningCallback.OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE:
6312                     provisionFailureCode = PasspointProvisionStats
6313                             .OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE;
6314                     break;
6315                 case ProvisioningCallback.OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES:
6316                     provisionFailureCode = PasspointProvisionStats
6317                             .OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES;
6318                     break;
6319                 case ProvisioningCallback.OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE:
6320                     provisionFailureCode = PasspointProvisionStats
6321                             .OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE;
6322                     break;
6323                 case ProvisioningCallback.OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION:
6324                     provisionFailureCode = PasspointProvisionStats
6325                             .OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION;
6326                     break;
6327                 case ProvisioningCallback.OSU_FAILURE_OSU_PROVIDER_NOT_FOUND:
6328                     provisionFailureCode = PasspointProvisionStats
6329                             .OSU_FAILURE_OSU_PROVIDER_NOT_FOUND;
6330                     break;
6331                 default:
6332                     provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_UNKNOWN;
6333             }
6334             mPasspointProvisionFailureCounts.increment(provisionFailureCode);
6335         }
6336     }
6337 
6338     /**
6339      * Add to the histogram of number of BSSIDs filtered out from network selection.
6340      */
6341     public void incrementNetworkSelectionFilteredBssidCount(int numBssid) {
6342         mBssidBlocklistStats.networkSelectionFilteredBssidCount.increment(numBssid);
6343     }
6344 
6345     /**
6346      * Increment the number of network connections skipped due to the high movement feature.
6347      */
6348     public void incrementNumHighMovementConnectionSkipped() {
6349         mBssidBlocklistStats.numHighMovementConnectionSkipped++;
6350     }
6351 
6352     /**
6353      * Increment the number of network connections initiated while under the high movement
6354      * feature.
6355      */
6356     public void incrementNumHighMovementConnectionStarted() {
6357         mBssidBlocklistStats.numHighMovementConnectionStarted++;
6358     }
6359 
6360     /**
6361      * Increment number of passpoint provision success
6362      */
6363     public void incrementPasspointProvisionSuccess() {
6364         synchronized (mLock) {
6365             mNumProvisionSuccess++;
6366         }
6367     }
6368 
6369     /**
6370      * Increment number of IP renewal failures.
6371      */
6372     public void incrementIpRenewalFailure() {
6373         synchronized (mLock) {
6374             mWifiLogProto.numIpRenewalFailure++;
6375         }
6376     }
6377 
6378     /**
6379      * Sets the duration for evaluating Wifi condition to trigger a data stall
6380      */
6381     public void setDataStallDurationMs(int duration) {
6382         synchronized (mLock) {
6383             mExperimentValues.dataStallDurationMs = duration;
6384         }
6385     }
6386 
6387     /**
6388      * Sets the threshold of Tx throughput below which to trigger a data stall
6389      */
6390     public void setDataStallTxTputThrKbps(int txTputThr) {
6391         synchronized (mLock) {
6392             mExperimentValues.dataStallTxTputThrKbps = txTputThr;
6393         }
6394     }
6395 
6396     /**
6397      * Sets the threshold of Rx throughput below which to trigger a data stall
6398      */
6399     public void setDataStallRxTputThrKbps(int rxTputThr) {
6400         synchronized (mLock) {
6401             mExperimentValues.dataStallRxTputThrKbps = rxTputThr;
6402         }
6403     }
6404 
6405     /**
6406      * Sets the threshold of Tx packet error rate above which to trigger a data stall
6407      */
6408     public void setDataStallTxPerThr(int txPerThr) {
6409         synchronized (mLock) {
6410             mExperimentValues.dataStallTxPerThr = txPerThr;
6411         }
6412     }
6413 
6414     /**
6415      * Sets the threshold of CCA level above which to trigger a data stall
6416      */
6417     public void setDataStallCcaLevelThr(int ccaLevel) {
6418         synchronized (mLock) {
6419             mExperimentValues.dataStallCcaLevelThr = ccaLevel;
6420         }
6421     }
6422 
6423     /**
6424      * Sets health monitor RSSI poll valid time in ms
6425      */
6426     public void setHealthMonitorRssiPollValidTimeMs(int rssiPollValidTimeMs) {
6427         synchronized (mLock) {
6428             mExperimentValues.healthMonitorRssiPollValidTimeMs = rssiPollValidTimeMs;
6429         }
6430     }
6431 
6432     /**
6433      * Increment connection duration while link layer stats report are on
6434      */
6435     public void incrementConnectionDuration(int timeDeltaLastTwoPollsMs,
6436             boolean isThroughputSufficient, boolean isCellularDataAvailable) {
6437         synchronized (mLock) {
6438             mConnectionDurationStats.incrementDurationCount(timeDeltaLastTwoPollsMs,
6439                     isThroughputSufficient, isCellularDataAvailable);
6440         }
6441     }
6442 
6443     /**
6444      * Sets the status to indicate whether external WiFi connected network scorer is present or not.
6445      */
6446     public void setIsExternalWifiScorerOn(boolean value) {
6447         synchronized (mLock) {
6448             mWifiLogProto.isExternalWifiScorerOn = value;
6449         }
6450     }
6451 
6452     /**
6453      * Note Wi-Fi off metrics
6454      */
6455     public void noteWifiOff(boolean isDeferred, boolean isTimeout, int duration) {
6456         synchronized (mLock) {
6457             mWifiOffMetrics.numWifiOff++;
6458             if (isDeferred) {
6459                 mWifiOffMetrics.numWifiOffDeferring++;
6460                 if (isTimeout) {
6461                     mWifiOffMetrics.numWifiOffDeferringTimeout++;
6462                 }
6463                 mWifiOffMetrics.wifiOffDeferringTimeHistogram.increment(duration);
6464             }
6465         }
6466     }
6467 
6468     /**
6469      * Increment number of BSSIDs filtered out from network selection due to MBO Association
6470      * disallowed indication.
6471      */
6472     public void incrementNetworkSelectionFilteredBssidCountDueToMboAssocDisallowInd() {
6473         synchronized (mLock) {
6474             mWifiLogProto.numBssidFilteredDueToMboAssocDisallowInd++;
6475         }
6476     }
6477 
6478     /**
6479      * Increment number of times force scan is triggered due to a
6480      * BSS transition management request frame from AP.
6481      */
6482     public void incrementForceScanCountDueToSteeringRequest() {
6483         synchronized (mLock) {
6484             mWifiLogProto.numForceScanDueToSteeringRequest++;
6485         }
6486     }
6487 
6488     /**
6489      * Increment number of times STA received cellular switch
6490      * request from MBO supported AP.
6491      */
6492     public void incrementMboCellularSwitchRequestCount() {
6493         synchronized (mLock) {
6494             mWifiLogProto.numMboCellularSwitchRequest++;
6495         }
6496     }
6497 
6498     /**
6499      * Increment number of times STA received steering request
6500      * including MBO association retry delay.
6501      */
6502     public void incrementSteeringRequestCountIncludingMboAssocRetryDelay() {
6503         synchronized (mLock) {
6504             mWifiLogProto.numSteeringRequestIncludingMboAssocRetryDelay++;
6505         }
6506     }
6507 
6508     /**
6509      * Increment number of connect request to AP adding FILS AKM.
6510      */
6511     public void incrementConnectRequestWithFilsAkmCount() {
6512         synchronized (mLock) {
6513             mWifiLogProto.numConnectRequestWithFilsAkm++;
6514         }
6515     }
6516 
6517     /**
6518      * Increment number of times STA connected through FILS
6519      * authentication.
6520      */
6521     public void incrementL2ConnectionThroughFilsAuthCount() {
6522         synchronized (mLock) {
6523             mWifiLogProto.numL2ConnectionThroughFilsAuthentication++;
6524         }
6525     }
6526 
6527     /**
6528      * Note SoftapConfig Reset Metrics
6529      */
6530     public void noteSoftApConfigReset(SoftApConfiguration originalConfig,
6531             SoftApConfiguration newConfig) {
6532         synchronized (mLock) {
6533             if (originalConfig.getSecurityType() != newConfig.getSecurityType()) {
6534                 mSoftApConfigLimitationMetrics.numSecurityTypeResetToDefault++;
6535             }
6536             if (originalConfig.getMaxNumberOfClients() != newConfig.getMaxNumberOfClients()) {
6537                 mSoftApConfigLimitationMetrics.numMaxClientSettingResetToDefault++;
6538             }
6539             if (originalConfig.isClientControlByUserEnabled()
6540                     != newConfig.isClientControlByUserEnabled()) {
6541                 mSoftApConfigLimitationMetrics.numClientControlByUserResetToDefault++;
6542             }
6543         }
6544     }
6545 
6546     /**
6547      * Note Softap client blocked due to max client limitation
6548      */
6549     public void noteSoftApClientBlocked(int maxClient) {
6550         mSoftApConfigLimitationMetrics.maxClientSettingWhenReachHistogram.increment(maxClient);
6551     }
6552 
6553     /**
6554      * Increment number of connection with different BSSID between framework and firmware selection.
6555      */
6556     public void incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware() {
6557         synchronized (mLock) {
6558             mWifiLogProto.numBssidDifferentSelectionBetweenFrameworkAndFirmware++;
6559         }
6560     }
6561 
6562     /**
6563      * Note the carrier wifi network connected successfully.
6564      */
6565     public void incrementNumOfCarrierWifiConnectionSuccess() {
6566         synchronized (mLock) {
6567             mCarrierWifiMetrics.numConnectionSuccess++;
6568         }
6569     }
6570 
6571     /**
6572      * Note the carrier wifi network connection authentication failure.
6573      */
6574     public void incrementNumOfCarrierWifiConnectionAuthFailure() {
6575         synchronized (mLock) {
6576             mCarrierWifiMetrics.numConnectionAuthFailure++;
6577         }
6578     }
6579 
6580     /**
6581      * Note the carrier wifi network connection non-authentication failure.
6582      */
6583     public void incrementNumOfCarrierWifiConnectionNonAuthFailure() {
6584         synchronized (mLock) {
6585             mCarrierWifiMetrics.numConnectionNonAuthFailure++;
6586         }
6587     }
6588 }
6589