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