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 com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY;
22 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_CONFIG_SAVED;
23 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_IS_UNUSABLE_REPORTED;
24 
25 import static java.lang.StrictMath.toIntExact;
26 
27 import android.annotation.IntDef;
28 import android.annotation.NonNull;
29 import android.annotation.Nullable;
30 import android.app.ActivityManager;
31 import android.content.Context;
32 import android.content.Intent;
33 import android.content.pm.PackageManager;
34 import android.content.pm.ResolveInfo;
35 import android.net.NetworkCapabilities;
36 import android.net.wifi.EAPConstants;
37 import android.net.wifi.IOnWifiUsabilityStatsListener;
38 import android.net.wifi.MloLink;
39 import android.net.wifi.ScanResult;
40 import android.net.wifi.SecurityParams;
41 import android.net.wifi.SoftApCapability;
42 import android.net.wifi.SoftApConfiguration;
43 import android.net.wifi.SoftApInfo;
44 import android.net.wifi.SupplicantState;
45 import android.net.wifi.WifiAnnotations;
46 import android.net.wifi.WifiConfiguration;
47 import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
48 import android.net.wifi.WifiEnterpriseConfig;
49 import android.net.wifi.WifiInfo;
50 import android.net.wifi.WifiManager;
51 import android.net.wifi.WifiManager.DeviceMobilityState;
52 import android.net.wifi.WifiScanner;
53 import android.net.wifi.WifiUsabilityStatsEntry.ProbeStatus;
54 import android.net.wifi.hotspot2.PasspointConfiguration;
55 import android.net.wifi.hotspot2.ProvisioningCallback;
56 import android.net.wifi.hotspot2.ProvisioningCallback.OsuFailure;
57 import android.net.wifi.nl80211.WifiNl80211Manager;
58 import android.net.wifi.util.ScanResultUtil;
59 import android.os.Handler;
60 import android.os.Looper;
61 import android.os.Message;
62 import android.os.Process;
63 import android.os.RemoteCallbackList;
64 import android.os.RemoteException;
65 import android.os.SystemProperties;
66 import android.os.WorkSource;
67 import android.provider.Settings;
68 import android.telephony.TelephonyManager;
69 import android.text.TextUtils;
70 import android.util.ArrayMap;
71 import android.util.ArraySet;
72 import android.util.Base64;
73 import android.util.Log;
74 import android.util.Pair;
75 import android.util.SparseArray;
76 import android.util.SparseBooleanArray;
77 import android.util.SparseIntArray;
78 
79 import com.android.internal.annotations.VisibleForTesting;
80 import com.android.server.wifi.SupplicantStaIfaceHal.StaIfaceReasonCode;
81 import com.android.server.wifi.SupplicantStaIfaceHal.StaIfaceStatusCode;
82 import com.android.server.wifi.aware.WifiAwareMetrics;
83 import com.android.server.wifi.hotspot2.ANQPNetworkKey;
84 import com.android.server.wifi.hotspot2.NetworkDetail;
85 import com.android.server.wifi.hotspot2.PasspointManager;
86 import com.android.server.wifi.hotspot2.PasspointMatch;
87 import com.android.server.wifi.hotspot2.PasspointProvider;
88 import com.android.server.wifi.hotspot2.Utils;
89 import com.android.server.wifi.p2p.WifiP2pMetrics;
90 import com.android.server.wifi.proto.WifiStatsLog;
91 import com.android.server.wifi.proto.nano.WifiMetricsProto;
92 import com.android.server.wifi.proto.nano.WifiMetricsProto.ConnectToNetworkNotificationAndActionCount;
93 import com.android.server.wifi.proto.nano.WifiMetricsProto.ContentionTimeStats;
94 import com.android.server.wifi.proto.nano.WifiMetricsProto.DeviceMobilityStatePnoScanStats;
95 import com.android.server.wifi.proto.nano.WifiMetricsProto.ExperimentValues;
96 import com.android.server.wifi.proto.nano.WifiMetricsProto.FirstConnectAfterBootStats;
97 import com.android.server.wifi.proto.nano.WifiMetricsProto.FirstConnectAfterBootStats.Attempt;
98 import com.android.server.wifi.proto.nano.WifiMetricsProto.HealthMonitorMetrics;
99 import com.android.server.wifi.proto.nano.WifiMetricsProto.InitPartialScanStats;
100 import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats;
101 import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.ExperimentProbeCounts;
102 import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.LinkProbeFailureReasonCount;
103 import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkSpeedCount;
104 import com.android.server.wifi.proto.nano.WifiMetricsProto.MeteredNetworkStats;
105 import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkDisableReason;
106 import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkSelectionExperimentDecisions;
107 import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProfileTypeCount;
108 import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProvisionStats;
109 import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProvisionStats.ProvisionFailureCount;
110 import com.android.server.wifi.proto.nano.WifiMetricsProto.PnoScanMetrics;
111 import com.android.server.wifi.proto.nano.WifiMetricsProto.RadioStats;
112 import com.android.server.wifi.proto.nano.WifiMetricsProto.RateStats;
113 import com.android.server.wifi.proto.nano.WifiMetricsProto.SoftApConnectedClientsEvent;
114 import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent;
115 import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent.ConfigInfo;
116 import com.android.server.wifi.proto.nano.WifiMetricsProto.TargetNetworkInfo;
117 import com.android.server.wifi.proto.nano.WifiMetricsProto.UserActionEvent;
118 import com.android.server.wifi.proto.nano.WifiMetricsProto.UserReactionToApprovalUiEvent;
119 import com.android.server.wifi.proto.nano.WifiMetricsProto.UserReactionToApprovalUiEvent.UserReaction;
120 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent;
121 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiLinkLayerUsageStats;
122 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiLockStats;
123 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiNetworkRequestApiLog;
124 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiNetworkSuggestionApiLog;
125 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiNetworkSuggestionApiLog.SuggestionAppCount;
126 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiStatus;
127 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiToWifiSwitchStats;
128 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiToggleStats;
129 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats;
130 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStatsEntry;
131 import com.android.server.wifi.rtt.RttMetrics;
132 import com.android.server.wifi.scanner.KnownBandsChannelHelper;
133 import com.android.server.wifi.util.InformationElementUtil;
134 import com.android.server.wifi.util.InformationElementUtil.ApType6GHz;
135 import com.android.server.wifi.util.InformationElementUtil.WifiMode;
136 import com.android.server.wifi.util.IntCounter;
137 import com.android.server.wifi.util.IntHistogram;
138 import com.android.server.wifi.util.MetricsUtils;
139 import com.android.server.wifi.util.ObjectCounter;
140 import com.android.server.wifi.util.StringUtil;
141 import com.android.wifi.resources.R;
142 
143 import org.json.JSONArray;
144 import org.json.JSONException;
145 import org.json.JSONObject;
146 
147 import java.io.FileDescriptor;
148 import java.io.PrintWriter;
149 import java.time.Duration;
150 import java.util.ArrayDeque;
151 import java.util.ArrayList;
152 import java.util.Arrays;
153 import java.util.BitSet;
154 import java.util.Calendar;
155 import java.util.Deque;
156 import java.util.HashMap;
157 import java.util.HashSet;
158 import java.util.LinkedList;
159 import java.util.List;
160 import java.util.Map;
161 import java.util.Random;
162 import java.util.Set;
163 
164 /**
165  * Provides storage for wireless connectivity metrics, as they are generated.
166  * Metrics logged by this class include:
167  *   Aggregated connection stats (num of connections, num of failures, ...)
168  *   Discrete connection event stats (time, duration, failure codes, ...)
169  *   Router details (technology type, authentication type, ...)
170  *   Scan stats
171  */
172 public class WifiMetrics {
173     private static final String TAG = "WifiMetrics";
174     private static final boolean DBG = false;
175 
176     /**
177      * Clamp the RSSI poll counts to values between [MIN,MAX]_RSSI_POLL
178      */
179     private static final int MAX_RSSI_POLL = 0;
180     private static final int MIN_RSSI_POLL = -127;
181     public static final int MAX_RSSI_DELTA = 127;
182     public static final int MIN_RSSI_DELTA = -127;
183     /** Minimum link speed (Mbps) to count for link_speed_counts */
184     public static final int MIN_LINK_SPEED_MBPS = 0;
185     /** Maximum time period between ScanResult and RSSI poll to generate rssi delta datapoint */
186     public static final long TIMEOUT_RSSI_DELTA_MILLIS =  3000;
187     private static final int MIN_WIFI_SCORE = 0;
188     private static final int MAX_WIFI_SCORE = ConnectedScore.WIFI_MAX_SCORE;
189     private static final int MIN_WIFI_USABILITY_SCORE = 0; // inclusive
190     private static final int MAX_WIFI_USABILITY_SCORE = 100; // inclusive
191     @VisibleForTesting
192     static final int LOW_WIFI_SCORE = 50; // Mobile data score
193     @VisibleForTesting
194     static final int LOW_WIFI_USABILITY_SCORE = 50; // Mobile data score
195     private final Object mLock = new Object();
196     private static final int MAX_CONNECTION_EVENTS = 256;
197     // Largest bucket in the NumConnectableNetworkCount histogram,
198     // anything large will be stored in this bucket
199     public static final int MAX_CONNECTABLE_SSID_NETWORK_BUCKET = 20;
200     public static final int MAX_CONNECTABLE_BSSID_NETWORK_BUCKET = 50;
201     public static final int MAX_TOTAL_SCAN_RESULT_SSIDS_BUCKET = 100;
202     public static final int MAX_TOTAL_SCAN_RESULTS_BUCKET = 250;
203     public static final int MAX_TOTAL_PASSPOINT_APS_BUCKET = 50;
204     public static final int MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET = 20;
205     public static final int MAX_PASSPOINT_APS_PER_UNIQUE_ESS_BUCKET = 50;
206     public static final int MAX_TOTAL_80211MC_APS_BUCKET = 20;
207     private static final int CONNECT_TO_NETWORK_NOTIFICATION_ACTION_KEY_MULTIPLIER = 1000;
208     // Max limit for number of soft AP related events, extra events will be dropped.
209     private static final int MAX_NUM_SOFT_AP_EVENTS = 256;
210     // Maximum number of WifiIsUnusableEvent
211     public static final int MAX_UNUSABLE_EVENTS = 20;
212     // Minimum time wait before generating next WifiIsUnusableEvent from data stall
213     public static final int MIN_DATA_STALL_WAIT_MS = 120 * 1000; // 2 minutes
214     // Max number of WifiUsabilityStatsEntry elements to store in the ringbuffer.
215     public static final int MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE = 40;
216     // Max number of WifiUsabilityStats elements to store for each type.
217     public static final int MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE = 10;
218     // Max number of WifiUsabilityStats per labeled type to upload to server
219     public static final int MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD = 2;
220     public static final int NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD = 100;
221     public static final int MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS = 1000 * 3600; // 1 hour
222     public static final int PASSPOINT_DEAUTH_IMMINENT_SCOPE_ESS = 0;
223     public static final int PASSPOINT_DEAUTH_IMMINENT_SCOPE_BSS = 1;
224     public static final int COUNTRY_CODE_CONFLICT_WIFI_SCAN = -1;
225     public static final int COUNTRY_CODE_CONFLICT_WIFI_SCAN_TELEPHONY = -2;
226     public static final int MAX_COUNTRY_CODE_COUNT = 4;
227     // Histogram for WifiConfigStore IO duration times. Indicates the following 5 buckets (in ms):
228     //   < 50
229     //   [50, 100)
230     //   [100, 150)
231     //   [150, 200)
232     //   [200, 300)
233     //   >= 300
234     private static final int[] WIFI_CONFIG_STORE_IO_DURATION_BUCKET_RANGES_MS =
235             {50, 100, 150, 200, 300};
236     // Minimum time wait before generating a LABEL_GOOD stats after score breaching low.
237     public static final int MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS = 60 * 1000; // 1 minute
238     // Maximum time that a score breaching low event stays valid.
239     public static final int VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS = 90 * 1000; // 1.5 minutes
240 
241     private static final int WIFI_RECONNECT_DURATION_SHORT_MILLIS = 10 * 1000;
242     private static final int WIFI_RECONNECT_DURATION_MEDIUM_MILLIS = 60 * 1000;
243     // Number of WME Access Categories
244     private static final int NUM_WME_ACCESS_CATEGORIES = 4;
245     private static final int MBB_LINGERING_DURATION_MAX_SECONDS = 30;
246 
247     private Clock mClock;
248     private boolean mScreenOn;
249     private int mWifiState;
250     private WifiAwareMetrics mWifiAwareMetrics;
251     private RttMetrics mRttMetrics;
252     private final PnoScanMetrics mPnoScanMetrics = new PnoScanMetrics();
253     private final WifiLinkLayerUsageStats mWifiLinkLayerUsageStats = new WifiLinkLayerUsageStats();
254     /** Mapping of radio id values to RadioStats objects. */
255     private final SparseArray<RadioStats> mRadioStats = new SparseArray<>();
256     private final ExperimentValues mExperimentValues = new ExperimentValues();
257     private Handler mHandler;
258     private ScoringParams mScoringParams;
259     private WifiConfigManager mWifiConfigManager;
260     private WifiBlocklistMonitor mWifiBlocklistMonitor;
261     private WifiNetworkSelector mWifiNetworkSelector;
262     private PasspointManager mPasspointManager;
263     private Context mContext;
264     private FrameworkFacade mFacade;
265     private WifiDataStall mWifiDataStall;
266     private WifiLinkLayerStats mLastLinkLayerStats;
267     private WifiHealthMonitor mWifiHealthMonitor;
268     private WifiScoreCard mWifiScoreCard;
269     private SessionData mPreviousSession;
270     private SessionData mCurrentSession;
271     private String mLastBssid;
272     private int mLastFrequency = -1;
273     private int mSeqNumInsideFramework = 0;
274     private int mLastWifiUsabilityScore = -1;
275     private int mLastWifiUsabilityScoreNoReset = -1;
276     private int mLastPredictionHorizonSec = -1;
277     private int mLastPredictionHorizonSecNoReset = -1;
278     private int mSeqNumToFramework = -1;
279     @ProbeStatus private int mProbeStatusSinceLastUpdate =
280             android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE;
281     private int mProbeElapsedTimeSinceLastUpdateMs = -1;
282     private int mProbeMcsRateSinceLastUpdate = -1;
283     private long mScoreBreachLowTimeMillis = -1;
284 
285     public static final int MAX_STA_EVENTS = 768;
286     @VisibleForTesting static final int MAX_USER_ACTION_EVENTS = 200;
287     private LinkedList<StaEventWithTime> mStaEventList = new LinkedList<>();
288     private LinkedList<UserActionEventWithTime> mUserActionEventList = new LinkedList<>();
289     private WifiStatusBuilder mWifiStatusBuilder = new WifiStatusBuilder();
290     private int mLastPollRssi = -127;
291     private int mLastPollLinkSpeed = -1;
292     private int mLastPollRxLinkSpeed = -1;
293     private int mLastPollFreq = -1;
294     private int mLastScore = -1;
295     private boolean mAdaptiveConnectivityEnabled = true;
296     private ScanMetrics mScanMetrics;
297     private WifiChannelUtilization mWifiChannelUtilization;
298     private WifiSettingsStore mWifiSettingsStore;
299     private IntCounter mPasspointDeauthImminentScope = new IntCounter();
300     private IntCounter mRecentFailureAssociationStatus = new IntCounter();
301     private boolean mFirstConnectionAfterBoot = true;
302     private long mLastTotalBeaconRx = 0;
303     private int mScorerUid = Process.WIFI_UID;
304 
305     /**
306      * Wi-Fi usability state per interface as predicted by the network scorer.
307      */
308     public enum WifiUsabilityState {UNKNOWN, USABLE, UNUSABLE};
309     private final Map<String, WifiUsabilityState> mWifiUsabilityStatePerIface = new ArrayMap<>();
310 
311     /**
312      * Metrics are stored within an instance of the WifiLog proto during runtime,
313      * The ConnectionEvent, SystemStateEntries & ScanReturnEntries metrics are stored during
314      * runtime in member lists of this WifiMetrics class, with the final WifiLog proto being pieced
315      * together at dump-time
316      */
317     private final WifiMetricsProto.WifiLog mWifiLogProto = new WifiMetricsProto.WifiLog();
318     /**
319      * Session information that gets logged for every Wifi connection attempt.
320      */
321     private final Deque<ConnectionEvent> mConnectionEventList = new ArrayDeque<>();
322     /**
323      * The latest started (but un-ended) connection attempt per interface.
324      */
325     private final Map<String, ConnectionEvent> mCurrentConnectionEventPerIface = new ArrayMap<>();
326     /**
327      * Count of number of times each scan return code, indexed by WifiLog.ScanReturnCode
328      */
329     private final SparseIntArray mScanReturnEntries = new SparseIntArray();
330     /**
331      * Mapping of system state to the counts of scans requested in that wifi state * screenOn
332      * combination. Indexed by WifiLog.WifiState * (1 + screenOn)
333      */
334     private final SparseIntArray mWifiSystemStateEntries = new SparseIntArray();
335     /** Mapping of channel frequency to its RSSI distribution histogram **/
336     private final Map<Integer, SparseIntArray> mRssiPollCountsMap = new HashMap<>();
337     /** Mapping of RSSI scan-poll delta values to counts. */
338     private final SparseIntArray mRssiDeltaCounts = new SparseIntArray();
339     /** Mapping of link speed values to LinkSpeedCount objects. */
340     private final SparseArray<LinkSpeedCount> mLinkSpeedCounts = new SparseArray<>();
341 
342     private final IntCounter mTxLinkSpeedCount2g = new IntCounter();
343     private final IntCounter mTxLinkSpeedCount5gLow = new IntCounter();
344     private final IntCounter mTxLinkSpeedCount5gMid = new IntCounter();
345     private final IntCounter mTxLinkSpeedCount5gHigh = new IntCounter();
346     private final IntCounter mTxLinkSpeedCount6gLow = new IntCounter();
347     private final IntCounter mTxLinkSpeedCount6gMid = new IntCounter();
348     private final IntCounter mTxLinkSpeedCount6gHigh = new IntCounter();
349 
350     private final IntCounter mRxLinkSpeedCount2g = new IntCounter();
351     private final IntCounter mRxLinkSpeedCount5gLow = new IntCounter();
352     private final IntCounter mRxLinkSpeedCount5gMid = new IntCounter();
353     private final IntCounter mRxLinkSpeedCount5gHigh = new IntCounter();
354     private final IntCounter mRxLinkSpeedCount6gLow = new IntCounter();
355     private final IntCounter mRxLinkSpeedCount6gMid = new IntCounter();
356     private final IntCounter mRxLinkSpeedCount6gHigh = new IntCounter();
357 
358     private final IntCounter mMakeBeforeBreakLingeringDurationSeconds = new IntCounter();
359 
360     /** RSSI of the scan result for the last connection event*/
361     private int mScanResultRssi = 0;
362     /** Boot-relative timestamp when the last candidate scanresult was received, used to calculate
363         RSSI deltas. -1 designates no candidate scanResult being tracked */
364     private long mScanResultRssiTimestampMillis = -1;
365     /** Mapping of alert reason to the respective alert count. */
366     private final SparseIntArray mWifiAlertReasonCounts = new SparseIntArray();
367     /**
368      * Records the getElapsedSinceBootMillis (in seconds) that represents the beginning of data
369      * capture for for this WifiMetricsProto
370      */
371     private long mRecordStartTimeSec;
372     /** Mapping of Wifi Scores to counts */
373     private final SparseIntArray mWifiScoreCounts = new SparseIntArray();
374     /** Mapping of Wifi Usability Scores to counts */
375     private final SparseIntArray mWifiUsabilityScoreCounts = new SparseIntArray();
376     /** Mapping of SoftApManager start SoftAp return codes to counts */
377     private final SparseIntArray mSoftApManagerReturnCodeCounts = new SparseIntArray();
378 
379     private final SparseIntArray mTotalSsidsInScanHistogram = new SparseIntArray();
380     private final SparseIntArray mTotalBssidsInScanHistogram = new SparseIntArray();
381     private final SparseIntArray mAvailableOpenSsidsInScanHistogram = new SparseIntArray();
382     private final SparseIntArray mAvailableOpenBssidsInScanHistogram = new SparseIntArray();
383     private final SparseIntArray mAvailableSavedSsidsInScanHistogram = new SparseIntArray();
384     private final SparseIntArray mAvailableSavedBssidsInScanHistogram = new SparseIntArray();
385     private final SparseIntArray mAvailableOpenOrSavedSsidsInScanHistogram = new SparseIntArray();
386     private final SparseIntArray mAvailableOpenOrSavedBssidsInScanHistogram = new SparseIntArray();
387     private final SparseIntArray mAvailableSavedPasspointProviderProfilesInScanHistogram =
388             new SparseIntArray();
389     private final SparseIntArray mAvailableSavedPasspointProviderBssidsInScanHistogram =
390             new SparseIntArray();
391 
392     private final IntCounter mInstalledPasspointProfileTypeForR1 = new IntCounter();
393     private final IntCounter mInstalledPasspointProfileTypeForR2 = new IntCounter();
394 
395     /** Mapping of "Connect to Network" notifications to counts. */
396     private final SparseIntArray mConnectToNetworkNotificationCount = new SparseIntArray();
397     /** Mapping of "Connect to Network" notification user actions to counts. */
398     private final SparseIntArray mConnectToNetworkNotificationActionCount = new SparseIntArray();
399     private int mOpenNetworkRecommenderBlocklistSize = 0;
400     private boolean mIsWifiNetworksAvailableNotificationOn = false;
401     private int mNumOpenNetworkConnectMessageFailedToSend = 0;
402     private int mNumOpenNetworkRecommendationUpdates = 0;
403     /** List of soft AP events related to number of connected clients in tethered mode */
404     private final List<SoftApConnectedClientsEvent> mSoftApEventListTethered = new ArrayList<>();
405     /** List of soft AP events related to number of connected clients in local only mode */
406     private final List<SoftApConnectedClientsEvent> mSoftApEventListLocalOnly = new ArrayList<>();
407 
408     private final SparseIntArray mObservedHotspotR1ApInScanHistogram = new SparseIntArray();
409     private final SparseIntArray mObservedHotspotR2ApInScanHistogram = new SparseIntArray();
410     private final SparseIntArray mObservedHotspotR3ApInScanHistogram = new SparseIntArray();
411     private final SparseIntArray mObservedHotspotR1EssInScanHistogram = new SparseIntArray();
412     private final SparseIntArray mObservedHotspotR2EssInScanHistogram = new SparseIntArray();
413     private final SparseIntArray mObservedHotspotR3EssInScanHistogram = new SparseIntArray();
414     private final SparseIntArray mObservedHotspotR1ApsPerEssInScanHistogram = new SparseIntArray();
415     private final SparseIntArray mObservedHotspotR2ApsPerEssInScanHistogram = new SparseIntArray();
416     private final SparseIntArray mObservedHotspotR3ApsPerEssInScanHistogram = new SparseIntArray();
417 
418     private final SparseIntArray mObserved80211mcApInScanHistogram = new SparseIntArray();
419 
420     // link probing stats
421     private final IntCounter mLinkProbeSuccessRssiCounts = new IntCounter(-85, -65);
422     private final IntCounter mLinkProbeFailureRssiCounts = new IntCounter(-85, -65);
423     private final IntCounter mLinkProbeSuccessLinkSpeedCounts = new IntCounter();
424     private final IntCounter mLinkProbeFailureLinkSpeedCounts = new IntCounter();
425 
426     private static final int[] LINK_PROBE_TIME_SINCE_LAST_TX_SUCCESS_SECONDS_HISTOGRAM_BUCKETS =
427             {5, 15, 45, 135};
428     private final IntHistogram mLinkProbeSuccessSecondsSinceLastTxSuccessHistogram =
429             new IntHistogram(LINK_PROBE_TIME_SINCE_LAST_TX_SUCCESS_SECONDS_HISTOGRAM_BUCKETS);
430     private final IntHistogram mLinkProbeFailureSecondsSinceLastTxSuccessHistogram =
431             new IntHistogram(LINK_PROBE_TIME_SINCE_LAST_TX_SUCCESS_SECONDS_HISTOGRAM_BUCKETS);
432 
433     private static final int[] LINK_PROBE_ELAPSED_TIME_MS_HISTOGRAM_BUCKETS =
434             {5, 10, 15, 20, 25, 50, 100, 200, 400, 800};
435     private final IntHistogram mLinkProbeSuccessElapsedTimeMsHistogram = new IntHistogram(
436             LINK_PROBE_ELAPSED_TIME_MS_HISTOGRAM_BUCKETS);
437     private final IntCounter mLinkProbeFailureReasonCounts = new IntCounter();
438     private final MeteredNetworkStatsBuilder mMeteredNetworkStatsBuilder =
439             new MeteredNetworkStatsBuilder();
440 
441     /**
442      * Maps a String link probe experiment ID to the number of link probes that were sent for this
443      * experiment.
444      */
445     private final ObjectCounter<String> mLinkProbeExperimentProbeCounts = new ObjectCounter<>();
446     private int mLinkProbeStaEventCount = 0;
447     @VisibleForTesting static final int MAX_LINK_PROBE_STA_EVENTS = MAX_STA_EVENTS / 4;
448 
449     private final LinkedList<WifiUsabilityStatsEntry> mWifiUsabilityStatsEntriesList =
450             new LinkedList<>();
451     private final LinkedList<WifiUsabilityStats> mWifiUsabilityStatsListBad = new LinkedList<>();
452     private final LinkedList<WifiUsabilityStats> mWifiUsabilityStatsListGood = new LinkedList<>();
453     private int mWifiUsabilityStatsCounter = 0;
454     private final Random mRand = new Random();
455     private final RemoteCallbackList<IOnWifiUsabilityStatsListener> mOnWifiUsabilityListeners;
456 
457     private final SparseArray<DeviceMobilityStatePnoScanStats> mMobilityStatePnoStatsMap =
458             new SparseArray<>();
459     private int mCurrentDeviceMobilityState;
460     /**
461      * The timestamp of the start of the current device mobility state.
462      */
463     private long mCurrentDeviceMobilityStateStartMs;
464     /**
465      * The timestamp of when the PNO scan started in the current device mobility state.
466      */
467     private long mCurrentDeviceMobilityStatePnoScanStartMs;
468 
469     /** Wifi power metrics*/
470     private WifiPowerMetrics mWifiPowerMetrics;
471 
472     /** Wifi Wake metrics */
473     private final WifiWakeMetrics mWifiWakeMetrics = new WifiWakeMetrics();
474 
475     /** Wifi P2p metrics */
476     private final WifiP2pMetrics mWifiP2pMetrics;
477 
478     /** DPP */
479     private final DppMetrics mDppMetrics;
480 
481     private final WifiMonitor mWifiMonitor;
482     private ActiveModeWarden mActiveModeWarden;
483     private final Map<String, ActiveModeManager.ClientRole> mIfaceToRoleMap = new ArrayMap<>();
484 
485     /** WifiConfigStore read duration histogram. */
486     private SparseIntArray mWifiConfigStoreReadDurationHistogram = new SparseIntArray();
487 
488     /** WifiConfigStore write duration histogram. */
489     private SparseIntArray mWifiConfigStoreWriteDurationHistogram = new SparseIntArray();
490 
491     /** New  API surface metrics */
492     private final WifiNetworkRequestApiLog mWifiNetworkRequestApiLog =
493             new WifiNetworkRequestApiLog();
494     private static final int[] NETWORK_REQUEST_API_MATCH_SIZE_HISTOGRAM_BUCKETS =
495             {0, 1, 5, 10};
496     private final IntHistogram mWifiNetworkRequestApiMatchSizeHistogram =
497             new IntHistogram(NETWORK_REQUEST_API_MATCH_SIZE_HISTOGRAM_BUCKETS);
498 
499     private static final int[] NETWORK_REQUEST_API_DURATION_SEC_BUCKETS =
500             {0, toIntExact(Duration.ofMinutes(3).getSeconds()),
501                     toIntExact(Duration.ofMinutes(10).getSeconds()),
502                     toIntExact(Duration.ofMinutes(30).getSeconds()),
503                     toIntExact(Duration.ofHours(1).getSeconds()),
504                     toIntExact(Duration.ofHours(6).getSeconds())};
505     private final IntHistogram mWifiNetworkRequestApiConnectionDurationSecOnPrimaryIfaceHistogram =
506             new IntHistogram(NETWORK_REQUEST_API_DURATION_SEC_BUCKETS);
507     private final IntHistogram
508             mWifiNetworkRequestApiConnectionDurationSecOnSecondaryIfaceHistogram =
509             new IntHistogram(NETWORK_REQUEST_API_DURATION_SEC_BUCKETS);
510     private final IntHistogram mWifiNetworkRequestApiConcurrentConnectionDurationSecHistogram =
511             new IntHistogram(NETWORK_REQUEST_API_DURATION_SEC_BUCKETS);
512 
513     private final WifiNetworkSuggestionApiLog mWifiNetworkSuggestionApiLog =
514             new WifiNetworkSuggestionApiLog();
515     private static final int[] NETWORK_SUGGESTION_API_LIST_SIZE_HISTOGRAM_BUCKETS =
516             {5, 20, 50, 100, 500};
517     private final IntHistogram mWifiNetworkSuggestionApiListSizeHistogram =
518             new IntHistogram(NETWORK_SUGGESTION_API_LIST_SIZE_HISTOGRAM_BUCKETS);
519     private final IntCounter mWifiNetworkSuggestionApiAppTypeCounter = new IntCounter();
520     private final List<UserReaction> mUserApprovalSuggestionAppUiReactionList =
521             new ArrayList<>();
522     private final List<UserReaction> mUserApprovalCarrierUiReactionList =
523             new ArrayList<>();
524     private final SparseBooleanArray mWifiNetworkSuggestionPriorityGroups =
525             new SparseBooleanArray();
526     private final Set<String> mWifiNetworkSuggestionCoexistSavedNetworks = new ArraySet<>();
527 
528     private final WifiLockStats mWifiLockStats = new WifiLockStats();
529     private static final int[] WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS =
530             {1, 10, 60, 600, 3600};
531     private final WifiToggleStats mWifiToggleStats = new WifiToggleStats();
532     private BssidBlocklistStats mBssidBlocklistStats = new BssidBlocklistStats();
533 
534     private final IntHistogram mWifiLockHighPerfAcqDurationSecHistogram =
535             new IntHistogram(WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS);
536     private final IntHistogram mWifiLockLowLatencyAcqDurationSecHistogram =
537             new IntHistogram(WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS);
538 
539     private final IntHistogram mWifiLockHighPerfActiveSessionDurationSecHistogram =
540             new IntHistogram(WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS);
541     private final IntHistogram mWifiLockLowLatencyActiveSessionDurationSecHistogram =
542             new IntHistogram(WIFI_LOCK_SESSION_DURATION_HISTOGRAM_BUCKETS);
543 
544     /**
545      * (experiment1Id, experiment2Id) =>
546      *     (sameSelectionNumChoicesCounter, differentSelectionNumChoicesCounter)
547      */
548     private Map<Pair<Integer, Integer>, NetworkSelectionExperimentResults>
549             mNetworkSelectionExperimentPairNumChoicesCounts = new ArrayMap<>();
550 
551     private int mNetworkSelectorExperimentId;
552 
553     /**
554      * Tracks the nominator for each network (i.e. which entity made the suggestion to connect).
555      * This object should not be cleared.
556      */
557     private final SparseIntArray mNetworkIdToNominatorId = new SparseIntArray();
558 
559     /** passpoint provision success count */
560     private int mNumProvisionSuccess = 0;
561 
562     /** Mapping of failure code to the respective passpoint provision failure count. */
563     private final IntCounter mPasspointProvisionFailureCounts = new IntCounter();
564 
565     // Connection duration stats collected while link layer stats reports are on
566     private final ConnectionDurationStats mConnectionDurationStats = new ConnectionDurationStats();
567 
568     private static final int[] CHANNEL_UTILIZATION_BUCKETS =
569             {25, 50, 75, 100, 125, 150, 175, 200, 225};
570 
571     private final IntHistogram mChannelUtilizationHistogram2G =
572             new IntHistogram(CHANNEL_UTILIZATION_BUCKETS);
573 
574     private final IntHistogram mChannelUtilizationHistogramAbove2G =
575             new IntHistogram(CHANNEL_UTILIZATION_BUCKETS);
576 
577     private static final int[] THROUGHPUT_MBPS_BUCKETS =
578             {1, 5, 10, 15, 25, 50, 100, 150, 200, 300, 450, 600, 800, 1200, 1600};
579     private final IntHistogram mTxThroughputMbpsHistogram2G =
580             new IntHistogram(THROUGHPUT_MBPS_BUCKETS);
581     private final IntHistogram mRxThroughputMbpsHistogram2G =
582             new IntHistogram(THROUGHPUT_MBPS_BUCKETS);
583     private final IntHistogram mTxThroughputMbpsHistogramAbove2G =
584             new IntHistogram(THROUGHPUT_MBPS_BUCKETS);
585     private final IntHistogram mRxThroughputMbpsHistogramAbove2G =
586             new IntHistogram(THROUGHPUT_MBPS_BUCKETS);
587 
588     // Init partial scan metrics
589     private int mInitPartialScanTotalCount;
590     private int mInitPartialScanSuccessCount;
591     private int mInitPartialScanFailureCount;
592     private static final int[] INIT_PARTIAL_SCAN_HISTOGRAM_BUCKETS =
593             {1, 3, 5, 10};
594     private final IntHistogram mInitPartialScanSuccessHistogram =
595             new IntHistogram(INIT_PARTIAL_SCAN_HISTOGRAM_BUCKETS);
596     private final IntHistogram mInitPartialScanFailureHistogram =
597             new IntHistogram(INIT_PARTIAL_SCAN_HISTOGRAM_BUCKETS);
598 
599     // Wi-Fi off metrics
600     private final WifiOffMetrics mWifiOffMetrics = new WifiOffMetrics();
601 
602     private final SoftApConfigLimitationMetrics mSoftApConfigLimitationMetrics =
603             new SoftApConfigLimitationMetrics();
604 
605     private final CarrierWifiMetrics mCarrierWifiMetrics =
606             new CarrierWifiMetrics();
607 
608     @Nullable
609     private FirstConnectAfterBootStats mFirstConnectAfterBootStats =
610             new FirstConnectAfterBootStats();
611     private boolean mIsFirstConnectionAttemptComplete = false;
612 
613     private final WifiToWifiSwitchStats mWifiToWifiSwitchStats = new WifiToWifiSwitchStats();
614 
615     /** Wi-Fi link specific metrics (MLO). */
616     public static class LinkMetrics {
617         private long mTotalBeaconRx = 0;
618         private @android.net.wifi.WifiUsabilityStatsEntry.LinkState int mLinkUsageState =
619                 android.net.wifi.WifiUsabilityStatsEntry.LINK_STATE_UNKNOWN;
620 
621         /** Get Total beacon received on this link */
getTotalBeaconRx()622         public long getTotalBeaconRx() {
623             return mTotalBeaconRx;
624         }
625 
626         /** Set Total beacon received on this link */
setTotalBeaconRx(long totalBeaconRx)627         public void setTotalBeaconRx(long totalBeaconRx) {
628             this.mTotalBeaconRx = totalBeaconRx;
629         }
630 
631         /** Get link usage state */
getLinkUsageState()632         public @android.net.wifi.WifiUsabilityStatsEntry.LinkState int getLinkUsageState() {
633             return mLinkUsageState;
634         }
635 
636         /** Set link usage state */
setLinkUsageState( @ndroid.net.wifi.WifiUsabilityStatsEntry.LinkState int linkUsageState)637         public void setLinkUsageState(
638                 @android.net.wifi.WifiUsabilityStatsEntry.LinkState int linkUsageState) {
639             this.mLinkUsageState = linkUsageState;
640         }
641     }
642 
643     public SparseArray<LinkMetrics> mLastLinkMetrics = new SparseArray<>();
644 
645     @VisibleForTesting
646     static class NetworkSelectionExperimentResults {
647         public static final int MAX_CHOICES = 10;
648 
649         public IntCounter sameSelectionNumChoicesCounter = new IntCounter(0, MAX_CHOICES);
650         public IntCounter differentSelectionNumChoicesCounter = new IntCounter(0, MAX_CHOICES);
651 
652         @Override
toString()653         public String toString() {
654             return "NetworkSelectionExperimentResults{"
655                     + "sameSelectionNumChoicesCounter="
656                     + sameSelectionNumChoicesCounter
657                     + ", differentSelectionNumChoicesCounter="
658                     + differentSelectionNumChoicesCounter
659                     + '}';
660         }
661     }
662 
663     private static class SessionData {
664         private String mSsid;
665         private long mSessionStartTimeMillis;
666         private long mSessionEndTimeMillis;
667         private int mBand;
668         private int mAuthType;
669         private ConnectionEvent mConnectionEvent;
670         private long mLastRoamCompleteMillis;
671 
SessionData(ConnectionEvent connectionEvent, String ssid, long sessionStartTimeMillis, int band, int authType)672         SessionData(ConnectionEvent connectionEvent, String ssid, long sessionStartTimeMillis,
673                 int band, int authType) {
674             mConnectionEvent = connectionEvent;
675             mSsid = ssid;
676             mSessionStartTimeMillis = sessionStartTimeMillis;
677             mBand = band;
678             mAuthType = authType;
679             mLastRoamCompleteMillis = sessionStartTimeMillis;
680         }
681     }
682 
683     /**
684      * Sets the timestamp after roaming is complete.
685      */
onRoamComplete()686     public void onRoamComplete() {
687         if (mCurrentSession != null) {
688             mCurrentSession.mLastRoamCompleteMillis = mClock.getElapsedSinceBootMillis();
689         }
690     }
691 
692     class RouterFingerPrint {
693         private final WifiMetricsProto.RouterFingerPrint mRouterFingerPrintProto =
694                 new WifiMetricsProto.RouterFingerPrint();
695         // Additional parameters which is not captured in WifiMetricsProto.RouterFingerPrint.
696         private boolean mIsFrameworkInitiatedRoaming = false;
697         private @WifiConfiguration.SecurityType int mSecurityMode =
698                 WifiConfiguration.SECURITY_TYPE_OPEN;
699         private boolean mIsIncorrectlyConfiguredAsHidden = false;
700         private int mWifiStandard = WifiMode.MODE_UNDEFINED;
701         private boolean mIs11bSupported = false;
702         private boolean mIsMboSupported = false;
703         private boolean mIsOceSupported = false;
704         private boolean mIsFilsSupported = false;
705         private boolean mIsIndividualTwtSupported = false;
706         private boolean mIsBroadcastTwtSupported = false;
707         private boolean mIsRestrictedTwtSupported = false;
708         private boolean mIsTwtRequired = false;
709         private boolean mIs11AzSupported = false;
710         private boolean mIs11McSupported = false;
711         private boolean mIsEcpsPriorityAccessSupported = false;
712         private NetworkDetail.HSRelease mHsRelease = NetworkDetail.HSRelease.Unknown;
713         private ApType6GHz mApType6GHz = ApType6GHz.AP_TYPE_6GHZ_UNKNOWN;
714         public @WifiAnnotations.ChannelWidth int mChannelWidth = ScanResult.UNSPECIFIED;
715 
toString()716         public String toString() {
717             StringBuilder sb = new StringBuilder();
718             synchronized (mLock) {
719                 sb.append("mConnectionEvent.roamType=" + mRouterFingerPrintProto.roamType);
720                 sb.append(", mChannelInfo=" + mRouterFingerPrintProto.channelInfo);
721                 sb.append(", mDtim=" + mRouterFingerPrintProto.dtim);
722                 sb.append(", mAuthentication=" + mRouterFingerPrintProto.authentication);
723                 sb.append(", mHidden=" + mRouterFingerPrintProto.hidden);
724                 sb.append(", mRouterTechnology=" + mRouterFingerPrintProto.routerTechnology);
725                 sb.append(", mSupportsIpv6=" + mRouterFingerPrintProto.supportsIpv6);
726                 sb.append(", mEapMethod=" + mRouterFingerPrintProto.eapMethod);
727                 sb.append(", mAuthPhase2Method=" + mRouterFingerPrintProto.authPhase2Method);
728                 sb.append(", mOcspType=" + mRouterFingerPrintProto.ocspType);
729                 sb.append(", mPmkCache=" + mRouterFingerPrintProto.pmkCacheEnabled);
730                 sb.append(", mMaxSupportedTxLinkSpeedMbps=" + mRouterFingerPrintProto
731                         .maxSupportedTxLinkSpeedMbps);
732                 sb.append(", mMaxSupportedRxLinkSpeedMbps=" + mRouterFingerPrintProto
733                         .maxSupportedRxLinkSpeedMbps);
734                 sb.append(", mIsFrameworkInitiatedRoaming=" + mIsFrameworkInitiatedRoaming);
735                 sb.append(", mIsIncorrectlyConfiguredAsHidden=" + mIsIncorrectlyConfiguredAsHidden);
736                 sb.append(", mWifiStandard=" + mWifiStandard);
737                 sb.append(", mIs11bSupported=" + mIs11bSupported);
738                 sb.append(", mIsMboSupported=" + mIsMboSupported);
739                 sb.append(", mIsOceSupported=" + mIsOceSupported);
740                 sb.append(", mIsFilsSupported=" + mIsFilsSupported);
741                 sb.append(", mIsIndividualTwtSupported=" + mIsIndividualTwtSupported);
742                 sb.append(", mIsBroadcastTwtSupported=" + mIsBroadcastTwtSupported);
743                 sb.append(", mIsRestrictedTwtSupported=" + mIsRestrictedTwtSupported);
744                 sb.append(", mIsTwtRequired=" + mIsTwtRequired);
745                 sb.append(", mIs11mcSupported=" + mIs11McSupported);
746                 sb.append(", mIs11azSupported=" + mIs11AzSupported);
747                 sb.append(", mApType6Ghz=" + mApType6GHz);
748                 sb.append(", mIsEcpsPriorityAccessSupported=" + mIsEcpsPriorityAccessSupported);
749                 sb.append(", mHsRelease=" + mHsRelease);
750                 sb.append(", mChannelWidth" + mChannelWidth);
751             }
752             return sb.toString();
753         }
754 
setPmkCache(boolean isEnabled)755         public void setPmkCache(boolean isEnabled) {
756             synchronized (mLock) {
757                 mRouterFingerPrintProto.pmkCacheEnabled = isEnabled;
758             }
759         }
760 
setMaxSupportedLinkSpeedMbps(int maxSupportedTxLinkSpeedMbps, int maxSupportedRxLinkSpeedMbps)761         public void setMaxSupportedLinkSpeedMbps(int maxSupportedTxLinkSpeedMbps,
762                 int maxSupportedRxLinkSpeedMbps) {
763             synchronized (mLock) {
764                 mRouterFingerPrintProto.maxSupportedTxLinkSpeedMbps = maxSupportedTxLinkSpeedMbps;
765                 mRouterFingerPrintProto.maxSupportedRxLinkSpeedMbps = maxSupportedRxLinkSpeedMbps;
766             }
767         }
768     }
getEapMethodProto(int eapMethod)769     private int getEapMethodProto(int eapMethod) {
770         switch (eapMethod) {
771             case WifiEnterpriseConfig.Eap.WAPI_CERT:
772                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_WAPI_CERT;
773             case WifiEnterpriseConfig.Eap.TLS:
774                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_TLS;
775             case WifiEnterpriseConfig.Eap.UNAUTH_TLS:
776                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_UNAUTH_TLS;
777             case WifiEnterpriseConfig.Eap.PEAP:
778                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_PEAP;
779             case WifiEnterpriseConfig.Eap.PWD:
780                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_PWD;
781             case WifiEnterpriseConfig.Eap.TTLS:
782                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_TTLS;
783             case WifiEnterpriseConfig.Eap.SIM:
784                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_SIM;
785             case WifiEnterpriseConfig.Eap.AKA:
786                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_AKA;
787             case WifiEnterpriseConfig.Eap.AKA_PRIME:
788                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_AKA_PRIME;
789             default:
790                 return WifiMetricsProto.RouterFingerPrint.TYPE_EAP_UNKNOWN;
791         }
792     }
793 
getAuthPhase2MethodProto(int phase2Method)794     private static int getAuthPhase2MethodProto(int phase2Method) {
795         switch (phase2Method) {
796             case WifiEnterpriseConfig.Phase2.PAP:
797                 return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_PAP;
798             case WifiEnterpriseConfig.Phase2.MSCHAP:
799                 return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_MSCHAP;
800             case WifiEnterpriseConfig.Phase2.MSCHAPV2:
801                 return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_MSCHAPV2;
802             case WifiEnterpriseConfig.Phase2.GTC:
803                 return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_GTC;
804             case WifiEnterpriseConfig.Phase2.SIM:
805                 return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_SIM;
806             case WifiEnterpriseConfig.Phase2.AKA:
807                 return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_AKA;
808             case WifiEnterpriseConfig.Phase2.AKA_PRIME:
809                 return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_AKA_PRIME;
810             default:
811                 return WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_NONE;
812         }
813     }
814 
getOcspTypeProto(int ocspType)815     private int getOcspTypeProto(int ocspType) {
816         switch (ocspType) {
817             case WifiEnterpriseConfig.OCSP_NONE:
818                 return WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_NONE;
819             case WifiEnterpriseConfig.OCSP_REQUEST_CERT_STATUS:
820                 return WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_REQUEST_CERT_STATUS;
821             case WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS:
822                 return WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_REQUIRE_CERT_STATUS;
823             case WifiEnterpriseConfig.OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS:
824                 return WifiMetricsProto.RouterFingerPrint
825                         .TYPE_OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS;
826             default:
827                 return WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_NONE;
828         }
829     }
830 
831     class BssidBlocklistStats {
832         public IntCounter networkSelectionFilteredBssidCount = new IntCounter();
833         public int numHighMovementConnectionSkipped = 0;
834         public int numHighMovementConnectionStarted = 0;
835         private final IntCounter mBlockedBssidPerReasonCount = new IntCounter();
836         private final IntCounter mBlockedConfigurationPerReasonCount = new IntCounter();
837 
toProto()838         public WifiMetricsProto.BssidBlocklistStats toProto() {
839             WifiMetricsProto.BssidBlocklistStats proto = new WifiMetricsProto.BssidBlocklistStats();
840             proto.networkSelectionFilteredBssidCount = networkSelectionFilteredBssidCount.toProto();
841             proto.highMovementMultipleScansFeatureEnabled = mContext.getResources().getBoolean(
842                     R.bool.config_wifiHighMovementNetworkSelectionOptimizationEnabled);
843             proto.numHighMovementConnectionSkipped = numHighMovementConnectionSkipped;
844             proto.numHighMovementConnectionStarted = numHighMovementConnectionStarted;
845             proto.bssidBlocklistPerReasonCount = mBlockedBssidPerReasonCount.toProto();
846             proto.wifiConfigBlocklistPerReasonCount = mBlockedConfigurationPerReasonCount.toProto();
847             return proto;
848         }
849 
incrementBssidBlocklistCount(int blockReason)850         public void incrementBssidBlocklistCount(int blockReason) {
851             mBlockedBssidPerReasonCount.increment(blockReason);
852         }
853 
incrementWificonfigurationBlocklistCount(int blockReason)854         public void incrementWificonfigurationBlocklistCount(int blockReason) {
855             mBlockedConfigurationPerReasonCount.increment(blockReason);
856         }
857 
858         @Override
toString()859         public String toString() {
860             StringBuilder sb = new StringBuilder();
861             sb.append("networkSelectionFilteredBssidCount=" + networkSelectionFilteredBssidCount);
862             sb.append("\nmBlockedBssidPerReasonCount=" + mBlockedBssidPerReasonCount);
863             sb.append("\nmBlockedConfigurationPerReasonCount="
864                     + mBlockedConfigurationPerReasonCount);
865 
866             sb.append(", highMovementMultipleScansFeatureEnabled="
867                     + mContext.getResources().getBoolean(
868                             R.bool.config_wifiHighMovementNetworkSelectionOptimizationEnabled));
869             sb.append(", numHighMovementConnectionSkipped=" + numHighMovementConnectionSkipped);
870             sb.append(", numHighMovementConnectionStarted=" + numHighMovementConnectionStarted);
871             sb.append(", mBlockedBssidPerReasonCount=" + mBlockedBssidPerReasonCount);
872             sb.append(", mBlockedConfigurationPerReasonCount="
873                     + mBlockedConfigurationPerReasonCount);
874             return sb.toString();
875         }
876     }
877 
878     class ConnectionDurationStats {
879         private int mConnectionDurationCellularDataOffMs;
880         private int mConnectionDurationSufficientThroughputMs;
881         private int mConnectionDurationInSufficientThroughputMs;
882         private int mConnectionDurationInSufficientThroughputDefaultWifiMs;
883 
toProto()884         public WifiMetricsProto.ConnectionDurationStats toProto() {
885             WifiMetricsProto.ConnectionDurationStats proto =
886                     new WifiMetricsProto.ConnectionDurationStats();
887             proto.totalTimeSufficientThroughputMs = mConnectionDurationSufficientThroughputMs;
888             proto.totalTimeInsufficientThroughputMs = mConnectionDurationInSufficientThroughputMs;
889             proto.totalTimeInsufficientThroughputDefaultWifiMs =
890                     mConnectionDurationInSufficientThroughputDefaultWifiMs;
891             proto.totalTimeCellularDataOffMs = mConnectionDurationCellularDataOffMs;
892             return proto;
893         }
clear()894         public void clear() {
895             mConnectionDurationCellularDataOffMs = 0;
896             mConnectionDurationSufficientThroughputMs = 0;
897             mConnectionDurationInSufficientThroughputMs = 0;
898             mConnectionDurationInSufficientThroughputDefaultWifiMs = 0;
899         }
incrementDurationCount(int timeDeltaLastTwoPollsMs, boolean isThroughputSufficient, boolean isCellularDataAvailable, boolean isDefaultOnWifi)900         public void incrementDurationCount(int timeDeltaLastTwoPollsMs,
901                 boolean isThroughputSufficient, boolean isCellularDataAvailable,
902                 boolean isDefaultOnWifi) {
903             if (!isCellularDataAvailable) {
904                 mConnectionDurationCellularDataOffMs += timeDeltaLastTwoPollsMs;
905             } else {
906                 if (isThroughputSufficient) {
907                     mConnectionDurationSufficientThroughputMs += timeDeltaLastTwoPollsMs;
908                 } else {
909                     mConnectionDurationInSufficientThroughputMs += timeDeltaLastTwoPollsMs;
910                     if (isDefaultOnWifi) {
911                         mConnectionDurationInSufficientThroughputDefaultWifiMs +=
912                                 timeDeltaLastTwoPollsMs;
913                     }
914                 }
915             }
916         }
917         @Override
toString()918         public String toString() {
919             StringBuilder sb = new StringBuilder();
920             sb.append("connectionDurationSufficientThroughputMs=")
921                     .append(mConnectionDurationSufficientThroughputMs)
922                     .append(", connectionDurationInSufficientThroughputMs=")
923                     .append(mConnectionDurationInSufficientThroughputMs)
924                     .append(", connectionDurationInSufficientThroughputDefaultWifiMs=")
925                     .append(mConnectionDurationInSufficientThroughputDefaultWifiMs)
926                     .append(", connectionDurationCellularDataOffMs=")
927                     .append(mConnectionDurationCellularDataOffMs);
928             return sb.toString();
929         }
930     }
931 
932     class WifiStatusBuilder {
933         private int mNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
934         private boolean mConnected;
935         private boolean mValidated;
936         private int mRssi;
937         private int mEstimatedTxKbps;
938         private int mEstimatedRxKbps;
939         private boolean mIsStuckDueToUserChoice;
940 
setNetworkId(int networkId)941         public void setNetworkId(int networkId) {
942             mNetworkId = networkId;
943         }
944 
getNetworkId()945         public int getNetworkId() {
946             return mNetworkId;
947         }
948 
setConnected(boolean connected)949         public void setConnected(boolean connected) {
950             mConnected = connected;
951         }
952 
setValidated(boolean validated)953         public void setValidated(boolean validated) {
954             mValidated = validated;
955         }
956 
setRssi(int rssi)957         public void setRssi(int rssi) {
958             mRssi = rssi;
959         }
960 
setEstimatedTxKbps(int estimatedTxKbps)961         public void setEstimatedTxKbps(int estimatedTxKbps) {
962             mEstimatedTxKbps = estimatedTxKbps;
963         }
964 
setEstimatedRxKbps(int estimatedRxKbps)965         public void setEstimatedRxKbps(int estimatedRxKbps) {
966             mEstimatedRxKbps = estimatedRxKbps;
967         }
968 
setUserChoice(boolean userChoice)969         public void setUserChoice(boolean userChoice) {
970             mIsStuckDueToUserChoice = userChoice;
971         }
972 
toProto()973         public WifiStatus toProto() {
974             WifiStatus result = new WifiStatus();
975             result.isConnected = mConnected;
976             result.isValidated = mValidated;
977             result.lastRssi = mRssi;
978             result.estimatedTxKbps = mEstimatedTxKbps;
979             result.estimatedRxKbps = mEstimatedRxKbps;
980             result.isStuckDueToUserConnectChoice = mIsStuckDueToUserChoice;
981             return result;
982         }
983     }
984 
convertToNetworkDisableReason( WifiConfiguration config, Set<Integer> bssidBlocklistReasons)985     private NetworkDisableReason convertToNetworkDisableReason(
986             WifiConfiguration config, Set<Integer> bssidBlocklistReasons) {
987         NetworkSelectionStatus status = config.getNetworkSelectionStatus();
988         NetworkDisableReason result = new NetworkDisableReason();
989         if (config.allowAutojoin) {
990             if (!status.isNetworkEnabled()) {
991                 result.disableReason =
992                         MetricsUtils.convertNetworkSelectionDisableReasonToWifiProtoEnum(
993                                 status.getNetworkSelectionDisableReason());
994                 if (status.isNetworkPermanentlyDisabled()) {
995                     result.configPermanentlyDisabled = true;
996                 } else {
997                     result.configTemporarilyDisabled = true;
998                 }
999             }
1000         } else {
1001             result.disableReason = NetworkDisableReason.REASON_AUTO_JOIN_DISABLED;
1002             result.configPermanentlyDisabled = true;
1003         }
1004 
1005         int[] convertedBssidBlockReasons = bssidBlocklistReasons.stream()
1006                 .mapToInt(i -> MetricsUtils.convertBssidBlocklistReasonToWifiProtoEnum(i))
1007                 .toArray();
1008         if (convertedBssidBlockReasons.length > 0) {
1009             result.bssidDisableReasons = convertedBssidBlockReasons;
1010         }
1011         return result;
1012     }
1013 
1014     class UserActionEventWithTime {
1015         private UserActionEvent mUserActionEvent;
1016         private long mWallClockTimeMs = 0; // wall clock time for debugging only
1017 
UserActionEventWithTime(int eventType, TargetNetworkInfo targetNetworkInfo)1018         UserActionEventWithTime(int eventType, TargetNetworkInfo targetNetworkInfo) {
1019             mUserActionEvent = new UserActionEvent();
1020             mUserActionEvent.eventType = eventType;
1021             mUserActionEvent.startTimeMillis = mClock.getElapsedSinceBootMillis();
1022             mWallClockTimeMs = mClock.getWallClockMillis();
1023             mUserActionEvent.targetNetworkInfo = targetNetworkInfo;
1024             mUserActionEvent.wifiStatus = mWifiStatusBuilder.toProto();
1025         }
1026 
UserActionEventWithTime(int eventType, int targetNetId)1027         UserActionEventWithTime(int eventType, int targetNetId) {
1028             this(eventType, null);
1029             if (targetNetId >= 0) {
1030                 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(targetNetId);
1031                 if (config != null) {
1032                     TargetNetworkInfo networkInfo = new TargetNetworkInfo();
1033                     networkInfo.isEphemeral = config.isEphemeral();
1034                     networkInfo.isPasspoint = config.isPasspoint();
1035                     mUserActionEvent.targetNetworkInfo = networkInfo;
1036                     mUserActionEvent.networkDisableReason = convertToNetworkDisableReason(
1037                             config, mWifiBlocklistMonitor.getFailureReasonsForSsid(config.SSID));
1038                 }
1039             }
1040         }
1041 
toString()1042         public String toString() {
1043             StringBuilder sb = new StringBuilder();
1044             Calendar c = Calendar.getInstance();
1045             c.setTimeInMillis(mWallClockTimeMs);
1046             sb.append(StringUtil.calendarToString(c));
1047             String eventType = "UNKNOWN";
1048             switch (mUserActionEvent.eventType) {
1049                 case UserActionEvent.EVENT_FORGET_WIFI:
1050                     eventType = "EVENT_FORGET_WIFI";
1051                     break;
1052                 case UserActionEvent.EVENT_DISCONNECT_WIFI:
1053                     eventType = "EVENT_DISCONNECT_WIFI";
1054                     break;
1055                 case UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_METERED:
1056                     eventType = "EVENT_CONFIGURE_METERED_STATUS_METERED";
1057                     break;
1058                 case UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_UNMETERED:
1059                     eventType = "EVENT_CONFIGURE_METERED_STATUS_UNMETERED";
1060                     break;
1061                 case UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_AUTO:
1062                     eventType = "EVENT_CONFIGURE_METERED_STATUS_AUTO";
1063                     break;
1064                 case UserActionEvent.EVENT_CONFIGURE_MAC_RANDOMIZATION_ON:
1065                     eventType = "EVENT_CONFIGURE_MAC_RANDOMIZATION_ON";
1066                     break;
1067                 case UserActionEvent.EVENT_CONFIGURE_MAC_RANDOMIZATION_OFF:
1068                     eventType = "EVENT_CONFIGURE_MAC_RANDOMIZATION_OFF";
1069                     break;
1070                 case UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_ON:
1071                     eventType = "EVENT_CONFIGURE_AUTO_CONNECT_ON";
1072                     break;
1073                 case UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_OFF:
1074                     eventType = "EVENT_CONFIGURE_AUTO_CONNECT_OFF";
1075                     break;
1076                 case UserActionEvent.EVENT_TOGGLE_WIFI_ON:
1077                     eventType = "EVENT_TOGGLE_WIFI_ON";
1078                     break;
1079                 case UserActionEvent.EVENT_TOGGLE_WIFI_OFF:
1080                     eventType = "EVENT_TOGGLE_WIFI_OFF";
1081                     break;
1082                 case UserActionEvent.EVENT_MANUAL_CONNECT:
1083                     eventType = "EVENT_MANUAL_CONNECT";
1084                     break;
1085                 case UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK:
1086                     eventType = "EVENT_ADD_OR_UPDATE_NETWORK";
1087                     break;
1088                 case UserActionEvent.EVENT_RESTART_WIFI_SUB_SYSTEM:
1089                     eventType = "EVENT_RESTART_WIFI_SUB_SYSTEM";
1090                     break;
1091             }
1092             sb.append(" eventType=").append(eventType);
1093             sb.append(" startTimeMillis=").append(mUserActionEvent.startTimeMillis);
1094             TargetNetworkInfo networkInfo = mUserActionEvent.targetNetworkInfo;
1095             if (networkInfo != null) {
1096                 sb.append(" isEphemeral=").append(networkInfo.isEphemeral);
1097                 sb.append(" isPasspoint=").append(networkInfo.isPasspoint);
1098             }
1099             WifiStatus wifiStatus = mUserActionEvent.wifiStatus;
1100             if (wifiStatus != null) {
1101                 sb.append("\nWifiStatus: isConnected=").append(wifiStatus.isConnected);
1102                 sb.append(" isValidated=").append(wifiStatus.isValidated);
1103                 sb.append(" lastRssi=").append(wifiStatus.lastRssi);
1104                 sb.append(" estimatedTxKbps=").append(wifiStatus.estimatedTxKbps);
1105                 sb.append(" estimatedRxKbps=").append(wifiStatus.estimatedRxKbps);
1106                 sb.append(" isStuckDueToUserConnectChoice=")
1107                         .append(wifiStatus.isStuckDueToUserConnectChoice);
1108             }
1109             NetworkDisableReason disableReason = mUserActionEvent.networkDisableReason;
1110             if (disableReason != null) {
1111                 sb.append("\nNetworkDisableReason: DisableReason=")
1112                         .append(disableReason.disableReason);
1113                 sb.append(" configTemporarilyDisabled=")
1114                         .append(disableReason.configTemporarilyDisabled);
1115                 sb.append(" configPermanentlyDisabled=")
1116                         .append(disableReason.configPermanentlyDisabled);
1117                 sb.append(" bssidDisableReasons=")
1118                         .append(Arrays.toString(disableReason.bssidDisableReasons));
1119             }
1120             return sb.toString();
1121         }
1122 
toProto()1123         public UserActionEvent toProto() {
1124             return mUserActionEvent;
1125         }
1126     }
1127 
1128     /**
1129      * Log event, tracking the start time, end time and result of a wireless connection attempt.
1130      */
1131     class ConnectionEvent {
1132         final WifiMetricsProto.ConnectionEvent mConnectionEvent;
1133         //<TODO> Move these constants into a wifi.proto Enum, and create a new Failure Type field
1134         //covering more than just l2 failures. see b/27652362
1135         /**
1136          * Failure codes, used for the 'level_2_failure_code' Connection event field (covers a lot
1137          * more failures than just l2 though, since the proto does not have a place to log
1138          * framework failures)
1139          */
1140         // Failure is unknown
1141         public static final int FAILURE_UNKNOWN = 0;
1142         // NONE
1143         public static final int FAILURE_NONE = 1;
1144         // ASSOCIATION_REJECTION_EVENT
1145         public static final int FAILURE_ASSOCIATION_REJECTION = 2;
1146         // AUTHENTICATION_FAILURE_EVENT
1147         public static final int FAILURE_AUTHENTICATION_FAILURE = 3;
1148         // SSID_TEMP_DISABLED (Also Auth failure)
1149         public static final int FAILURE_SSID_TEMP_DISABLED = 4;
1150         // reconnect() or reassociate() call to WifiNative failed
1151         public static final int FAILURE_CONNECT_NETWORK_FAILED = 5;
1152         // NETWORK_DISCONNECTION_EVENT
1153         public static final int FAILURE_NETWORK_DISCONNECTION = 6;
1154         // NEW_CONNECTION_ATTEMPT before previous finished
1155         public static final int FAILURE_NEW_CONNECTION_ATTEMPT = 7;
1156         // New connection attempt to the same network & bssid
1157         public static final int FAILURE_REDUNDANT_CONNECTION_ATTEMPT = 8;
1158         // Roam Watchdog timer triggered (Roaming timed out)
1159         public static final int FAILURE_ROAM_TIMEOUT = 9;
1160         // DHCP failure
1161         public static final int FAILURE_DHCP = 10;
1162         // ASSOCIATION_TIMED_OUT
1163         public static final int FAILURE_ASSOCIATION_TIMED_OUT = 11;
1164         // NETWORK_NOT_FOUND
1165         public static final int FAILURE_NETWORK_NOT_FOUND = 12;
1166         // Connection attempt aborted by the watchdog because the AP didn't respond.
1167         public static final int FAILURE_NO_RESPONSE = 13;
1168 
1169         RouterFingerPrint mRouterFingerPrint;
1170         private String mConfigSsid;
1171         private String mConfigBssid;
1172         private int mWifiState;
1173         private boolean mScreenOn;
1174         private int mAuthType;
1175         private int mTrigger;
1176         private boolean mHasEverConnected;
1177         private boolean mIsCarrierWifi;
1178         private boolean mIsOobPseudonymEnabled;
1179         private int mRole;
1180         private int mUid;
1181         private int mCarrierId;
1182         private int mEapType;
1183         private int mPhase2Method;
1184         private int mPasspointRoamingType;
1185         private int mTofuConnectionState;
1186 
ConnectionEvent()1187         private ConnectionEvent() {
1188             mConnectionEvent = new WifiMetricsProto.ConnectionEvent();
1189             mRouterFingerPrint = new RouterFingerPrint();
1190             mConnectionEvent.routerFingerprint = mRouterFingerPrint.mRouterFingerPrintProto;
1191             mConfigSsid = "<NULL>";
1192             mConfigBssid = "<NULL>";
1193             mWifiState = WifiMetricsProto.WifiLog.WIFI_UNKNOWN;
1194             mScreenOn = false;
1195             mIsCarrierWifi = false;
1196             mIsOobPseudonymEnabled = false;
1197         }
1198 
toString()1199         public String toString() {
1200             StringBuilder sb = new StringBuilder();
1201             sb.append("startTime=");
1202             Calendar c = Calendar.getInstance();
1203             synchronized (mLock) {
1204                 c.setTimeInMillis(mConnectionEvent.startTimeMillis);
1205                 if (mConnectionEvent.startTimeMillis == 0) {
1206                     sb.append("            <null>");
1207                 } else {
1208                     sb.append(StringUtil.calendarToString(c));
1209                 }
1210                 sb.append(", SSID=");
1211                 sb.append(mConfigSsid);
1212                 sb.append(", BSSID=");
1213                 sb.append(mConfigBssid);
1214                 sb.append(", durationMillis=");
1215                 sb.append(mConnectionEvent.durationTakenToConnectMillis);
1216                 sb.append(", roamType=");
1217                 switch(mConnectionEvent.roamType) {
1218                     case 1:
1219                         sb.append("ROAM_NONE");
1220                         break;
1221                     case 2:
1222                         sb.append("ROAM_DBDC");
1223                         break;
1224                     case 3:
1225                         sb.append("ROAM_ENTERPRISE");
1226                         break;
1227                     case 4:
1228                         sb.append("ROAM_USER_SELECTED");
1229                         break;
1230                     case 5:
1231                         sb.append("ROAM_UNRELATED");
1232                         break;
1233                     default:
1234                         sb.append("ROAM_UNKNOWN");
1235                 }
1236                 sb.append(", connectionResult=");
1237                 sb.append(mConnectionEvent.connectionResult);
1238                 sb.append(", level2FailureCode=");
1239                 switch(mConnectionEvent.level2FailureCode) {
1240                     case FAILURE_NONE:
1241                         sb.append("NONE");
1242                         break;
1243                     case FAILURE_ASSOCIATION_REJECTION:
1244                         sb.append("ASSOCIATION_REJECTION");
1245                         break;
1246                     case FAILURE_AUTHENTICATION_FAILURE:
1247                         sb.append("AUTHENTICATION_FAILURE");
1248                         break;
1249                     case FAILURE_SSID_TEMP_DISABLED:
1250                         sb.append("SSID_TEMP_DISABLED");
1251                         break;
1252                     case FAILURE_CONNECT_NETWORK_FAILED:
1253                         sb.append("CONNECT_NETWORK_FAILED");
1254                         break;
1255                     case FAILURE_NETWORK_DISCONNECTION:
1256                         sb.append("NETWORK_DISCONNECTION");
1257                         break;
1258                     case FAILURE_NEW_CONNECTION_ATTEMPT:
1259                         sb.append("NEW_CONNECTION_ATTEMPT");
1260                         break;
1261                     case FAILURE_REDUNDANT_CONNECTION_ATTEMPT:
1262                         sb.append("REDUNDANT_CONNECTION_ATTEMPT");
1263                         break;
1264                     case FAILURE_ROAM_TIMEOUT:
1265                         sb.append("ROAM_TIMEOUT");
1266                         break;
1267                     case FAILURE_DHCP:
1268                         sb.append("DHCP");
1269                         break;
1270                     case FAILURE_ASSOCIATION_TIMED_OUT:
1271                         sb.append("ASSOCIATION_TIMED_OUT");
1272                         break;
1273                     case FAILURE_NETWORK_NOT_FOUND:
1274                         sb.append("FAILURE_NETWORK_NOT_FOUND");
1275                         break;
1276                     case FAILURE_NO_RESPONSE:
1277                         sb.append("FAILURE_NO_RESPONSE");
1278                         break;
1279                     default:
1280                         sb.append("UNKNOWN");
1281                         break;
1282                 }
1283                 sb.append(", connectivityLevelFailureCode=");
1284                 switch(mConnectionEvent.connectivityLevelFailureCode) {
1285                     case WifiMetricsProto.ConnectionEvent.HLF_NONE:
1286                         sb.append("NONE");
1287                         break;
1288                     case WifiMetricsProto.ConnectionEvent.HLF_DHCP:
1289                         sb.append("DHCP");
1290                         break;
1291                     case WifiMetricsProto.ConnectionEvent.HLF_NO_INTERNET:
1292                         sb.append("NO_INTERNET");
1293                         break;
1294                     case WifiMetricsProto.ConnectionEvent.HLF_UNWANTED:
1295                         sb.append("UNWANTED");
1296                         break;
1297                     default:
1298                         sb.append("UNKNOWN");
1299                         break;
1300                 }
1301                 sb.append(", signalStrength=");
1302                 sb.append(mConnectionEvent.signalStrength);
1303                 sb.append(", wifiState=");
1304                 switch(mWifiState) {
1305                     case WifiMetricsProto.WifiLog.WIFI_DISABLED:
1306                         sb.append("WIFI_DISABLED");
1307                         break;
1308                     case WifiMetricsProto.WifiLog.WIFI_DISCONNECTED:
1309                         sb.append("WIFI_DISCONNECTED");
1310                         break;
1311                     case WifiMetricsProto.WifiLog.WIFI_ASSOCIATED:
1312                         sb.append("WIFI_ASSOCIATED");
1313                         break;
1314                     default:
1315                         sb.append("WIFI_UNKNOWN");
1316                         break;
1317                 }
1318                 sb.append(", screenOn=");
1319                 sb.append(mScreenOn);
1320                 sb.append(", mRouterFingerprint=");
1321                 sb.append(mRouterFingerPrint.toString());
1322                 sb.append(", useRandomizedMac=");
1323                 sb.append(mConnectionEvent.useRandomizedMac);
1324                 sb.append(", useAggressiveMac=" + mConnectionEvent.useAggressiveMac);
1325                 sb.append(", connectionNominator=");
1326                 switch (mConnectionEvent.connectionNominator) {
1327                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_UNKNOWN:
1328                         sb.append("NOMINATOR_UNKNOWN");
1329                         break;
1330                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL:
1331                         sb.append("NOMINATOR_MANUAL");
1332                         break;
1333                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED:
1334                         sb.append("NOMINATOR_SAVED");
1335                         break;
1336                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_SUGGESTION:
1337                         sb.append("NOMINATOR_SUGGESTION");
1338                         break;
1339                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_PASSPOINT:
1340                         sb.append("NOMINATOR_PASSPOINT");
1341                         break;
1342                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_CARRIER:
1343                         sb.append("NOMINATOR_CARRIER");
1344                         break;
1345                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_EXTERNAL_SCORED:
1346                         sb.append("NOMINATOR_EXTERNAL_SCORED");
1347                         break;
1348                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER:
1349                         sb.append("NOMINATOR_SPECIFIER");
1350                         break;
1351                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED_USER_CONNECT_CHOICE:
1352                         sb.append("NOMINATOR_SAVED_USER_CONNECT_CHOICE");
1353                         break;
1354                     case WifiMetricsProto.ConnectionEvent.NOMINATOR_OPEN_NETWORK_AVAILABLE:
1355                         sb.append("NOMINATOR_OPEN_NETWORK_AVAILABLE");
1356                         break;
1357                     default:
1358                         sb.append("UnrecognizedNominator(" + mConnectionEvent.connectionNominator
1359                                 + ")");
1360                 }
1361                 sb.append(", networkSelectorExperimentId=");
1362                 sb.append(mConnectionEvent.networkSelectorExperimentId);
1363                 sb.append(", numBssidInBlocklist=" + mConnectionEvent.numBssidInBlocklist);
1364                 sb.append(", level2FailureReason=");
1365                 switch(mConnectionEvent.level2FailureReason) {
1366                     case WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE:
1367                         sb.append("AUTH_FAILURE_NONE");
1368                         break;
1369                     case WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_TIMEOUT:
1370                         sb.append("AUTH_FAILURE_TIMEOUT");
1371                         break;
1372                     case WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD:
1373                         sb.append("AUTH_FAILURE_WRONG_PSWD");
1374                         break;
1375                     case WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_EAP_FAILURE:
1376                         sb.append("AUTH_FAILURE_EAP_FAILURE");
1377                         break;
1378                     case WifiMetricsProto.ConnectionEvent.DISCONNECTION_NON_LOCAL:
1379                         sb.append("DISCONNECTION_NON_LOCAL");
1380                         break;
1381                     default:
1382                         sb.append("FAILURE_REASON_UNKNOWN");
1383                         break;
1384                 }
1385                 sb.append(", networkType=");
1386                 switch(mConnectionEvent.networkType) {
1387                     case WifiMetricsProto.ConnectionEvent.TYPE_UNKNOWN:
1388                         sb.append("TYPE_UNKNOWN");
1389                         break;
1390                     case WifiMetricsProto.ConnectionEvent.TYPE_WPA2:
1391                         sb.append("TYPE_WPA2");
1392                         break;
1393                     case WifiMetricsProto.ConnectionEvent.TYPE_WPA3:
1394                         sb.append("TYPE_WPA3");
1395                         break;
1396                     case WifiMetricsProto.ConnectionEvent.TYPE_PASSPOINT:
1397                         sb.append("TYPE_PASSPOINT");
1398                         break;
1399                     case WifiMetricsProto.ConnectionEvent.TYPE_EAP:
1400                         sb.append("TYPE_EAP");
1401                         break;
1402                     case WifiMetricsProto.ConnectionEvent.TYPE_OWE:
1403                         sb.append("TYPE_OWE");
1404                         break;
1405                     case WifiMetricsProto.ConnectionEvent.TYPE_OPEN:
1406                         sb.append("TYPE_OPEN");
1407                         break;
1408                     case WifiMetricsProto.ConnectionEvent.TYPE_WAPI:
1409                         sb.append("TYPE_WAPI");
1410                         break;
1411                 }
1412                 sb.append(", networkCreator=");
1413                 switch (mConnectionEvent.networkCreator) {
1414                     case WifiMetricsProto.ConnectionEvent.CREATOR_UNKNOWN:
1415                         sb.append("CREATOR_UNKNOWN");
1416                         break;
1417                     case WifiMetricsProto.ConnectionEvent.CREATOR_USER:
1418                         sb.append("CREATOR_USER");
1419                         break;
1420                     case WifiMetricsProto.ConnectionEvent.CREATOR_CARRIER:
1421                         sb.append("CREATOR_CARRIER");
1422                         break;
1423                 }
1424                 sb.append(", numConsecutiveConnectionFailure="
1425                         + mConnectionEvent.numConsecutiveConnectionFailure);
1426                 sb.append(", isOsuProvisioned=" + mConnectionEvent.isOsuProvisioned);
1427                 sb.append(" interfaceName=").append(mConnectionEvent.interfaceName);
1428                 sb.append(" interfaceRole=").append(
1429                         clientRoleEnumToString(mConnectionEvent.interfaceRole));
1430                 sb.append(", isFirstConnectionAfterBoot="
1431                         + mConnectionEvent.isFirstConnectionAfterBoot);
1432                 sb.append(", isCarrierWifi=" + mIsCarrierWifi);
1433                 sb.append(", isOobPseudonymEnabled=" + mIsOobPseudonymEnabled);
1434                 sb.append(", uid=" + mUid);
1435                 return sb.toString();
1436             }
1437         }
1438 
updateFromWifiConfiguration(WifiConfiguration config)1439         private void updateFromWifiConfiguration(WifiConfiguration config) {
1440             synchronized (mLock) {
1441                 if (config != null) {
1442                     // Is this a hidden network
1443                     mRouterFingerPrint.mRouterFingerPrintProto.hidden = config.hiddenSSID;
1444                     // Config may not have a valid dtimInterval set yet, in which case dtim will be
1445                     // zero (These are only populated from beacon frame scan results, which are
1446                     // returned as scan results from the chip far less frequently than
1447                     // Probe-responses)
1448                     if (config.dtimInterval > 0) {
1449                         mRouterFingerPrint.mRouterFingerPrintProto.dtim = config.dtimInterval;
1450                     }
1451 
1452                     if (config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) {
1453                         mIsCarrierWifi = true;
1454                     }
1455 
1456                     mConfigSsid = config.SSID;
1457                     // Get AuthType information from config (We do this again from ScanResult after
1458                     // associating with BSSID)
1459                     if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_OPEN)) {
1460                         mRouterFingerPrint.mRouterFingerPrintProto.authentication =
1461                                 WifiMetricsProto.RouterFingerPrint.AUTH_OPEN;
1462                     } else if (config.isEnterprise()) {
1463                         mRouterFingerPrint.mRouterFingerPrintProto.authentication =
1464                                 WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE;
1465                     } else {
1466                         mRouterFingerPrint.mRouterFingerPrintProto.authentication =
1467                                 WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL;
1468                     }
1469                     mRouterFingerPrint.mRouterFingerPrintProto.passpoint = config.isPasspoint();
1470                     mRouterFingerPrint.mRouterFingerPrintProto.isPasspointHomeProvider =
1471                             config.isHomeProviderNetwork;
1472                     // If there's a ScanResult candidate associated with this config already, get it
1473                     // and log (more accurate) metrics from it
1474                     ScanResult candidate = config.getNetworkSelectionStatus().getCandidate();
1475                     if (candidate != null) {
1476                         updateMetricsFromScanResult(this, candidate);
1477                     }
1478                     if (mRouterFingerPrint.mRouterFingerPrintProto.authentication
1479                             == WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE
1480                             && config.enterpriseConfig != null) {
1481                         int eapMethod = config.enterpriseConfig.getEapMethod();
1482                         mRouterFingerPrint.mRouterFingerPrintProto.eapMethod =
1483                                 getEapMethodProto(eapMethod);
1484                         int phase2Method = config.enterpriseConfig.getPhase2Method();
1485                         mRouterFingerPrint.mRouterFingerPrintProto.authPhase2Method =
1486                                 getAuthPhase2MethodProto(phase2Method);
1487                         int ocspType = config.enterpriseConfig.getOcsp();
1488                         mRouterFingerPrint.mRouterFingerPrintProto.ocspType =
1489                                 getOcspTypeProto(ocspType);
1490                     }
1491                     mTofuConnectionState = convertTofuConnectionStateToProto(config);
1492                 }
1493             }
1494         }
1495     }
1496 
1497     class WifiOffMetrics {
1498         public int numWifiOff = 0;
1499         public int numWifiOffDeferring = 0;
1500         public int numWifiOffDeferringTimeout = 0;
1501         public final IntCounter wifiOffDeferringTimeHistogram = new IntCounter();
1502 
toProto()1503         public WifiMetricsProto.WifiOffMetrics toProto() {
1504             WifiMetricsProto.WifiOffMetrics proto =
1505                     new WifiMetricsProto.WifiOffMetrics();
1506             proto.numWifiOff = numWifiOff;
1507             proto.numWifiOffDeferring = numWifiOffDeferring;
1508             proto.numWifiOffDeferringTimeout = numWifiOffDeferringTimeout;
1509             proto.wifiOffDeferringTimeHistogram = wifiOffDeferringTimeHistogram.toProto();
1510             return proto;
1511         }
1512 
clear()1513         public void clear() {
1514             numWifiOff = 0;
1515             numWifiOffDeferring = 0;
1516             numWifiOffDeferringTimeout = 0;
1517             wifiOffDeferringTimeHistogram.clear();
1518         }
1519 
1520         @Override
toString()1521         public String toString() {
1522             StringBuilder sb = new StringBuilder();
1523             sb.append("numWifiOff=")
1524                     .append(numWifiOff)
1525                     .append(", numWifiOffDeferring=")
1526                     .append(numWifiOffDeferring)
1527                     .append(", numWifiOffDeferringTimeout=")
1528                     .append(numWifiOffDeferringTimeout)
1529                     .append(", wifiOffDeferringTimeHistogram=")
1530                     .append(wifiOffDeferringTimeHistogram);
1531             return sb.toString();
1532         }
1533     }
1534 
1535     class SoftApConfigLimitationMetrics {
1536         // Collect the number of softap security setting reset to default during the restore
1537         public int numSecurityTypeResetToDefault = 0;
1538         // Collect the number of softap max client setting reset to default during the restore
1539         public int numMaxClientSettingResetToDefault = 0;
1540         // Collect the number of softap client control setting reset to default during the restore
1541         public int numClientControlByUserResetToDefault = 0;
1542         // Collect the max client setting when reach it cause client is blocked
1543         public final IntCounter maxClientSettingWhenReachHistogram = new IntCounter();
1544 
toProto()1545         public WifiMetricsProto.SoftApConfigLimitationMetrics toProto() {
1546             WifiMetricsProto.SoftApConfigLimitationMetrics proto =
1547                     new WifiMetricsProto.SoftApConfigLimitationMetrics();
1548             proto.numSecurityTypeResetToDefault = numSecurityTypeResetToDefault;
1549             proto.numMaxClientSettingResetToDefault = numMaxClientSettingResetToDefault;
1550             proto.numClientControlByUserResetToDefault = numClientControlByUserResetToDefault;
1551             proto.maxClientSettingWhenReachHistogram = maxClientSettingWhenReachHistogram.toProto();
1552             return proto;
1553         }
1554 
clear()1555         public void clear() {
1556             numSecurityTypeResetToDefault = 0;
1557             numMaxClientSettingResetToDefault = 0;
1558             numClientControlByUserResetToDefault = 0;
1559             maxClientSettingWhenReachHistogram.clear();
1560         }
1561 
1562         @Override
toString()1563         public String toString() {
1564             StringBuilder sb = new StringBuilder();
1565             sb.append("numSecurityTypeResetToDefault=")
1566                     .append(numSecurityTypeResetToDefault)
1567                     .append(", numMaxClientSettingResetToDefault=")
1568                     .append(numMaxClientSettingResetToDefault)
1569                     .append(", numClientControlByUserResetToDefault=")
1570                     .append(numClientControlByUserResetToDefault)
1571                     .append(", maxClientSettingWhenReachHistogram=")
1572                     .append(maxClientSettingWhenReachHistogram);
1573             return sb.toString();
1574         }
1575     }
1576 
1577     class CarrierWifiMetrics {
1578         public int numConnectionSuccess = 0;
1579         public int numConnectionAuthFailure = 0;
1580         public int numConnectionNonAuthFailure = 0;
1581 
toProto()1582         public WifiMetricsProto.CarrierWifiMetrics toProto() {
1583             WifiMetricsProto.CarrierWifiMetrics proto =
1584                     new WifiMetricsProto.CarrierWifiMetrics();
1585             proto.numConnectionSuccess = numConnectionSuccess;
1586             proto.numConnectionAuthFailure = numConnectionAuthFailure;
1587             proto.numConnectionNonAuthFailure = numConnectionNonAuthFailure;
1588             return proto;
1589         }
1590 
clear()1591         public void clear() {
1592             numConnectionSuccess = 0;
1593             numConnectionAuthFailure = 0;
1594             numConnectionNonAuthFailure = 0;
1595         }
1596 
1597         @Override
toString()1598         public String toString() {
1599             StringBuilder sb = new StringBuilder();
1600             sb.append("numConnectionSuccess=")
1601                     .append(numConnectionSuccess)
1602                     .append(", numConnectionAuthFailure=")
1603                     .append(numConnectionAuthFailure)
1604                     .append(", numConnectionNonAuthFailure")
1605                     .append(numConnectionNonAuthFailure);
1606             return sb.toString();
1607         }
1608     }
1609 
WifiMetrics( Context context, FrameworkFacade facade, Clock clock, Looper looper, WifiAwareMetrics awareMetrics, RttMetrics rttMetrics, WifiPowerMetrics wifiPowerMetrics, WifiP2pMetrics wifiP2pMetrics, DppMetrics dppMetrics, WifiMonitor wifiMonitor, WifiDeviceStateChangeManager wifiDeviceStateChangeManager)1610     public WifiMetrics(
1611             Context context,
1612             FrameworkFacade facade,
1613             Clock clock,
1614             Looper looper,
1615             WifiAwareMetrics awareMetrics,
1616             RttMetrics rttMetrics,
1617             WifiPowerMetrics wifiPowerMetrics,
1618             WifiP2pMetrics wifiP2pMetrics,
1619             DppMetrics dppMetrics,
1620             WifiMonitor wifiMonitor,
1621             WifiDeviceStateChangeManager wifiDeviceStateChangeManager) {
1622         mContext = context;
1623         mFacade = facade;
1624         mClock = clock;
1625         mWifiState = WifiMetricsProto.WifiLog.WIFI_DISABLED;
1626         mRecordStartTimeSec = mClock.getElapsedSinceBootMillis() / 1000;
1627         mWifiAwareMetrics = awareMetrics;
1628         mRttMetrics = rttMetrics;
1629         mWifiPowerMetrics = wifiPowerMetrics;
1630         mWifiP2pMetrics = wifiP2pMetrics;
1631         mDppMetrics = dppMetrics;
1632         mWifiMonitor = wifiMonitor;
1633         mHandler = new Handler(looper) {
1634             public void handleMessage(Message msg) {
1635                 synchronized (mLock) {
1636                     processMessage(msg);
1637                 }
1638             }
1639         };
1640 
1641         mCurrentDeviceMobilityState = WifiManager.DEVICE_MOBILITY_STATE_UNKNOWN;
1642         DeviceMobilityStatePnoScanStats unknownStateStats =
1643                 getOrCreateDeviceMobilityStatePnoScanStats(mCurrentDeviceMobilityState);
1644         unknownStateStats.numTimesEnteredState++;
1645         mCurrentDeviceMobilityStateStartMs = mClock.getElapsedSinceBootMillis();
1646         mCurrentDeviceMobilityStatePnoScanStartMs = -1;
1647         mOnWifiUsabilityListeners = new RemoteCallbackList<>();
1648         mScanMetrics = new ScanMetrics(context, clock);
1649         wifiDeviceStateChangeManager.registerStateChangeCallback(
1650                 new WifiDeviceStateChangeManager.StateChangeCallback() {
1651                     @Override
1652                     public void onScreenStateChanged(boolean screenOn) {
1653                         setScreenState(screenOn);
1654                     }
1655                 });
1656     }
1657 
1658     /** Sets internal ScoringParams member */
setScoringParams(ScoringParams scoringParams)1659     public void setScoringParams(ScoringParams scoringParams) {
1660         mScoringParams = scoringParams;
1661     }
1662 
1663     /** Sets internal WifiConfigManager member */
setWifiConfigManager(WifiConfigManager wifiConfigManager)1664     public void setWifiConfigManager(WifiConfigManager wifiConfigManager) {
1665         mWifiConfigManager = wifiConfigManager;
1666     }
1667 
1668     /** Sets internal WifiNetworkSelector member */
setWifiNetworkSelector(WifiNetworkSelector wifiNetworkSelector)1669     public void setWifiNetworkSelector(WifiNetworkSelector wifiNetworkSelector) {
1670         mWifiNetworkSelector = wifiNetworkSelector;
1671     }
1672 
1673     /** Sets internal PasspointManager member */
setPasspointManager(PasspointManager passpointManager)1674     public void setPasspointManager(PasspointManager passpointManager) {
1675         mPasspointManager = passpointManager;
1676     }
1677 
1678     /** Sets internal WifiDataStall member */
setWifiDataStall(WifiDataStall wifiDataStall)1679     public void setWifiDataStall(WifiDataStall wifiDataStall) {
1680         mWifiDataStall = wifiDataStall;
1681     }
1682 
1683     /** Sets internal WifiBlocklistMonitor member */
setWifiBlocklistMonitor(WifiBlocklistMonitor wifiBlocklistMonitor)1684     public void setWifiBlocklistMonitor(WifiBlocklistMonitor wifiBlocklistMonitor) {
1685         mWifiBlocklistMonitor = wifiBlocklistMonitor;
1686     }
1687 
1688     /** Sets internal WifiHealthMonitor member */
setWifiHealthMonitor(WifiHealthMonitor wifiHealthMonitor)1689     public void setWifiHealthMonitor(WifiHealthMonitor wifiHealthMonitor) {
1690         mWifiHealthMonitor = wifiHealthMonitor;
1691     }
1692 
1693     /** Sets internal WifiScoreCard member */
setWifiScoreCard(WifiScoreCard wifiScoreCard)1694     public void setWifiScoreCard(WifiScoreCard wifiScoreCard) {
1695         mWifiScoreCard = wifiScoreCard;
1696     }
1697 
1698     /** Sets internal WifiChannelUtilization member */
setWifiChannelUtilization(WifiChannelUtilization wifiChannelUtilization)1699     public void setWifiChannelUtilization(WifiChannelUtilization wifiChannelUtilization) {
1700         mWifiChannelUtilization = wifiChannelUtilization;
1701     }
1702 
1703     /** Sets internal WifiSettingsStore member */
setWifiSettingsStore(WifiSettingsStore wifiSettingsStore)1704     public void setWifiSettingsStore(WifiSettingsStore wifiSettingsStore) {
1705         mWifiSettingsStore = wifiSettingsStore;
1706     }
1707 
1708     /** Sets internal ActiveModeWarden member */
setActiveModeWarden(ActiveModeWarden activeModeWarden)1709     public void setActiveModeWarden(ActiveModeWarden activeModeWarden) {
1710         mActiveModeWarden = activeModeWarden;
1711         mActiveModeWarden.registerModeChangeCallback(new ModeChangeCallback());
1712     }
1713 
1714     /**
1715      * Implements callbacks that set the internal ifaceName to ClientRole mapping.
1716      */
1717     @VisibleForTesting
1718     private class ModeChangeCallback implements ActiveModeWarden.ModeChangeCallback {
1719         @Override
onActiveModeManagerAdded(@onNull ActiveModeManager activeModeManager)1720         public void onActiveModeManagerAdded(@NonNull ActiveModeManager activeModeManager) {
1721             if (!(activeModeManager instanceof ConcreteClientModeManager)) {
1722                 return;
1723             }
1724             synchronized (mLock) {
1725                 ConcreteClientModeManager clientModeManager =
1726                         (ConcreteClientModeManager) activeModeManager;
1727                 mIfaceToRoleMap.put(clientModeManager.getInterfaceName(),
1728                         clientModeManager.getRole());
1729             }
1730         }
1731 
1732         @Override
onActiveModeManagerRemoved(@onNull ActiveModeManager activeModeManager)1733         public void onActiveModeManagerRemoved(@NonNull ActiveModeManager activeModeManager) {
1734             if (!(activeModeManager instanceof ConcreteClientModeManager)) {
1735                 return;
1736             }
1737             synchronized (mLock) {
1738                 ConcreteClientModeManager clientModeManager =
1739                         (ConcreteClientModeManager) activeModeManager;
1740                 mIfaceToRoleMap.remove(clientModeManager.getInterfaceName());
1741             }
1742         }
1743 
1744         @Override
onActiveModeManagerRoleChanged(@onNull ActiveModeManager activeModeManager)1745         public void onActiveModeManagerRoleChanged(@NonNull ActiveModeManager activeModeManager) {
1746             if (!(activeModeManager instanceof ConcreteClientModeManager)) {
1747                 return;
1748             }
1749             synchronized (mLock) {
1750                 ConcreteClientModeManager clientModeManager =
1751                         (ConcreteClientModeManager) activeModeManager;
1752                 mIfaceToRoleMap.put(clientModeManager.getInterfaceName(),
1753                         clientModeManager.getRole());
1754             }
1755         }
1756     }
1757 
1758     /**
1759      * Increment cumulative counters for link layer stats.
1760      * @param newStats
1761      */
incrementWifiLinkLayerUsageStats(String ifaceName, WifiLinkLayerStats newStats)1762     public void incrementWifiLinkLayerUsageStats(String ifaceName, WifiLinkLayerStats newStats) {
1763         // This is only collected for primary STA currently because RSSI polling is disabled for
1764         // non-primary STAs.
1765         if (!isPrimary(ifaceName)) {
1766             return;
1767         }
1768         if (newStats == null) {
1769             return;
1770         }
1771         if (mLastLinkLayerStats == null) {
1772             mLastLinkLayerStats = newStats;
1773             return;
1774         }
1775         if (!newLinkLayerStatsIsValid(mLastLinkLayerStats, newStats)) {
1776             // This could mean the radio chip is reset or the data is incorrectly reported.
1777             // Don't increment any counts and discard the possibly corrupt |newStats| completely.
1778             mLastLinkLayerStats = null;
1779             return;
1780         }
1781         mWifiLinkLayerUsageStats.loggingDurationMs +=
1782                 (newStats.timeStampInMs - mLastLinkLayerStats.timeStampInMs);
1783         mWifiLinkLayerUsageStats.radioOnTimeMs += (newStats.on_time - mLastLinkLayerStats.on_time);
1784         mWifiLinkLayerUsageStats.radioTxTimeMs += (newStats.tx_time - mLastLinkLayerStats.tx_time);
1785         mWifiLinkLayerUsageStats.radioRxTimeMs += (newStats.rx_time - mLastLinkLayerStats.rx_time);
1786         mWifiLinkLayerUsageStats.radioScanTimeMs +=
1787                 (newStats.on_time_scan - mLastLinkLayerStats.on_time_scan);
1788         mWifiLinkLayerUsageStats.radioNanScanTimeMs +=
1789                 (newStats.on_time_nan_scan - mLastLinkLayerStats.on_time_nan_scan);
1790         mWifiLinkLayerUsageStats.radioBackgroundScanTimeMs +=
1791                 (newStats.on_time_background_scan - mLastLinkLayerStats.on_time_background_scan);
1792         mWifiLinkLayerUsageStats.radioRoamScanTimeMs +=
1793                 (newStats.on_time_roam_scan - mLastLinkLayerStats.on_time_roam_scan);
1794         mWifiLinkLayerUsageStats.radioPnoScanTimeMs +=
1795                 (newStats.on_time_pno_scan - mLastLinkLayerStats.on_time_pno_scan);
1796         mWifiLinkLayerUsageStats.radioHs20ScanTimeMs +=
1797                 (newStats.on_time_hs20_scan - mLastLinkLayerStats.on_time_hs20_scan);
1798         incrementPerRadioUsageStats(mLastLinkLayerStats, newStats);
1799 
1800         mLastLinkLayerStats = newStats;
1801     }
1802 
1803     /**
1804      * Increment individual radio stats usage
1805      */
incrementPerRadioUsageStats(WifiLinkLayerStats oldStats, WifiLinkLayerStats newStats)1806     private void incrementPerRadioUsageStats(WifiLinkLayerStats oldStats,
1807             WifiLinkLayerStats newStats) {
1808         if (newStats.radioStats != null && newStats.radioStats.length > 0
1809                 && oldStats.radioStats != null && oldStats.radioStats.length > 0
1810                 && newStats.radioStats.length == oldStats.radioStats.length) {
1811             int numRadios = newStats.radioStats.length;
1812             for (int i = 0; i < numRadios; i++) {
1813                 WifiLinkLayerStats.RadioStat newRadio = newStats.radioStats[i];
1814                 WifiLinkLayerStats.RadioStat oldRadio = oldStats.radioStats[i];
1815                 if (newRadio.radio_id != oldRadio.radio_id) {
1816                     continue;
1817                 }
1818                 RadioStats radioStats = mRadioStats.get(newRadio.radio_id);
1819                 if (radioStats == null) {
1820                     radioStats = new RadioStats();
1821                     radioStats.radioId = newRadio.radio_id;
1822                     mRadioStats.put(newRadio.radio_id, radioStats);
1823                 }
1824                 radioStats.totalRadioOnTimeMs
1825                         += newRadio.on_time - oldRadio.on_time;
1826                 radioStats.totalRadioTxTimeMs
1827                         += newRadio.tx_time - oldRadio.tx_time;
1828                 radioStats.totalRadioRxTimeMs
1829                         += newRadio.rx_time - oldRadio.rx_time;
1830                 radioStats.totalScanTimeMs
1831                         += newRadio.on_time_scan - oldRadio.on_time_scan;
1832                 radioStats.totalNanScanTimeMs
1833                         += newRadio.on_time_nan_scan - oldRadio.on_time_nan_scan;
1834                 radioStats.totalBackgroundScanTimeMs
1835                         += newRadio.on_time_background_scan - oldRadio.on_time_background_scan;
1836                 radioStats.totalRoamScanTimeMs
1837                         += newRadio.on_time_roam_scan - oldRadio.on_time_roam_scan;
1838                 radioStats.totalPnoScanTimeMs
1839                         += newRadio.on_time_pno_scan - oldRadio.on_time_pno_scan;
1840                 radioStats.totalHotspot2ScanTimeMs
1841                         += newRadio.on_time_hs20_scan - oldRadio.on_time_hs20_scan;
1842             }
1843         }
1844     }
1845 
newLinkLayerStatsIsValid(WifiLinkLayerStats oldStats, WifiLinkLayerStats newStats)1846     private boolean newLinkLayerStatsIsValid(WifiLinkLayerStats oldStats,
1847             WifiLinkLayerStats newStats) {
1848         if (newStats.on_time < oldStats.on_time
1849                 || newStats.tx_time < oldStats.tx_time
1850                 || newStats.rx_time < oldStats.rx_time
1851                 || newStats.on_time_scan < oldStats.on_time_scan) {
1852             return false;
1853         }
1854         return true;
1855     }
1856 
1857     /**
1858      * Increment total number of attempts to start a pno scan
1859      */
incrementPnoScanStartAttemptCount()1860     public void incrementPnoScanStartAttemptCount() {
1861         synchronized (mLock) {
1862             mPnoScanMetrics.numPnoScanAttempts++;
1863         }
1864     }
1865 
1866     /**
1867      * Increment total number of attempts with pno scan failed
1868      */
incrementPnoScanFailedCount()1869     public void incrementPnoScanFailedCount() {
1870         synchronized (mLock) {
1871             mPnoScanMetrics.numPnoScanFailed++;
1872         }
1873     }
1874 
1875     /**
1876      * Increment number of times pno scan found a result
1877      */
incrementPnoFoundNetworkEventCount()1878     public void incrementPnoFoundNetworkEventCount() {
1879         synchronized (mLock) {
1880             mPnoScanMetrics.numPnoFoundNetworkEvents++;
1881         }
1882     }
1883 
1884     // Values used for indexing SystemStateEntries
1885     private static final int SCREEN_ON = 1;
1886     private static final int SCREEN_OFF = 0;
1887 
convertSecurityTypeToWifiMetricsNetworkType( @ifiConfiguration.SecurityType int type)1888     private int convertSecurityTypeToWifiMetricsNetworkType(
1889             @WifiConfiguration.SecurityType int type) {
1890         switch (type) {
1891             case WifiConfiguration.SECURITY_TYPE_OPEN:
1892                 return WifiMetricsProto.ConnectionEvent.TYPE_OPEN;
1893             case WifiConfiguration.SECURITY_TYPE_PSK:
1894                 return WifiMetricsProto.ConnectionEvent.TYPE_WPA2;
1895             case WifiConfiguration.SECURITY_TYPE_EAP:
1896                 return WifiMetricsProto.ConnectionEvent.TYPE_EAP;
1897             case WifiConfiguration.SECURITY_TYPE_SAE:
1898                 return WifiMetricsProto.ConnectionEvent.TYPE_WPA3;
1899             case WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT:
1900                 return WifiMetricsProto.ConnectionEvent.TYPE_EAP;
1901             case WifiConfiguration.SECURITY_TYPE_OWE:
1902                 return WifiMetricsProto.ConnectionEvent.TYPE_OWE;
1903             case WifiConfiguration.SECURITY_TYPE_WAPI_PSK:
1904             case WifiConfiguration.SECURITY_TYPE_WAPI_CERT:
1905                 return WifiMetricsProto.ConnectionEvent.TYPE_WAPI;
1906             case WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE:
1907                 return WifiMetricsProto.ConnectionEvent.TYPE_EAP;
1908             // No metric network type for WEP, OSEN, and DPP.
1909             default:
1910                 return WifiMetricsProto.ConnectionEvent.TYPE_UNKNOWN;
1911         }
1912     }
1913 
1914     /**
1915      * Create a new connection event and check if the new one overlaps with previous one.
1916      * Call when wifi attempts to make a new network connection
1917      * If there is a current 'un-ended' connection event, it will be ended with UNKNOWN connectivity
1918      * failure code.
1919      * Gathers and sets the RouterFingerPrint data as well
1920      *
1921      * @param ifaceName interface name for this connection event
1922      * @param config WifiConfiguration of the config used for the current connection attempt
1923      * @param roamType Roam type that caused connection attempt, see WifiMetricsProto.WifiLog.ROAM_X
1924      * @return The duration in ms since the last unfinished connection attempt,
1925      * or 0 if there is no unfinished connection
1926      */
startConnectionEvent( String ifaceName, WifiConfiguration config, String targetBSSID, int roamType, boolean isOobPseudonymEnabled, int role, int uid)1927     public int startConnectionEvent(
1928             String ifaceName, WifiConfiguration config, String targetBSSID, int roamType,
1929             boolean isOobPseudonymEnabled, int role, int uid) {
1930         synchronized (mLock) {
1931             int overlapWithLastConnectionMs = 0;
1932             ConnectionEvent currentConnectionEvent = mCurrentConnectionEventPerIface.get(ifaceName);
1933             if (currentConnectionEvent != null) {
1934                 overlapWithLastConnectionMs = (int) (mClock.getElapsedSinceBootMillis()
1935                         - currentConnectionEvent.mConnectionEvent.startTimeSinceBootMillis);
1936                 // Is this new Connection Event the same as the current one
1937                 if (currentConnectionEvent.mConfigSsid != null
1938                         && currentConnectionEvent.mConfigBssid != null
1939                         && config != null
1940                         && currentConnectionEvent.mConfigSsid.equals(config.SSID)
1941                         && (currentConnectionEvent.mConfigBssid.equals("any")
1942                         || currentConnectionEvent.mConfigBssid.equals(targetBSSID))) {
1943                     currentConnectionEvent.mConfigBssid = targetBSSID;
1944                     // End Connection Event due to new connection attempt to the same network
1945                     endConnectionEvent(ifaceName,
1946                             ConnectionEvent.FAILURE_REDUNDANT_CONNECTION_ATTEMPT,
1947                             WifiMetricsProto.ConnectionEvent.HLF_NONE,
1948                             WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0, 0);
1949                 } else {
1950                     // End Connection Event due to new connection attempt to different network
1951                     endConnectionEvent(ifaceName,
1952                             ConnectionEvent.FAILURE_NEW_CONNECTION_ATTEMPT,
1953                             WifiMetricsProto.ConnectionEvent.HLF_NONE,
1954                             WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0, 0);
1955                 }
1956             }
1957             // If past maximum connection events, start removing the oldest
1958             while(mConnectionEventList.size() >= MAX_CONNECTION_EVENTS) {
1959                 mConnectionEventList.removeFirst();
1960             }
1961             currentConnectionEvent = new ConnectionEvent();
1962             mCurrentConnectionEventPerIface.put(ifaceName, currentConnectionEvent);
1963             currentConnectionEvent.mConnectionEvent.interfaceName = ifaceName;
1964             currentConnectionEvent.mConnectionEvent.interfaceRole = convertIfaceToEnum(ifaceName);
1965             currentConnectionEvent.mConnectionEvent.startTimeMillis =
1966                     mClock.getWallClockMillis();
1967             currentConnectionEvent.mConnectionEvent.startTimeSinceBootMillis =
1968                     mClock.getElapsedSinceBootMillis();
1969             currentConnectionEvent.mConfigBssid = targetBSSID;
1970             currentConnectionEvent.mConnectionEvent.roamType = roamType;
1971             currentConnectionEvent.mConnectionEvent.networkSelectorExperimentId =
1972                     mNetworkSelectorExperimentId;
1973             currentConnectionEvent.updateFromWifiConfiguration(config);
1974             currentConnectionEvent.mIsOobPseudonymEnabled = isOobPseudonymEnabled;
1975             currentConnectionEvent.mConfigBssid = "any";
1976             currentConnectionEvent.mWifiState = mWifiState;
1977             currentConnectionEvent.mScreenOn = mScreenOn;
1978             currentConnectionEvent.mConnectionEvent.isFirstConnectionAfterBoot =
1979                     mFirstConnectionAfterBoot;
1980             currentConnectionEvent.mRole = role;
1981             currentConnectionEvent.mUid = uid;
1982             mFirstConnectionAfterBoot = false;
1983             mConnectionEventList.add(currentConnectionEvent);
1984             mScanResultRssiTimestampMillis = -1;
1985             if (config != null) {
1986                 try {
1987                     currentConnectionEvent.mAuthType = config.getAuthType();
1988                 } catch (IllegalStateException e) {
1989                     currentConnectionEvent.mAuthType = 0;
1990                 }
1991                 currentConnectionEvent.mHasEverConnected =
1992                         config.getNetworkSelectionStatus().hasEverConnected();
1993                 currentConnectionEvent.mConnectionEvent.useRandomizedMac =
1994                         config.macRandomizationSetting
1995                         != WifiConfiguration.RANDOMIZATION_NONE;
1996                 currentConnectionEvent.mConnectionEvent.useAggressiveMac =
1997                         mWifiConfigManager.shouldUseNonPersistentRandomization(config);
1998                 currentConnectionEvent.mConnectionEvent.connectionNominator =
1999                         mNetworkIdToNominatorId.get(config.networkId,
2000                                 WifiMetricsProto.ConnectionEvent.NOMINATOR_UNKNOWN);
2001                 currentConnectionEvent.mConnectionEvent.isCarrierMerged = config.carrierMerged;
2002                 currentConnectionEvent.mCarrierId = config.carrierId;
2003                 if (config.enterpriseConfig != null) {
2004                     currentConnectionEvent.mEapType = config.enterpriseConfig.getEapMethod();
2005                     currentConnectionEvent.mPhase2Method =
2006                             config.enterpriseConfig.getPhase2Method();
2007                     currentConnectionEvent.mPasspointRoamingType = Utils.getRoamingType(config);
2008                 }
2009 
2010                 ScanResult candidate = config.getNetworkSelectionStatus().getCandidate();
2011                 if (candidate != null) {
2012                     // Cache the RSSI of the candidate, as the connection event level is updated
2013                     // from other sources (polls, bssid_associations) and delta requires the
2014                     // scanResult rssi
2015                     mScanResultRssi = candidate.level;
2016                     mScanResultRssiTimestampMillis = mClock.getElapsedSinceBootMillis();
2017                 }
2018                 currentConnectionEvent.mConnectionEvent.numBssidInBlocklist =
2019                         mWifiBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid(config.SSID);
2020                 currentConnectionEvent.mConnectionEvent.networkType =
2021                         WifiMetricsProto.ConnectionEvent.TYPE_UNKNOWN;
2022                 currentConnectionEvent.mConnectionEvent.isOsuProvisioned = false;
2023                 SecurityParams params = config.getNetworkSelectionStatus()
2024                         .getCandidateSecurityParams();
2025                 currentConnectionEvent.mRouterFingerPrint.mSecurityMode =
2026                         getSecurityMode(config, true);
2027                 if (config.isPasspoint()) {
2028                     currentConnectionEvent.mConnectionEvent.networkType =
2029                             WifiMetricsProto.ConnectionEvent.TYPE_PASSPOINT;
2030                     currentConnectionEvent.mConnectionEvent.isOsuProvisioned =
2031                             !TextUtils.isEmpty(config.updateIdentifier);
2032                 } else if (null != params) {
2033                     currentConnectionEvent.mConnectionEvent.networkType =
2034                             convertSecurityTypeToWifiMetricsNetworkType(params.getSecurityType());
2035                 } else if (WifiConfigurationUtil.isConfigForSaeNetwork(config)) {
2036                     currentConnectionEvent.mConnectionEvent.networkType =
2037                             WifiMetricsProto.ConnectionEvent.TYPE_WPA3;
2038                 } else if (WifiConfigurationUtil.isConfigForWapiPskNetwork(config)) {
2039                     currentConnectionEvent.mConnectionEvent.networkType =
2040                             WifiMetricsProto.ConnectionEvent.TYPE_WAPI;
2041                 } else if (WifiConfigurationUtil.isConfigForWapiCertNetwork(config)) {
2042                     currentConnectionEvent.mConnectionEvent.networkType =
2043                             WifiMetricsProto.ConnectionEvent.TYPE_WAPI;
2044                 } else if (WifiConfigurationUtil.isConfigForPskNetwork(config)) {
2045                     currentConnectionEvent.mConnectionEvent.networkType =
2046                             WifiMetricsProto.ConnectionEvent.TYPE_WPA2;
2047                 } else if (WifiConfigurationUtil.isConfigForEnterpriseNetwork(config)) {
2048                     currentConnectionEvent.mConnectionEvent.networkType =
2049                             WifiMetricsProto.ConnectionEvent.TYPE_EAP;
2050                 } else if (WifiConfigurationUtil.isConfigForOweNetwork(config)) {
2051                     currentConnectionEvent.mConnectionEvent.networkType =
2052                             WifiMetricsProto.ConnectionEvent.TYPE_OWE;
2053                 } else if (WifiConfigurationUtil.isConfigForOpenNetwork(config)) {
2054                     currentConnectionEvent.mConnectionEvent.networkType =
2055                             WifiMetricsProto.ConnectionEvent.TYPE_OPEN;
2056                 }
2057 
2058                 if (!config.fromWifiNetworkSuggestion) {
2059                     currentConnectionEvent.mConnectionEvent.networkCreator =
2060                             WifiMetricsProto.ConnectionEvent.CREATOR_USER;
2061                 } else if (config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) {
2062                     currentConnectionEvent.mConnectionEvent.networkCreator =
2063                             WifiMetricsProto.ConnectionEvent.CREATOR_CARRIER;
2064                 } else {
2065                     currentConnectionEvent.mConnectionEvent.networkCreator =
2066                             WifiMetricsProto.ConnectionEvent.CREATOR_UNKNOWN;
2067                 }
2068 
2069                 currentConnectionEvent.mConnectionEvent.screenOn = mScreenOn;
2070                 if (currentConnectionEvent.mConfigSsid != null) {
2071                     WifiScoreCard.NetworkConnectionStats recentStats = mWifiScoreCard.lookupNetwork(
2072                             currentConnectionEvent.mConfigSsid).getRecentStats();
2073                     currentConnectionEvent.mConnectionEvent.numConsecutiveConnectionFailure =
2074                             recentStats.getCount(WifiScoreCard.CNT_CONSECUTIVE_CONNECTION_FAILURE);
2075                 }
2076 
2077                 String ssid = currentConnectionEvent.mConfigSsid;
2078                 int nominator = currentConnectionEvent.mConnectionEvent.connectionNominator;
2079                 int trigger = WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__TRIGGER__UNKNOWN;
2080 
2081                 if (nominator == WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL) {
2082                     trigger = WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__TRIGGER__MANUAL;
2083                 } else if (mPreviousSession == null) {
2084                     trigger = WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__TRIGGER__AUTOCONNECT_BOOT;
2085                 } else if (ssid != null && ssid.equals(mPreviousSession.mSsid)) {
2086                     trigger = WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__TRIGGER__RECONNECT_SAME_NETWORK;
2087                 } else if (nominator != WifiMetricsProto.ConnectionEvent.NOMINATOR_UNKNOWN) {
2088                     trigger = WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__TRIGGER__AUTOCONNECT_CONFIGURED_NETWORK;
2089                 }
2090                 currentConnectionEvent.mTrigger = trigger;
2091             }
2092 
2093             return overlapWithLastConnectionMs;
2094         }
2095     }
2096 
2097     /**
2098      * Set AP related metrics from ScanDetail
2099      */
setConnectionScanDetail(String ifaceName, ScanDetail scanDetail)2100     public void setConnectionScanDetail(String ifaceName, ScanDetail scanDetail) {
2101         synchronized (mLock) {
2102             ConnectionEvent currentConnectionEvent = mCurrentConnectionEventPerIface.get(ifaceName);
2103             if (currentConnectionEvent == null || scanDetail == null) {
2104                 return;
2105             }
2106             NetworkDetail networkDetail = scanDetail.getNetworkDetail();
2107             ScanResult scanResult = scanDetail.getScanResult();
2108             // Ensure that we have a networkDetail, and that it corresponds to the currently
2109             // tracked connection attempt
2110             if (networkDetail == null || scanResult == null
2111                     || currentConnectionEvent.mConfigSsid == null
2112                     || !currentConnectionEvent.mConfigSsid
2113                     .equals("\"" + networkDetail.getSSID() + "\"")) {
2114                 return;
2115             }
2116             updateMetricsFromNetworkDetail(currentConnectionEvent, networkDetail);
2117             updateMetricsFromScanResult(currentConnectionEvent, scanResult);
2118         }
2119     }
2120 
2121     /**
2122      * Set PMK cache status for a connection event
2123      */
setConnectionPmkCache(String ifaceName, boolean isEnabled)2124     public void setConnectionPmkCache(String ifaceName, boolean isEnabled) {
2125         synchronized (mLock) {
2126             ConnectionEvent currentConnectionEvent = mCurrentConnectionEventPerIface.get(ifaceName);
2127             if (currentConnectionEvent != null) {
2128                 currentConnectionEvent.mRouterFingerPrint.setPmkCache(isEnabled);
2129             }
2130         }
2131     }
2132 
2133     /**
2134      * Set channel width of the current connection.
2135      */
setConnectionChannelWidth(String interfaceName, @WifiAnnotations.ChannelWidth int channelWidth)2136     public void setConnectionChannelWidth(String interfaceName,
2137             @WifiAnnotations.ChannelWidth int channelWidth) {
2138         synchronized (mLock) {
2139             ConnectionEvent currentConnectionEvent = mCurrentConnectionEventPerIface.get(
2140                     interfaceName);
2141             if (currentConnectionEvent != null) {
2142                 currentConnectionEvent.mRouterFingerPrint.mChannelWidth = channelWidth;
2143             }
2144         }
2145     }
2146 
2147     /**
2148      * Set the max link speed supported by current network
2149      */
setConnectionMaxSupportedLinkSpeedMbps( String ifaceName, int maxSupportedTxLinkSpeedMbps, int maxSupportedRxLinkSpeedMbps)2150     public void setConnectionMaxSupportedLinkSpeedMbps(
2151             String ifaceName, int maxSupportedTxLinkSpeedMbps, int maxSupportedRxLinkSpeedMbps) {
2152         synchronized (mLock) {
2153             ConnectionEvent currentConnectionEvent = mCurrentConnectionEventPerIface.get(ifaceName);
2154             if (currentConnectionEvent != null) {
2155                 currentConnectionEvent.mRouterFingerPrint.setMaxSupportedLinkSpeedMbps(
2156                         maxSupportedTxLinkSpeedMbps, maxSupportedRxLinkSpeedMbps);
2157             }
2158         }
2159     }
2160 
toMetricEapType(int eapType)2161     private int toMetricEapType(int eapType) {
2162         switch (eapType) {
2163             case WifiEnterpriseConfig.Eap.TLS:
2164                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__EAP_TYPE__TYPE_EAP_TLS;
2165             case WifiEnterpriseConfig.Eap.TTLS:
2166                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__EAP_TYPE__TYPE_EAP_TTLS;
2167             case WifiEnterpriseConfig.Eap.SIM:
2168                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__EAP_TYPE__TYPE_EAP_SIM;
2169             case WifiEnterpriseConfig.Eap.AKA:
2170                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__EAP_TYPE__TYPE_EAP_AKA;
2171             case WifiEnterpriseConfig.Eap.AKA_PRIME:
2172                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__EAP_TYPE__TYPE_EAP_AKA_PRIME;
2173             case WifiEnterpriseConfig.Eap.WAPI_CERT:
2174                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__EAP_TYPE__TYPE_EAP_WAPI_CERT;
2175             case WifiEnterpriseConfig.Eap.UNAUTH_TLS:
2176                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__EAP_TYPE__TYPE_EAP_UNAUTH_TLS;
2177             case WifiEnterpriseConfig.Eap.PEAP:
2178                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__EAP_TYPE__TYPE_EAP_PEAP;
2179             case WifiEnterpriseConfig.Eap.PWD:
2180                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__EAP_TYPE__TYPE_EAP_PWD;
2181             default:
2182                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__EAP_TYPE__TYPE_EAP_OTHERS;
2183         }
2184     }
2185 
toMetricPhase2Method(int phase2Method)2186     private int toMetricPhase2Method(int phase2Method) {
2187         switch (phase2Method) {
2188             case WifiEnterpriseConfig.Phase2.PAP:
2189                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__EAP_INNER_METHOD__METHOD_PAP;
2190             case WifiEnterpriseConfig.Phase2.MSCHAP:
2191                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__EAP_INNER_METHOD__METHOD_MSCHAP;
2192             case WifiEnterpriseConfig.Phase2.MSCHAPV2:
2193                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__EAP_INNER_METHOD__METHOD_MSCHAP_V2;
2194             default:
2195                 return  WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__EAP_INNER_METHOD__METHOD_OTHERS;
2196         }
2197     }
2198 
2199     /**
2200      * End a Connection event record. Call when wifi connection attempt succeeds or fails.
2201      * If a Connection event has not been started and is active when .end is called, then this
2202      * method will do nothing.
2203      *
2204      * @param ifaceName
2205      * @param level2FailureCode Level 2 failure code returned by supplicant
2206      * @param connectivityFailureCode WifiMetricsProto.ConnectionEvent.HLF_X
2207      * @param level2FailureReason Breakdown of level2FailureCode with more detailed reason
2208      */
endConnectionEvent( String ifaceName, int level2FailureCode, int connectivityFailureCode, int level2FailureReason, int frequency, int statusCode)2209     public void endConnectionEvent(
2210             String ifaceName,
2211             int level2FailureCode,
2212             int connectivityFailureCode,
2213             int level2FailureReason,
2214             int frequency,
2215             int statusCode) {
2216         synchronized (mLock) {
2217             ConnectionEvent currentConnectionEvent = mCurrentConnectionEventPerIface.get(ifaceName);
2218             if (currentConnectionEvent != null) {
2219                 boolean connectionSucceeded = (level2FailureCode == 1)
2220                         && (connectivityFailureCode == WifiMetricsProto.ConnectionEvent.HLF_NONE);
2221 
2222                 int band = KnownBandsChannelHelper.getBand(frequency);
2223                 int durationTakenToConnectMillis =
2224                         (int) (mClock.getElapsedSinceBootMillis()
2225                                 - currentConnectionEvent.mConnectionEvent.startTimeSinceBootMillis);
2226 
2227                 if (connectionSucceeded) {
2228                     mCurrentSession = new SessionData(currentConnectionEvent,
2229                             currentConnectionEvent.mConfigSsid,
2230                             mClock.getElapsedSinceBootMillis(),
2231                             band, currentConnectionEvent.mAuthType);
2232                     if (currentConnectionEvent.mRole == WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_PRIMARY) {
2233                         WifiStatsLog.write(WifiStatsLog.WIFI_CONNECTION_STATE_CHANGED,
2234                                 true, band, currentConnectionEvent.mAuthType);
2235                     }
2236                 }
2237 
2238                 currentConnectionEvent.mConnectionEvent.connectionResult =
2239                         connectionSucceeded ? 1 : 0;
2240                 currentConnectionEvent.mConnectionEvent.durationTakenToConnectMillis =
2241                         durationTakenToConnectMillis;
2242                 currentConnectionEvent.mConnectionEvent.level2FailureCode = level2FailureCode;
2243                 currentConnectionEvent.mConnectionEvent.connectivityLevelFailureCode =
2244                         connectivityFailureCode;
2245                 currentConnectionEvent.mConnectionEvent.level2FailureReason = level2FailureReason;
2246 
2247                 // Write metrics to statsd
2248                 int wwFailureCode = getConnectionResultFailureCode(level2FailureCode,
2249                         level2FailureReason);
2250                 int timeSinceConnectedSeconds = (int) ((mPreviousSession != null
2251                         ? (mClock.getElapsedSinceBootMillis()
2252                                 - mPreviousSession.mSessionEndTimeMillis) :
2253                         mClock.getElapsedSinceBootMillis()) / 1000);
2254                 WifiStatsLog.write(WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED,
2255                         connectionSucceeded,
2256                         wwFailureCode, currentConnectionEvent.mConnectionEvent.signalStrength,
2257                         durationTakenToConnectMillis, band, currentConnectionEvent.mAuthType,
2258                         currentConnectionEvent.mTrigger,
2259                         currentConnectionEvent.mHasEverConnected,
2260                         timeSinceConnectedSeconds,
2261                         currentConnectionEvent.mIsCarrierWifi,
2262                         currentConnectionEvent.mIsOobPseudonymEnabled,
2263                         currentConnectionEvent.mRole,
2264                         statusCode,
2265                         toMetricEapType(currentConnectionEvent.mEapType),
2266                         toMetricPhase2Method(currentConnectionEvent.mPhase2Method),
2267                         currentConnectionEvent.mPasspointRoamingType,
2268                         currentConnectionEvent.mCarrierId,
2269                         currentConnectionEvent.mTofuConnectionState,
2270                         currentConnectionEvent.mUid);
2271 
2272                 if (connectionSucceeded) {
2273                     reportRouterCapabilities(currentConnectionEvent.mRouterFingerPrint);
2274                 }
2275                 // ConnectionEvent already added to ConnectionEvents List. Safe to remove here.
2276                 mCurrentConnectionEventPerIface.remove(ifaceName);
2277                 if (!connectionSucceeded) {
2278                     mScanResultRssiTimestampMillis = -1;
2279                 }
2280                 mWifiStatusBuilder.setConnected(connectionSucceeded);
2281             }
2282         }
2283     }
2284 
convertTofuConnectionStateToProto(WifiConfiguration config)2285     protected static int convertTofuConnectionStateToProto(WifiConfiguration config) {
2286         if (!config.isEnterprise()) {
2287             return WifiStatsLog
2288                     .WIFI_CONFIGURED_NETWORK_INFO__TOFU_CONFIGURATION__TOFU_CONFIGURATION_UNSPECIFIED;
2289         }
2290 
2291         switch (config.enterpriseConfig.getTofuConnectionState()) {
2292             case WifiEnterpriseConfig.TOFU_STATE_NOT_ENABLED:
2293                 return WifiStatsLog
2294                         .WIFI_CONFIGURED_NETWORK_INFO__TOFU_CONFIGURATION__TOFU_CONFIGURATION_NOT_ENABLED;
2295             case WifiEnterpriseConfig.TOFU_STATE_ENABLED_PRE_CONNECTION:
2296                 return WifiStatsLog
2297                         .WIFI_CONFIGURED_NETWORK_INFO__TOFU_CONFIGURATION__TOFU_CONFIGURATION_ENABLED_PRE_CONNECTION;
2298             case WifiEnterpriseConfig.TOFU_STATE_CONFIGURE_ROOT_CA:
2299                 return WifiStatsLog
2300                         .WIFI_CONFIGURED_NETWORK_INFO__TOFU_CONFIGURATION__TOFU_CONFIGURATION_CONFIGURE_ROOT_CA;
2301             case WifiEnterpriseConfig.TOFU_STATE_CERT_PINNING:
2302                 return WifiStatsLog
2303                         .WIFI_CONFIGURED_NETWORK_INFO__TOFU_CONFIGURATION__TOFU_CONFIGURATION_CERT_PINNING;
2304             default:
2305                 return WifiStatsLog
2306                         .WIFI_CONFIGURED_NETWORK_INFO__TOFU_CONFIGURATION__TOFU_CONFIGURATION_UNSPECIFIED;
2307         }
2308     }
2309 
convertTofuDialogStateToProto(WifiConfiguration config)2310     protected static int convertTofuDialogStateToProto(WifiConfiguration config) {
2311         if (!config.isEnterprise()) {
2312             return WifiStatsLog
2313                     .WIFI_CONFIGURED_NETWORK_INFO__TOFU_DIALOG_STATE__TOFU_DIALOG_STATE_UNSPECIFIED;
2314         }
2315 
2316         switch (config.enterpriseConfig.getTofuDialogState()) {
2317             case WifiEnterpriseConfig.TOFU_DIALOG_STATE_REJECTED:
2318                 return WifiStatsLog
2319                         .WIFI_CONFIGURED_NETWORK_INFO__TOFU_DIALOG_STATE__TOFU_DIALOG_STATE_REJECTED;
2320             case WifiEnterpriseConfig.TOFU_DIALOG_STATE_ACCEPTED:
2321                 return WifiStatsLog
2322                         .WIFI_CONFIGURED_NETWORK_INFO__TOFU_DIALOG_STATE__TOFU_DIALOG_STATE_ACCEPTED;
2323             default:
2324                 return WifiStatsLog
2325                         .WIFI_CONFIGURED_NETWORK_INFO__TOFU_DIALOG_STATE__TOFU_DIALOG_STATE_UNSPECIFIED;
2326         }
2327     }
2328 
convertMacRandomizationToProto( @ifiConfiguration.MacRandomizationSetting int macRandomizationSetting)2329     protected static int convertMacRandomizationToProto(
2330             @WifiConfiguration.MacRandomizationSetting int macRandomizationSetting) {
2331         switch (macRandomizationSetting) {
2332             case WifiConfiguration.RANDOMIZATION_NONE:
2333                 return WifiStatsLog
2334                         .WIFI_CONFIGURED_NETWORK_INFO__MAC_RANDOMIZATION__MAC_RANDOMIZATION_NONE;
2335             case WifiConfiguration.RANDOMIZATION_PERSISTENT:
2336                 return WifiStatsLog
2337                         .WIFI_CONFIGURED_NETWORK_INFO__MAC_RANDOMIZATION__MAC_RANDOMIZATION_PERSISTENT;
2338             case WifiConfiguration.RANDOMIZATION_NON_PERSISTENT:
2339                 return WifiStatsLog
2340                         .WIFI_CONFIGURED_NETWORK_INFO__MAC_RANDOMIZATION__MAC_RANDOMIZATION_NON_PERSISTENT;
2341             case WifiConfiguration.RANDOMIZATION_AUTO:
2342                 return WifiStatsLog
2343                         .WIFI_CONFIGURED_NETWORK_INFO__MAC_RANDOMIZATION__MAC_RANDOMIZATION_AUTO;
2344             default:
2345                 return WifiStatsLog
2346                         .WIFI_CONFIGURED_NETWORK_INFO__MAC_RANDOMIZATION__MAC_RANDOMIZATION_UNSPECIFIED;
2347         }
2348     }
2349 
convertMeteredOverrideToProto( @ifiConfiguration.MeteredOverride int meteredOverride)2350     protected static int convertMeteredOverrideToProto(
2351             @WifiConfiguration.MeteredOverride int meteredOverride) {
2352         switch (meteredOverride) {
2353             case WifiConfiguration.METERED_OVERRIDE_NONE:
2354                 return WifiStatsLog
2355                         .WIFI_CONFIGURED_NETWORK_INFO__METERED_OVERRIDE__METERED_OVERRIDE_NONE;
2356             case WifiConfiguration.METERED_OVERRIDE_METERED:
2357                 return WifiStatsLog
2358                         .WIFI_CONFIGURED_NETWORK_INFO__METERED_OVERRIDE__METERED_OVERRIDE_METERED;
2359             case WifiConfiguration.METERED_OVERRIDE_NOT_METERED:
2360                 return WifiStatsLog
2361                         .WIFI_CONFIGURED_NETWORK_INFO__METERED_OVERRIDE__METERED_OVERRIDE_NOT_METERED;
2362             default:
2363                 return WifiStatsLog
2364                         .WIFI_CONFIGURED_NETWORK_INFO__METERED_OVERRIDE__METERED_OVERRIDE_UNSPECIFIED;
2365         }
2366     }
2367 
getSecurityMode(WifiConfiguration config, boolean useCandidateParams)2368     protected static int getSecurityMode(WifiConfiguration config, boolean useCandidateParams) {
2369         SecurityParams params =
2370                 useCandidateParams
2371                         ? config.getNetworkSelectionStatus().getCandidateSecurityParams()
2372                         : config.getNetworkSelectionStatus().getLastUsedSecurityParams();
2373         if (params != null) {
2374             return params.getSecurityType();
2375         } else if (WifiConfigurationUtil.isConfigForWpa3Enterprise192BitNetwork(config)) {
2376             return WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT;
2377         } else if (WifiConfigurationUtil.isConfigForWpa3EnterpriseNetwork(config)) {
2378             return WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE;
2379         } else if (WifiConfigurationUtil.isConfigForDppNetwork(config)) {
2380             return WifiConfiguration.SECURITY_TYPE_DPP;
2381         } else if (WifiConfigurationUtil.isConfigForSaeNetwork(config)) {
2382             return WifiConfiguration.SECURITY_TYPE_SAE;
2383         } else if (WifiConfigurationUtil.isConfigForWapiPskNetwork(config)) {
2384             return WifiConfiguration.SECURITY_TYPE_WAPI_PSK;
2385         } else if (WifiConfigurationUtil.isConfigForWapiCertNetwork(config)) {
2386             return WifiConfiguration.SECURITY_TYPE_WAPI_CERT;
2387         } else if (WifiConfigurationUtil.isConfigForPskNetwork(config)) {
2388             return WifiConfiguration.SECURITY_TYPE_PSK;
2389         } else if (WifiConfigurationUtil.isConfigForOweNetwork(config)) {
2390             return WifiConfiguration.SECURITY_TYPE_OWE;
2391         } else if (WifiConfigurationUtil.isConfigForWepNetwork(config)) {
2392             return WifiConfiguration.SECURITY_TYPE_WEP;
2393         } else if (WifiConfigurationUtil.isConfigForOpenNetwork(config)) {
2394             return WifiConfiguration.SECURITY_TYPE_OPEN;
2395         } else {
2396             Log.e(TAG, "Unknown security mode for config " + config);
2397             return -1;
2398         }
2399     }
2400 
2401     /**
2402      * Check if the provided security type is enabled in the security params list.
2403      */
securityTypeEnabled(List<SecurityParams> securityParamsList, int securityType)2404     private static boolean securityTypeEnabled(List<SecurityParams> securityParamsList,
2405             int securityType) {
2406         for (SecurityParams params : securityParamsList) {
2407             if (params.isSecurityType(securityType) && params.isEnabled()) {
2408                 return true;
2409             }
2410         }
2411         return false;
2412     }
2413 
2414     /**
2415      * Check if any security parameters with the provided type were added by auto-upgrade.
2416      */
securityTypeAddedByAutoUpgrade(List<SecurityParams> securityParamsList, int securityType)2417     private static boolean securityTypeAddedByAutoUpgrade(List<SecurityParams> securityParamsList,
2418             int securityType) {
2419         for (SecurityParams params : securityParamsList) {
2420             if (params.isSecurityType(securityType) && params.isAddedByAutoUpgrade()) {
2421                 return true;
2422             }
2423         }
2424         return false;
2425     }
2426 
convertSecurityModeToProto(WifiConfiguration config)2427     protected static int convertSecurityModeToProto(WifiConfiguration config) {
2428         if (config == null || config.getDefaultSecurityParams() == null) {
2429             return WifiStatsLog.WIFI_CONFIGURED_NETWORK_INFO__CONNECTED_SECURITY_MODE__SECURITY_MODE_UNKNOWN;
2430         }
2431         SecurityParams defaultParams = config.getDefaultSecurityParams();
2432         List<SecurityParams> securityParamsList = config.getSecurityParamsList();
2433         switch (defaultParams.getSecurityType()) {
2434             case WifiConfiguration.SECURITY_TYPE_OPEN:
2435             case WifiConfiguration.SECURITY_TYPE_OWE: {
2436                 boolean openEnabled = securityTypeEnabled(
2437                         securityParamsList, WifiConfiguration.SECURITY_TYPE_OPEN);
2438                 boolean oweEnabled = securityTypeEnabled(
2439                         securityParamsList, WifiConfiguration.SECURITY_TYPE_OWE);
2440                 if (openEnabled && !oweEnabled) {
2441                     // OWE params may be disabled or may not exist.
2442                     return WifiStatsLog.WIFI_CONFIGURED_NETWORK_INFO__CONNECTED_SECURITY_MODE__SECURITY_MODE_NONE;
2443                 } else if (!openEnabled && oweEnabled) {
2444                     // Open params may get disabled via TDI.
2445                     return WifiStatsLog.WIFI_CONFIGURED_NETWORK_INFO__CONNECTED_SECURITY_MODE__SECURITY_MODE_OWE;
2446                 }
2447 
2448                 if (securityTypeAddedByAutoUpgrade(
2449                         securityParamsList, WifiConfiguration.SECURITY_TYPE_OWE)) {
2450                     // User configured this network using Open, but OWE params were auto-added.
2451                     return WifiStatsLog.WIFI_CONFIGURED_NETWORK_INFO__CONNECTED_SECURITY_MODE__SECURITY_MODE_NONE;
2452                 }
2453                 // User manually configured this network with both Open and OWE params.
2454                 return WifiStatsLog.WIFI_CONFIGURED_NETWORK_INFO__CONNECTED_SECURITY_MODE__SECURITY_MODE_OWE_TRANSITION;
2455             }
2456             case WifiConfiguration.SECURITY_TYPE_WEP:
2457                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CONNECTED_SECURITY_MODE__SECURITY_MODE_WEP;
2458             case WifiConfiguration.SECURITY_TYPE_PSK: {
2459                 boolean pskEnabled = securityTypeEnabled(
2460                         securityParamsList, WifiConfiguration.SECURITY_TYPE_PSK);
2461                 boolean saeEnabled = securityTypeEnabled(
2462                         securityParamsList, WifiConfiguration.SECURITY_TYPE_SAE);
2463                 if (pskEnabled && !saeEnabled) {
2464                     // WPA3 params may be disabled or may not exist.
2465                     return WifiStatsLog.WIFI_CONFIGURED_NETWORK_INFO__CONNECTED_SECURITY_MODE__SECURITY_MODE_WPA2_PERSONAL;
2466                 } else if (!pskEnabled && saeEnabled) {
2467                     // WPA2 params may get disabled via TDI.
2468                     return WifiStatsLog.WIFI_CONFIGURED_NETWORK_INFO__CONNECTED_SECURITY_MODE__SECURITY_MODE_WPA3_PERSONAL;
2469                 }
2470 
2471                 if (securityTypeAddedByAutoUpgrade(
2472                         securityParamsList, WifiConfiguration.SECURITY_TYPE_SAE)) {
2473                     // User configured this network using WPA2, but WPA3 params were auto-added.
2474                     return WifiStatsLog.WIFI_CONFIGURED_NETWORK_INFO__CONNECTED_SECURITY_MODE__SECURITY_MODE_WPA2_PERSONAL;
2475                 }
2476                 // User manually configured this network with both WPA2 and WPA3 params.
2477                 return WifiStatsLog.WIFI_CONFIGURED_NETWORK_INFO__CONNECTED_SECURITY_MODE__SECURITY_MODE_WPA3_WPA2_PERSONAL_TRANSITION;
2478             }
2479             case WifiConfiguration.SECURITY_TYPE_SAE:
2480                 return WifiStatsLog.WIFI_CONFIGURED_NETWORK_INFO__CONNECTED_SECURITY_MODE__SECURITY_MODE_WPA3_PERSONAL;
2481             case WifiConfiguration.SECURITY_TYPE_WAPI_PSK:
2482                 return WifiStatsLog.WIFI_CONFIGURED_NETWORK_INFO__CONNECTED_SECURITY_MODE__SECURITY_MODE_WAPI_PSK;
2483             case WifiConfiguration.SECURITY_TYPE_WAPI_CERT:
2484                 return WifiStatsLog.WIFI_CONFIGURED_NETWORK_INFO__CONNECTED_SECURITY_MODE__SECURITY_MODE_WAPI_CERT;
2485             case WifiConfiguration.SECURITY_TYPE_DPP:
2486                 return WifiStatsLog.WIFI_CONFIGURED_NETWORK_INFO__CONNECTED_SECURITY_MODE__SECURITY_MODE_DPP;
2487             case WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT:
2488                 return WifiStatsLog.WIFI_CONFIGURED_NETWORK_INFO__CONNECTED_SECURITY_MODE__SECURITY_MODE_WPA3_ENTERPRISE_192_BIT;
2489             case WifiConfiguration.SECURITY_TYPE_EAP:
2490             case WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE:
2491             case WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2:
2492             case WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3: {
2493                 if (WifiConfigurationUtil.isConfigForWpa3EnterpriseNetwork(config)) {
2494                     return WifiStatsLog.WIFI_CONFIGURED_NETWORK_INFO__CONNECTED_SECURITY_MODE__SECURITY_MODE_WPA3_ENTERPRISE;
2495                 }
2496                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CONNECTED_SECURITY_MODE__SECURITY_MODE_WPA_ENTERPRISE_LEGACY;
2497             }
2498             default:
2499                 return WifiStatsLog.WIFI_CONFIGURED_NETWORK_INFO__CONNECTED_SECURITY_MODE__SECURITY_MODE_INVALID;
2500         }
2501     }
2502 
convertSecurityModeToProto(@ifiConfiguration.SecurityType int securityMode)2503     static int convertSecurityModeToProto(@WifiConfiguration.SecurityType int securityMode) {
2504         switch (securityMode) {
2505             case WifiConfiguration.SECURITY_TYPE_OPEN:
2506                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CONNECTED_SECURITY_MODE__SECURITY_MODE_NONE;
2507             case WifiConfiguration.SECURITY_TYPE_WEP:
2508                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CONNECTED_SECURITY_MODE__SECURITY_MODE_WEP;
2509             case WifiConfiguration.SECURITY_TYPE_PSK:
2510                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CONNECTED_SECURITY_MODE__SECURITY_MODE_WPA2_PERSONAL;
2511             case WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2:
2512                 // Passpoint R1 & R2 uses WPA2 Enterprise (Legacy)
2513             case WifiConfiguration.SECURITY_TYPE_EAP:
2514                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CONNECTED_SECURITY_MODE__SECURITY_MODE_WPA_ENTERPRISE_LEGACY;
2515             case WifiConfiguration.SECURITY_TYPE_SAE:
2516                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CONNECTED_SECURITY_MODE__SECURITY_MODE_WPA3_PERSONAL;
2517             case WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT:
2518                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CONNECTED_SECURITY_MODE__SECURITY_MODE_WPA3_ENTERPRISE_192_BIT;
2519             case WifiConfiguration.SECURITY_TYPE_OWE:
2520                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CONNECTED_SECURITY_MODE__SECURITY_MODE_OWE;
2521             case WifiConfiguration.SECURITY_TYPE_WAPI_PSK:
2522                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CONNECTED_SECURITY_MODE__SECURITY_MODE_WAPI_PSK;
2523             case WifiConfiguration.SECURITY_TYPE_WAPI_CERT:
2524                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CONNECTED_SECURITY_MODE__SECURITY_MODE_WAPI_CERT;
2525             case WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3:
2526                 // Passpoint R3 uses WPA3 Enterprise
2527             case WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE:
2528                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CONNECTED_SECURITY_MODE__SECURITY_MODE_WPA3_ENTERPRISE;
2529             case WifiConfiguration.SECURITY_TYPE_DPP:
2530                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CONNECTED_SECURITY_MODE__SECURITY_MODE_DPP;
2531             default:
2532                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CONNECTED_SECURITY_MODE__SECURITY_MODE_UNKNOWN;
2533         }
2534     }
2535 
convertHsReleasetoProto(NetworkDetail.HSRelease hsRelease)2536     private int convertHsReleasetoProto(NetworkDetail.HSRelease hsRelease) {
2537         if (hsRelease == NetworkDetail.HSRelease.R1) {
2538             return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__PASSPOINT_RELEASE__PASSPOINT_RELEASE_1;
2539         } else if (hsRelease == NetworkDetail.HSRelease.R2) {
2540             return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__PASSPOINT_RELEASE__PASSPOINT_RELEASE_2;
2541         } else if (hsRelease == NetworkDetail.HSRelease.R3) {
2542             return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__PASSPOINT_RELEASE__PASSPOINT_RELEASE_3;
2543         } else {
2544             return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__PASSPOINT_RELEASE__PASSPOINT_RELEASE_UNKNOWN;
2545         }
2546     }
2547 
convertApType6GhzToProto(ApType6GHz apType6Ghz)2548     private int convertApType6GhzToProto(ApType6GHz apType6Ghz) {
2549         if (apType6Ghz == ApType6GHz.AP_TYPE_6GHZ_INDOOR) {
2550             return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__AP_TYPE_6GHZ__AP_TYPE_6GHZ_INDOOR;
2551         } else if (apType6Ghz == ApType6GHz.AP_TYPE_6GHZ_STANDARD_POWER) {
2552             return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__AP_TYPE_6GHZ__AP_TYPE_6GHZ_STANDARD_POWER;
2553         } else {
2554             return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__AP_TYPE_6GHZ__AP_TYPE_6HZ_UNKNOWN;
2555         }
2556     }
2557 
convertWifiStandardToProto(int wifiMode)2558     private int convertWifiStandardToProto(int wifiMode) {
2559         switch (wifiMode) {
2560             case WifiMode.MODE_11A:
2561             case WifiMode.MODE_11B:
2562             case WifiMode.MODE_11G:
2563                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__STANDARD__WIFI_STANDARD_LEGACY;
2564             case WifiMode.MODE_11N:
2565                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__STANDARD__WIFI_STANDARD_11N;
2566             case WifiMode.MODE_11AC:
2567                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__STANDARD__WIFI_STANDARD_11AC;
2568             case WifiMode.MODE_11AX:
2569                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__STANDARD__WIFI_STANDARD_11AX;
2570             case WifiMode.MODE_11BE:
2571                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__STANDARD__WIFI_STANDARD_11BE;
2572             case WifiMode.MODE_UNDEFINED:
2573             default:
2574                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__STANDARD__WIFI_STANDARD_UNKNOWN;
2575         }
2576 
2577     }
2578 
convertEapMethodToProto(WifiConfiguration config)2579     protected static int convertEapMethodToProto(WifiConfiguration config) {
2580         if (config.enterpriseConfig == null) {
2581             return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_TYPE__TYPE_UNKNOWN;
2582         }
2583         return convertEapMethodToProto(config.enterpriseConfig.getEapMethod());
2584     }
2585 
convertEapMethodToProto(int eapMethod)2586     private static int convertEapMethodToProto(int eapMethod) {
2587         switch (eapMethod) {
2588             case WifiMetricsProto.RouterFingerPrint.TYPE_EAP_WAPI_CERT:
2589                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_TYPE__TYPE_EAP_WAPI_CERT;
2590             case WifiMetricsProto.RouterFingerPrint.TYPE_EAP_TLS:
2591                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_TYPE__TYPE_EAP_TLS;
2592             case WifiMetricsProto.RouterFingerPrint.TYPE_EAP_UNAUTH_TLS:
2593                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_TYPE__TYPE_EAP_UNAUTH_TLS;
2594             case WifiMetricsProto.RouterFingerPrint.TYPE_EAP_PEAP:
2595                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_TYPE__TYPE_EAP_PEAP;
2596             case WifiMetricsProto.RouterFingerPrint.TYPE_EAP_PWD:
2597                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_TYPE__TYPE_EAP_PWD;
2598             case WifiMetricsProto.RouterFingerPrint.TYPE_EAP_TTLS:
2599                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_TYPE__TYPE_EAP_TTLS;
2600             case WifiMetricsProto.RouterFingerPrint.TYPE_EAP_SIM:
2601                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_TYPE__TYPE_EAP_SIM;
2602             case WifiMetricsProto.RouterFingerPrint.TYPE_EAP_AKA:
2603                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_TYPE__TYPE_EAP_AKA;
2604             case WifiMetricsProto.RouterFingerPrint.TYPE_EAP_AKA_PRIME:
2605                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_TYPE__TYPE_EAP_AKA_PRIME;
2606             default:
2607                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_TYPE__TYPE_UNKNOWN;
2608         }
2609     }
2610 
convertEapInnerMethodToProto(WifiConfiguration config)2611     protected static int convertEapInnerMethodToProto(WifiConfiguration config) {
2612         if (config.enterpriseConfig == null) {
2613             return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_INNER_METHOD__METHOD_UNKNOWN;
2614         }
2615         int phase2Method = config.enterpriseConfig.getPhase2Method();
2616         return convertEapInnerMethodToProto(getAuthPhase2MethodProto(phase2Method));
2617     }
2618 
convertEapInnerMethodToProto(int phase2Method)2619     private static int convertEapInnerMethodToProto(int phase2Method) {
2620         switch (phase2Method) {
2621             case WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_PAP:
2622                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_INNER_METHOD__METHOD_PAP;
2623             case WifiEnterpriseConfig.Phase2.MSCHAP:
2624                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_INNER_METHOD__METHOD_MSCHAP;
2625             case WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_MSCHAPV2:
2626                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_INNER_METHOD__METHOD_MSCHAP_V2;
2627             case WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_GTC:
2628                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_INNER_METHOD__METHOD_GTC;
2629             case WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_SIM:
2630                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_INNER_METHOD__METHOD_SIM;
2631             case WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_AKA:
2632                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_INNER_METHOD__METHOD_AKA;
2633             case WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_AKA_PRIME:
2634                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_INNER_METHOD__METHOD_AKA_PRIME;
2635             default:
2636                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__EAP_INNER_METHOD__METHOD_UNKNOWN;
2637         }
2638     }
2639 
convertOcspTypeToProto(int ocspType)2640     private int convertOcspTypeToProto(int ocspType) {
2641         switch (ocspType) {
2642             case WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_NONE:
2643                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__OCSP_TYPE__TYPE_OCSP_NONE;
2644             case WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_REQUEST_CERT_STATUS:
2645                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__OCSP_TYPE__TYPE_OCSP_REQUEST_CERT_STATUS;
2646             case WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_REQUIRE_CERT_STATUS:
2647                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__OCSP_TYPE__TYPE_OCSP_REQUIRE_CERT_STATUS;
2648             case WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS:
2649                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__OCSP_TYPE__TYPE_OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS;
2650             default:
2651                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__OCSP_TYPE__TYPE_OCSP_UNKNOWN;
2652         }
2653     }
2654 
isFreeOpenRoaming(WifiConfiguration config)2655     protected static boolean isFreeOpenRoaming(WifiConfiguration config) {
2656         return Utils.getRoamingType(config)
2657                 == WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__PASSPOINT_ROAMING_TYPE__ROAMING_RCOI_OPENROAMING_FREE;
2658     }
2659 
isSettledOpenRoaming(WifiConfiguration config)2660     protected static boolean isSettledOpenRoaming(WifiConfiguration config) {
2661         return Utils.getRoamingType(config)
2662                 == WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__PASSPOINT_ROAMING_TYPE__ROAMING_RCOI_OPENROAMING_SETTLED;
2663     }
2664 
convertChannelWidthToProto(@ifiAnnotations.ChannelWidth int channelWidth)2665     private int convertChannelWidthToProto(@WifiAnnotations.ChannelWidth int channelWidth) {
2666         switch(channelWidth) {
2667             case ScanResult.CHANNEL_WIDTH_20MHZ:
2668                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CHANNEL_WIDTH_MHZ__CHANNEL_WIDTH_20MHZ;
2669             case ScanResult.CHANNEL_WIDTH_40MHZ:
2670                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CHANNEL_WIDTH_MHZ__CHANNEL_WIDTH_40MHZ;
2671             case ScanResult.CHANNEL_WIDTH_80MHZ:
2672                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CHANNEL_WIDTH_MHZ__CHANNEL_WIDTH_80MHZ;
2673             case ScanResult.CHANNEL_WIDTH_160MHZ:
2674                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CHANNEL_WIDTH_MHZ__CHANNEL_WIDTH_160MHZ;
2675             case ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ:
2676                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CHANNEL_WIDTH_MHZ__CHANNEL_WIDTH_80MHZ_PLUS_MHZ;
2677             case ScanResult.CHANNEL_WIDTH_320MHZ:
2678                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CHANNEL_WIDTH_MHZ__CHANNEL_WIDTH_320MHZ;
2679             default:
2680                 return WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CHANNEL_WIDTH_MHZ__CHANNEL_WIDTH_UNKNOWN;
2681         }
2682     }
2683 
reportRouterCapabilities(RouterFingerPrint r)2684     private void reportRouterCapabilities(RouterFingerPrint r) {
2685         WifiStatsLog.write(WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED,
2686                 r.mIsFrameworkInitiatedRoaming, r.mRouterFingerPrintProto.channelInfo,
2687                 KnownBandsChannelHelper.getBand(r.mRouterFingerPrintProto.channelInfo),
2688                 r.mRouterFingerPrintProto.dtim, convertSecurityModeToProto(r.mSecurityMode),
2689                 r.mRouterFingerPrintProto.hidden, r.mIsIncorrectlyConfiguredAsHidden,
2690                 convertWifiStandardToProto(r.mWifiStandard), r.mIs11bSupported,
2691                 convertEapMethodToProto(r.mRouterFingerPrintProto.eapMethod),
2692                 convertEapInnerMethodToProto(r.mRouterFingerPrintProto.authPhase2Method),
2693                 convertOcspTypeToProto(r.mRouterFingerPrintProto.ocspType),
2694                 r.mRouterFingerPrintProto.pmkCacheEnabled, r.mIsMboSupported, r.mIsOceSupported,
2695                 r.mIsFilsSupported, r.mIsTwtRequired, r.mIsIndividualTwtSupported,
2696                 r.mIsBroadcastTwtSupported, r.mIsRestrictedTwtSupported, r.mIs11McSupported,
2697                 r.mIs11AzSupported, convertHsReleasetoProto(r.mHsRelease),
2698                 r.mRouterFingerPrintProto.isPasspointHomeProvider,
2699                 convertApType6GhzToProto(r.mApType6GHz), r.mIsEcpsPriorityAccessSupported,
2700                 convertChannelWidthToProto(r.mChannelWidth));
2701     }
2702 
2703     /**
2704      * Report that an active Wifi network connection was dropped.
2705      *
2706      * @param disconnectReason Error code for the disconnect.
2707      * @param rssi Last seen RSSI.
2708      * @param linkSpeed Last seen link speed.
2709      */
reportNetworkDisconnect(String ifaceName, int disconnectReason, int rssi, int linkSpeed, long lastRssiUpdateMillis)2710     public void reportNetworkDisconnect(String ifaceName, int disconnectReason, int rssi,
2711             int linkSpeed, long lastRssiUpdateMillis) {
2712         synchronized (mLock) {
2713             if (!isPrimary(ifaceName)) {
2714                 return;
2715             }
2716             if (mCurrentSession != null) {
2717                 if (mCurrentSession.mConnectionEvent.mRole == WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_PRIMARY) {
2718                     WifiStatsLog.write(WifiStatsLog.WIFI_CONNECTION_STATE_CHANGED,
2719                             false,
2720                             mCurrentSession.mBand,
2721                             mCurrentSession.mAuthType);
2722                 }
2723                 mCurrentSession.mSessionEndTimeMillis = mClock.getElapsedSinceBootMillis();
2724                 int durationSeconds = (int) (mCurrentSession.mSessionEndTimeMillis
2725                         - mCurrentSession.mSessionStartTimeMillis) / 1000;
2726                 int connectedSinceLastRoamSeconds = (int) (mCurrentSession.mSessionEndTimeMillis
2727                         - mCurrentSession.mLastRoamCompleteMillis) / 1000;
2728                 int timeSinceLastRssiUpdateSeconds = (int) (mClock.getElapsedSinceBootMillis()
2729                         - lastRssiUpdateMillis) / 1000;
2730 
2731                 WifiStatsLog.write(WifiStatsLog.WIFI_DISCONNECT_REPORTED,
2732                         durationSeconds,
2733                         disconnectReason,
2734                         mCurrentSession.mBand,
2735                         mCurrentSession.mAuthType,
2736                         rssi,
2737                         linkSpeed,
2738                         timeSinceLastRssiUpdateSeconds,
2739                         connectedSinceLastRoamSeconds,
2740                         mCurrentSession.mConnectionEvent.mRole,
2741                         toMetricEapType(mCurrentSession.mConnectionEvent.mEapType),
2742                         toMetricPhase2Method(mCurrentSession.mConnectionEvent.mPhase2Method),
2743                         mCurrentSession.mConnectionEvent.mPasspointRoamingType,
2744                         mCurrentSession.mConnectionEvent.mCarrierId,
2745                         mCurrentSession.mConnectionEvent.mUid);
2746 
2747                 mPreviousSession = mCurrentSession;
2748                 mCurrentSession = null;
2749             }
2750         }
2751     }
2752 
2753     /**
2754      * Report an airplane mode session.
2755      *
2756      * @param wifiOnBeforeEnteringApm Whether Wi-Fi is on before entering airplane mode
2757      * @param wifiOnAfterEnteringApm Whether Wi-Fi is on after entering airplane mode
2758      * @param wifiOnBeforeExitingApm Whether Wi-Fi is on before exiting airplane mode
2759      * @param apmEnhancementActive Whether the user has activated the airplane mode enhancement
2760      *                            feature by toggling Wi-Fi in airplane mode
2761      * @param userToggledWifiDuringApm Whether the user toggled Wi-Fi during the current
2762      *                                  airplane mode
2763      * @param userToggledWifiAfterEnteringApmWithinMinute Whether the user toggled Wi-Fi within one
2764      *                                                    minute of entering airplane mode
2765      */
reportAirplaneModeSession(boolean wifiOnBeforeEnteringApm, boolean wifiOnAfterEnteringApm, boolean wifiOnBeforeExitingApm, boolean apmEnhancementActive, boolean userToggledWifiDuringApm, boolean userToggledWifiAfterEnteringApmWithinMinute)2766     public void reportAirplaneModeSession(boolean wifiOnBeforeEnteringApm,
2767             boolean wifiOnAfterEnteringApm, boolean wifiOnBeforeExitingApm,
2768             boolean apmEnhancementActive, boolean userToggledWifiDuringApm,
2769             boolean userToggledWifiAfterEnteringApmWithinMinute) {
2770         WifiStatsLog.write(WifiStatsLog.AIRPLANE_MODE_SESSION_REPORTED,
2771                 WifiStatsLog.AIRPLANE_MODE_SESSION_REPORTED__PACKAGE_NAME__WIFI,
2772                 wifiOnBeforeEnteringApm, wifiOnAfterEnteringApm, wifiOnBeforeExitingApm,
2773                 apmEnhancementActive, userToggledWifiDuringApm,
2774                 userToggledWifiAfterEnteringApmWithinMinute, false);
2775     }
2776 
2777     /**
2778      * Report a Wi-Fi state change.
2779      *
2780      * @param wifiState Whether Wi-Fi is enabled
2781      * @param wifiWakeState Whether Wi-Fi Wake is enabled
2782      * @param enabledByWifiWake Whether Wi-Fi was enabled by Wi-Fi Wake
2783      */
reportWifiStateChanged(boolean wifiState, boolean wifiWakeState, boolean enabledByWifiWake)2784     public void reportWifiStateChanged(boolean wifiState, boolean wifiWakeState,
2785             boolean enabledByWifiWake) {
2786         WifiStatsLog.write(WifiStatsLog.WIFI_STATE_CHANGED, wifiState, wifiWakeState,
2787                 enabledByWifiWake);
2788     }
2789 
getConnectionResultFailureCode(int level2FailureCode, int level2FailureReason)2790     private int getConnectionResultFailureCode(int level2FailureCode, int level2FailureReason) {
2791         switch (level2FailureCode) {
2792             case ConnectionEvent.FAILURE_NONE:
2793                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_UNKNOWN;
2794             case ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT:
2795                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_ASSOCIATION_TIMEOUT;
2796             case ConnectionEvent.FAILURE_ASSOCIATION_REJECTION:
2797                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_ASSOCIATION_REJECTION;
2798             case ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE:
2799                 switch (level2FailureReason) {
2800                     case WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_EAP_FAILURE:
2801                         return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_AUTHENTICATION_EAP;
2802                     case WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD:
2803                         return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_WRONG_PASSWORD;
2804                     default:
2805                         return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_AUTHENTICATION_GENERAL;
2806                 }
2807             case ConnectionEvent.FAILURE_DHCP:
2808                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_DHCP;
2809             case ConnectionEvent.FAILURE_NETWORK_DISCONNECTION:
2810                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_NETWORK_DISCONNECTION;
2811             case ConnectionEvent.FAILURE_ROAM_TIMEOUT:
2812                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_ROAM_TIMEOUT;
2813             case ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED:
2814                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_CONNECT_NETWORK_FAILED;
2815             case ConnectionEvent.FAILURE_NEW_CONNECTION_ATTEMPT:
2816                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_NEW_CONNECTION_ATTEMPT;
2817             case ConnectionEvent.FAILURE_REDUNDANT_CONNECTION_ATTEMPT:
2818                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_REDUNDANT_CONNECTION_ATTEMPT;
2819             case ConnectionEvent.FAILURE_NETWORK_NOT_FOUND:
2820                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_NETWORK_NOT_FOUND;
2821             case ConnectionEvent.FAILURE_NO_RESPONSE:
2822                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_NO_RESPONSE;
2823             default:
2824                 return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_OTHERS;
2825         }
2826     }
2827 
2828     /**
2829      * Set ConnectionEvent DTIM Interval (if set), and 802.11 Connection mode, from NetworkDetail
2830      */
updateMetricsFromNetworkDetail( ConnectionEvent currentConnectionEvent, NetworkDetail networkDetail)2831     private void updateMetricsFromNetworkDetail(
2832             ConnectionEvent currentConnectionEvent, NetworkDetail networkDetail) {
2833         int dtimInterval = networkDetail.getDtimInterval();
2834         if (dtimInterval > 0) {
2835             currentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.dtim =
2836                     dtimInterval;
2837         }
2838 
2839         if (currentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.hidden
2840                 && !networkDetail.isHiddenBeaconFrame()) {
2841             currentConnectionEvent.mRouterFingerPrint.mIsIncorrectlyConfiguredAsHidden = true;
2842         }
2843 
2844         final int connectionWifiMode;
2845         switch (networkDetail.getWifiMode()) {
2846             case InformationElementUtil.WifiMode.MODE_UNDEFINED:
2847                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_UNKNOWN;
2848                 break;
2849             case InformationElementUtil.WifiMode.MODE_11A:
2850                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_A;
2851                 break;
2852             case InformationElementUtil.WifiMode.MODE_11B:
2853                 currentConnectionEvent.mRouterFingerPrint.mIs11bSupported = true;
2854                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_B;
2855                 break;
2856             case InformationElementUtil.WifiMode.MODE_11G:
2857                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_G;
2858                 break;
2859             case InformationElementUtil.WifiMode.MODE_11N:
2860                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_N;
2861                 break;
2862             case InformationElementUtil.WifiMode.MODE_11AC  :
2863                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_AC;
2864                 break;
2865             case InformationElementUtil.WifiMode.MODE_11AX  :
2866                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_AX;
2867                 break;
2868             default:
2869                 connectionWifiMode = WifiMetricsProto.RouterFingerPrint.ROUTER_TECH_OTHER;
2870                 break;
2871         }
2872         currentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.routerTechnology =
2873                 connectionWifiMode;
2874         currentConnectionEvent.mRouterFingerPrint.mWifiStandard = networkDetail.getWifiMode();
2875 
2876         if (networkDetail.isMboSupported()) {
2877             mWifiLogProto.numConnectToNetworkSupportingMbo++;
2878             if (networkDetail.isOceSupported()) {
2879                 mWifiLogProto.numConnectToNetworkSupportingOce++;
2880             }
2881         }
2882 
2883         currentConnectionEvent.mRouterFingerPrint.mApType6GHz =
2884                 networkDetail.getApType6GHz();
2885         currentConnectionEvent.mRouterFingerPrint.mIsBroadcastTwtSupported =
2886                 networkDetail.isBroadcastTwtSupported();
2887         currentConnectionEvent.mRouterFingerPrint.mIsRestrictedTwtSupported =
2888                 networkDetail.isRestrictedTwtSupported();
2889         currentConnectionEvent.mRouterFingerPrint.mIsIndividualTwtSupported =
2890                 networkDetail.isIndividualTwtSupported();
2891         currentConnectionEvent.mRouterFingerPrint.mIsTwtRequired = networkDetail.isTwtRequired();
2892         currentConnectionEvent.mRouterFingerPrint.mIsFilsSupported = networkDetail.isFilsCapable();
2893         currentConnectionEvent.mRouterFingerPrint.mIs11AzSupported =
2894                 networkDetail.is80211azNtbResponder() || networkDetail.is80211azTbResponder();
2895         currentConnectionEvent.mRouterFingerPrint.mIs11McSupported =
2896                 networkDetail.is80211McResponderSupport();
2897         currentConnectionEvent.mRouterFingerPrint.mIsMboSupported = networkDetail.isMboSupported();
2898         currentConnectionEvent.mRouterFingerPrint.mIsOceSupported = networkDetail.isOceSupported();
2899         currentConnectionEvent.mRouterFingerPrint.mIsEcpsPriorityAccessSupported =
2900                 networkDetail.isEpcsPriorityAccessSupported();
2901         currentConnectionEvent.mRouterFingerPrint.mHsRelease = networkDetail.getHSRelease();
2902     }
2903 
2904     /**
2905      * Set ConnectionEvent RSSI and authentication type from ScanResult
2906      */
updateMetricsFromScanResult( ConnectionEvent currentConnectionEvent, ScanResult scanResult)2907     private void updateMetricsFromScanResult(
2908             ConnectionEvent currentConnectionEvent, ScanResult scanResult) {
2909         currentConnectionEvent.mConnectionEvent.signalStrength = scanResult.level;
2910         currentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication =
2911                 WifiMetricsProto.RouterFingerPrint.AUTH_OPEN;
2912         currentConnectionEvent.mConfigBssid = scanResult.BSSID;
2913         if (scanResult.capabilities != null) {
2914             if (ScanResultUtil.isScanResultForWepNetwork(scanResult)) {
2915                 currentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication =
2916                         WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL;
2917             } else if (ScanResultUtil.isScanResultForPskNetwork(scanResult)
2918                     || ScanResultUtil.isScanResultForSaeNetwork(scanResult)) {
2919                 currentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication =
2920                         WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL;
2921             } else if (ScanResultUtil.isScanResultForWpa3EnterpriseTransitionNetwork(scanResult)
2922                     || ScanResultUtil.isScanResultForWpa3EnterpriseOnlyNetwork(scanResult)
2923                     || ScanResultUtil.isScanResultForWpa2EnterpriseOnlyNetwork(scanResult)
2924                     || ScanResultUtil.isScanResultForEapSuiteBNetwork(scanResult)) {
2925                 currentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.authentication =
2926                         WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE;
2927             }
2928         }
2929         currentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto.channelInfo =
2930                 scanResult.frequency;
2931     }
2932 
setIsLocationEnabled(boolean enabled)2933     void setIsLocationEnabled(boolean enabled) {
2934         synchronized (mLock) {
2935             mWifiLogProto.isLocationEnabled = enabled;
2936         }
2937     }
2938 
setIsScanningAlwaysEnabled(boolean enabled)2939     void setIsScanningAlwaysEnabled(boolean enabled) {
2940         synchronized (mLock) {
2941             mWifiLogProto.isScanningAlwaysEnabled = enabled;
2942         }
2943     }
2944 
2945     /**
2946      * Developer options toggle value for verbose logging.
2947      */
setVerboseLoggingEnabled(boolean enabled)2948     public void setVerboseLoggingEnabled(boolean enabled) {
2949         synchronized (mLock) {
2950             mWifiLogProto.isVerboseLoggingEnabled = enabled;
2951         }
2952     }
2953 
2954     /**
2955      * Developer options toggle value for non-persistent MAC randomization.
2956      */
setNonPersistentMacRandomizationForceEnabled(boolean enabled)2957     public void setNonPersistentMacRandomizationForceEnabled(boolean enabled) {
2958         synchronized (mLock) {
2959             mWifiLogProto.isEnhancedMacRandomizationForceEnabled = enabled;
2960         }
2961     }
2962 
2963     /**
2964      * Wifi wake feature toggle.
2965      */
setWifiWakeEnabled(boolean enabled)2966     public void setWifiWakeEnabled(boolean enabled) {
2967         synchronized (mLock) {
2968             mWifiLogProto.isWifiWakeEnabled = enabled;
2969         }
2970     }
2971 
2972     /**
2973      * Increment Non Empty Scan Results count
2974      */
incrementNonEmptyScanResultCount()2975     public void incrementNonEmptyScanResultCount() {
2976         if (DBG) Log.v(TAG, "incrementNonEmptyScanResultCount");
2977         synchronized (mLock) {
2978             mWifiLogProto.numNonEmptyScanResults++;
2979         }
2980     }
2981 
2982     /**
2983      * Increment Empty Scan Results count
2984      */
incrementEmptyScanResultCount()2985     public void incrementEmptyScanResultCount() {
2986         if (DBG) Log.v(TAG, "incrementEmptyScanResultCount");
2987         synchronized (mLock) {
2988             mWifiLogProto.numEmptyScanResults++;
2989         }
2990     }
2991 
2992     /**
2993      * Increment background scan count
2994      */
incrementBackgroundScanCount()2995     public void incrementBackgroundScanCount() {
2996         if (DBG) Log.v(TAG, "incrementBackgroundScanCount");
2997         synchronized (mLock) {
2998             mWifiLogProto.numBackgroundScans++;
2999         }
3000     }
3001 
3002     /**
3003      * Get Background scan count
3004      */
getBackgroundScanCount()3005     public int getBackgroundScanCount() {
3006         synchronized (mLock) {
3007             return mWifiLogProto.numBackgroundScans;
3008         }
3009     }
3010 
3011     /**
3012      * Increment oneshot scan count, and the associated WifiSystemScanStateCount entry
3013      */
incrementOneshotScanCount()3014     public void incrementOneshotScanCount() {
3015         synchronized (mLock) {
3016             mWifiLogProto.numOneshotScans++;
3017         }
3018         incrementWifiSystemScanStateCount(mWifiState, mScreenOn);
3019     }
3020 
3021     /**
3022      * Increment the count of oneshot scans that include DFS channels.
3023      */
incrementOneshotScanWithDfsCount()3024     public void incrementOneshotScanWithDfsCount() {
3025         synchronized (mLock) {
3026             mWifiLogProto.numOneshotHasDfsChannelScans++;
3027         }
3028     }
3029 
3030     /**
3031      * Increment connectivity oneshot scan count.
3032      */
incrementConnectivityOneshotScanCount()3033     public void incrementConnectivityOneshotScanCount() {
3034         synchronized (mLock) {
3035             mWifiLogProto.numConnectivityOneshotScans++;
3036         }
3037     }
3038 
3039     /**
3040      * Get oneshot scan count
3041      */
getOneshotScanCount()3042     public int getOneshotScanCount() {
3043         synchronized (mLock) {
3044             return mWifiLogProto.numOneshotScans;
3045         }
3046     }
3047 
3048     /**
3049      * Get connectivity oneshot scan count
3050      */
getConnectivityOneshotScanCount()3051     public int getConnectivityOneshotScanCount() {
3052         synchronized (mLock) {
3053             return mWifiLogProto.numConnectivityOneshotScans;
3054         }
3055     }
3056 
3057     /**
3058      * Get the count of oneshot scan requests that included DFS channels.
3059      */
getOneshotScanWithDfsCount()3060     public int getOneshotScanWithDfsCount() {
3061         synchronized (mLock) {
3062             return mWifiLogProto.numOneshotHasDfsChannelScans;
3063         }
3064     }
3065 
3066     /**
3067      * Increment oneshot scan count for external apps.
3068      */
incrementExternalAppOneshotScanRequestsCount()3069     public void incrementExternalAppOneshotScanRequestsCount() {
3070         synchronized (mLock) {
3071             mWifiLogProto.numExternalAppOneshotScanRequests++;
3072         }
3073     }
3074     /**
3075      * Increment oneshot scan throttle count for external foreground apps.
3076      */
incrementExternalForegroundAppOneshotScanRequestsThrottledCount()3077     public void incrementExternalForegroundAppOneshotScanRequestsThrottledCount() {
3078         synchronized (mLock) {
3079             mWifiLogProto.numExternalForegroundAppOneshotScanRequestsThrottled++;
3080         }
3081     }
3082 
3083     /**
3084      * Increment oneshot scan throttle count for external background apps.
3085      */
incrementExternalBackgroundAppOneshotScanRequestsThrottledCount()3086     public void incrementExternalBackgroundAppOneshotScanRequestsThrottledCount() {
3087         synchronized (mLock) {
3088             mWifiLogProto.numExternalBackgroundAppOneshotScanRequestsThrottled++;
3089         }
3090     }
3091 
returnCodeToString(int scanReturnCode)3092     private String returnCodeToString(int scanReturnCode) {
3093         switch(scanReturnCode){
3094             case WifiMetricsProto.WifiLog.SCAN_UNKNOWN:
3095                 return "SCAN_UNKNOWN";
3096             case WifiMetricsProto.WifiLog.SCAN_SUCCESS:
3097                 return "SCAN_SUCCESS";
3098             case WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED:
3099                 return "SCAN_FAILURE_INTERRUPTED";
3100             case WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION:
3101                 return "SCAN_FAILURE_INVALID_CONFIGURATION";
3102             case WifiMetricsProto.WifiLog.FAILURE_WIFI_DISABLED:
3103                 return "FAILURE_WIFI_DISABLED";
3104             default:
3105                 return "<UNKNOWN>";
3106         }
3107     }
3108 
3109     /**
3110      * Increment count of scan return code occurrence
3111      *
3112      * @param scanReturnCode Return code from scan attempt WifiMetricsProto.WifiLog.SCAN_X
3113      */
incrementScanReturnEntry(int scanReturnCode, int countToAdd)3114     public void incrementScanReturnEntry(int scanReturnCode, int countToAdd) {
3115         synchronized (mLock) {
3116             if (DBG) Log.v(TAG, "incrementScanReturnEntry " + returnCodeToString(scanReturnCode));
3117             int entry = mScanReturnEntries.get(scanReturnCode);
3118             entry += countToAdd;
3119             mScanReturnEntries.put(scanReturnCode, entry);
3120         }
3121     }
3122     /**
3123      * Get the count of this scanReturnCode
3124      * @param scanReturnCode that we are getting the count for
3125      */
getScanReturnEntry(int scanReturnCode)3126     public int getScanReturnEntry(int scanReturnCode) {
3127         synchronized (mLock) {
3128             return mScanReturnEntries.get(scanReturnCode);
3129         }
3130     }
3131 
wifiSystemStateToString(int state)3132     private String wifiSystemStateToString(int state) {
3133         switch(state){
3134             case WifiMetricsProto.WifiLog.WIFI_UNKNOWN:
3135                 return "WIFI_UNKNOWN";
3136             case WifiMetricsProto.WifiLog.WIFI_DISABLED:
3137                 return "WIFI_DISABLED";
3138             case WifiMetricsProto.WifiLog.WIFI_DISCONNECTED:
3139                 return "WIFI_DISCONNECTED";
3140             case WifiMetricsProto.WifiLog.WIFI_ASSOCIATED:
3141                 return "WIFI_ASSOCIATED";
3142             default:
3143                 return "default";
3144         }
3145     }
3146 
3147     /**
3148      * Increments the count of scans initiated by each wifi state, accounts for screenOn/Off
3149      *
3150      * @param state State of the system when scan was initiated, see WifiMetricsProto.WifiLog.WIFI_X
3151      * @param screenOn Is the screen on
3152      */
incrementWifiSystemScanStateCount(int state, boolean screenOn)3153     public void incrementWifiSystemScanStateCount(int state, boolean screenOn) {
3154         synchronized (mLock) {
3155             if (DBG) {
3156                 Log.v(TAG, "incrementWifiSystemScanStateCount " + wifiSystemStateToString(state)
3157                         + " " + screenOn);
3158             }
3159             int index = (state * 2) + (screenOn ? SCREEN_ON : SCREEN_OFF);
3160             int entry = mWifiSystemStateEntries.get(index);
3161             entry++;
3162             mWifiSystemStateEntries.put(index, entry);
3163         }
3164     }
3165 
3166     /**
3167      * Get the count of this system State Entry
3168      */
getSystemStateCount(int state, boolean screenOn)3169     public int getSystemStateCount(int state, boolean screenOn) {
3170         synchronized (mLock) {
3171             int index = state * 2 + (screenOn ? SCREEN_ON : SCREEN_OFF);
3172             return mWifiSystemStateEntries.get(index);
3173         }
3174     }
3175 
3176     /**
3177      * Increment number of times the Watchdog of Last Resort triggered, resetting the wifi stack
3178      */
incrementNumLastResortWatchdogTriggers()3179     public void incrementNumLastResortWatchdogTriggers() {
3180         synchronized (mLock) {
3181             mWifiLogProto.numLastResortWatchdogTriggers++;
3182         }
3183     }
3184     /**
3185      * @param count number of networks over bad association threshold when watchdog triggered
3186      */
addCountToNumLastResortWatchdogBadAssociationNetworksTotal(int count)3187     public void addCountToNumLastResortWatchdogBadAssociationNetworksTotal(int count) {
3188         synchronized (mLock) {
3189             mWifiLogProto.numLastResortWatchdogBadAssociationNetworksTotal += count;
3190         }
3191     }
3192     /**
3193      * @param count number of networks over bad authentication threshold when watchdog triggered
3194      */
addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal(int count)3195     public void addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal(int count) {
3196         synchronized (mLock) {
3197             mWifiLogProto.numLastResortWatchdogBadAuthenticationNetworksTotal += count;
3198         }
3199     }
3200     /**
3201      * @param count number of networks over bad dhcp threshold when watchdog triggered
3202      */
addCountToNumLastResortWatchdogBadDhcpNetworksTotal(int count)3203     public void addCountToNumLastResortWatchdogBadDhcpNetworksTotal(int count) {
3204         synchronized (mLock) {
3205             mWifiLogProto.numLastResortWatchdogBadDhcpNetworksTotal += count;
3206         }
3207     }
3208     /**
3209      * @param count number of networks over bad other threshold when watchdog triggered
3210      */
addCountToNumLastResortWatchdogBadOtherNetworksTotal(int count)3211     public void addCountToNumLastResortWatchdogBadOtherNetworksTotal(int count) {
3212         synchronized (mLock) {
3213             mWifiLogProto.numLastResortWatchdogBadOtherNetworksTotal += count;
3214         }
3215     }
3216     /**
3217      * @param count number of networks seen when watchdog triggered
3218      */
addCountToNumLastResortWatchdogAvailableNetworksTotal(int count)3219     public void addCountToNumLastResortWatchdogAvailableNetworksTotal(int count) {
3220         synchronized (mLock) {
3221             mWifiLogProto.numLastResortWatchdogAvailableNetworksTotal += count;
3222         }
3223     }
3224     /**
3225      * Increment count of triggers with atleast one bad association network
3226      */
incrementNumLastResortWatchdogTriggersWithBadAssociation()3227     public void incrementNumLastResortWatchdogTriggersWithBadAssociation() {
3228         synchronized (mLock) {
3229             mWifiLogProto.numLastResortWatchdogTriggersWithBadAssociation++;
3230         }
3231     }
3232     /**
3233      * Increment count of triggers with atleast one bad authentication network
3234      */
incrementNumLastResortWatchdogTriggersWithBadAuthentication()3235     public void incrementNumLastResortWatchdogTriggersWithBadAuthentication() {
3236         synchronized (mLock) {
3237             mWifiLogProto.numLastResortWatchdogTriggersWithBadAuthentication++;
3238         }
3239     }
3240     /**
3241      * Increment count of triggers with atleast one bad dhcp network
3242      */
incrementNumLastResortWatchdogTriggersWithBadDhcp()3243     public void incrementNumLastResortWatchdogTriggersWithBadDhcp() {
3244         synchronized (mLock) {
3245             mWifiLogProto.numLastResortWatchdogTriggersWithBadDhcp++;
3246         }
3247     }
3248     /**
3249      * Increment count of triggers with atleast one bad other network
3250      */
incrementNumLastResortWatchdogTriggersWithBadOther()3251     public void incrementNumLastResortWatchdogTriggersWithBadOther() {
3252         synchronized (mLock) {
3253             mWifiLogProto.numLastResortWatchdogTriggersWithBadOther++;
3254         }
3255     }
3256 
3257     /**
3258      * Increment number of times connectivity watchdog confirmed pno is working
3259      */
incrementNumConnectivityWatchdogPnoGood()3260     public void incrementNumConnectivityWatchdogPnoGood() {
3261         synchronized (mLock) {
3262             mWifiLogProto.numConnectivityWatchdogPnoGood++;
3263         }
3264     }
3265     /**
3266      * Increment number of times connectivity watchdog found pno not working
3267      */
incrementNumConnectivityWatchdogPnoBad()3268     public void incrementNumConnectivityWatchdogPnoBad() {
3269         synchronized (mLock) {
3270             mWifiLogProto.numConnectivityWatchdogPnoBad++;
3271         }
3272     }
3273     /**
3274      * Increment number of times connectivity watchdog confirmed background scan is working
3275      */
incrementNumConnectivityWatchdogBackgroundGood()3276     public void incrementNumConnectivityWatchdogBackgroundGood() {
3277         synchronized (mLock) {
3278             mWifiLogProto.numConnectivityWatchdogBackgroundGood++;
3279         }
3280     }
3281     /**
3282      * Increment number of times connectivity watchdog found background scan not working
3283      */
incrementNumConnectivityWatchdogBackgroundBad()3284     public void incrementNumConnectivityWatchdogBackgroundBad() {
3285         synchronized (mLock) {
3286             mWifiLogProto.numConnectivityWatchdogBackgroundBad++;
3287         }
3288     }
3289 
3290     /**
3291      * Increment various poll related metrics, and cache performance data for StaEvent logging
3292      */
handlePollResult(String ifaceName, WifiInfo wifiInfo)3293     public void handlePollResult(String ifaceName, WifiInfo wifiInfo) {
3294         if (!isPrimary(ifaceName)) {
3295             return;
3296         }
3297         mLastPollRssi = wifiInfo.getRssi();
3298         mLastPollLinkSpeed = wifiInfo.getLinkSpeed();
3299         mLastPollFreq = wifiInfo.getFrequency();
3300         incrementRssiPollRssiCount(mLastPollFreq, mLastPollRssi);
3301         incrementLinkSpeedCount(mLastPollLinkSpeed, mLastPollRssi);
3302         mLastPollRxLinkSpeed = wifiInfo.getRxLinkSpeedMbps();
3303         incrementTxLinkSpeedBandCount(mLastPollLinkSpeed, mLastPollFreq);
3304         incrementRxLinkSpeedBandCount(mLastPollRxLinkSpeed, mLastPollFreq);
3305         mWifiStatusBuilder.setRssi(mLastPollRssi);
3306         mWifiStatusBuilder.setNetworkId(wifiInfo.getNetworkId());
3307     }
3308 
3309     /**
3310      * Increment occurence count of RSSI level from RSSI poll for the given frequency.
3311      * @param frequency (MHz)
3312      * @param rssi
3313      */
3314     @VisibleForTesting
incrementRssiPollRssiCount(int frequency, int rssi)3315     public void incrementRssiPollRssiCount(int frequency, int rssi) {
3316         if (!(rssi >= MIN_RSSI_POLL && rssi <= MAX_RSSI_POLL)) {
3317             return;
3318         }
3319         synchronized (mLock) {
3320             if (!mRssiPollCountsMap.containsKey(frequency)) {
3321                 mRssiPollCountsMap.put(frequency, new SparseIntArray());
3322             }
3323             SparseIntArray sparseIntArray = mRssiPollCountsMap.get(frequency);
3324             int count = sparseIntArray.get(rssi);
3325             sparseIntArray.put(rssi, count + 1);
3326             maybeIncrementRssiDeltaCount(rssi - mScanResultRssi);
3327         }
3328     }
3329 
3330     /**
3331      * Increment occurence count of difference between scan result RSSI and the first RSSI poll.
3332      * Ignores rssi values outside the bounds of [MIN_RSSI_DELTA, MAX_RSSI_DELTA]
3333      * mLock must be held when calling this method.
3334      */
maybeIncrementRssiDeltaCount(int rssi)3335     private void maybeIncrementRssiDeltaCount(int rssi) {
3336         // Check if this RSSI poll is close enough to a scan result RSSI to log a delta value
3337         if (mScanResultRssiTimestampMillis >= 0) {
3338             long timeDelta = mClock.getElapsedSinceBootMillis() - mScanResultRssiTimestampMillis;
3339             if (timeDelta <= TIMEOUT_RSSI_DELTA_MILLIS) {
3340                 if (rssi >= MIN_RSSI_DELTA && rssi <= MAX_RSSI_DELTA) {
3341                     int count = mRssiDeltaCounts.get(rssi);
3342                     mRssiDeltaCounts.put(rssi, count + 1);
3343                 }
3344             }
3345             mScanResultRssiTimestampMillis = -1;
3346         }
3347     }
3348 
3349     /**
3350      * Increment occurrence count of link speed.
3351      * Ignores link speed values that are lower than MIN_LINK_SPEED_MBPS
3352      * and rssi values outside the bounds of [MIN_RSSI_POLL, MAX_RSSI_POLL]
3353      */
3354     @VisibleForTesting
incrementLinkSpeedCount(int linkSpeed, int rssi)3355     public void incrementLinkSpeedCount(int linkSpeed, int rssi) {
3356         if (!(mContext.getResources().getBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled)
3357                 && linkSpeed >= MIN_LINK_SPEED_MBPS
3358                 && rssi >= MIN_RSSI_POLL
3359                 && rssi <= MAX_RSSI_POLL)) {
3360             return;
3361         }
3362         synchronized (mLock) {
3363             LinkSpeedCount linkSpeedCount = mLinkSpeedCounts.get(linkSpeed);
3364             if (linkSpeedCount == null) {
3365                 linkSpeedCount = new LinkSpeedCount();
3366                 linkSpeedCount.linkSpeedMbps = linkSpeed;
3367                 mLinkSpeedCounts.put(linkSpeed, linkSpeedCount);
3368             }
3369             linkSpeedCount.count++;
3370             linkSpeedCount.rssiSumDbm += Math.abs(rssi);
3371             linkSpeedCount.rssiSumOfSquaresDbmSq += rssi * rssi;
3372         }
3373     }
3374 
3375     /**
3376      * Increment occurrence count of Tx link speed for operating sub-band
3377      * Ignores link speed values that are lower than MIN_LINK_SPEED_MBPS
3378      * @param txLinkSpeed PHY layer Tx link speed in Mbps
3379      * @param frequency Channel frequency of beacon frames in MHz
3380      */
3381     @VisibleForTesting
incrementTxLinkSpeedBandCount(int txLinkSpeed, int frequency)3382     public void incrementTxLinkSpeedBandCount(int txLinkSpeed, int frequency) {
3383         if (!(mContext.getResources().getBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled)
3384                 && txLinkSpeed >= MIN_LINK_SPEED_MBPS)) {
3385             return;
3386         }
3387         synchronized (mLock) {
3388             if (ScanResult.is24GHz(frequency)) {
3389                 mTxLinkSpeedCount2g.increment(txLinkSpeed);
3390             } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_LOW_END_FREQ) {
3391                 mTxLinkSpeedCount5gLow.increment(txLinkSpeed);
3392             } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_MID_END_FREQ) {
3393                 mTxLinkSpeedCount5gMid.increment(txLinkSpeed);
3394             } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_HIGH_END_FREQ) {
3395                 mTxLinkSpeedCount5gHigh.increment(txLinkSpeed);
3396             } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_LOW_END_FREQ) {
3397                 mTxLinkSpeedCount6gLow.increment(txLinkSpeed);
3398             } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_MID_END_FREQ) {
3399                 mTxLinkSpeedCount6gMid.increment(txLinkSpeed);
3400             } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_HIGH_END_FREQ) {
3401                 mTxLinkSpeedCount6gHigh.increment(txLinkSpeed);
3402             }
3403         }
3404     }
3405 
3406     /**
3407      * Increment occurrence count of Rx link speed for operating sub-band
3408      * Ignores link speed values that are lower than MIN_LINK_SPEED_MBPS
3409      * @param rxLinkSpeed PHY layer Tx link speed in Mbps
3410      * @param frequency Channel frequency of beacon frames in MHz
3411      */
3412     @VisibleForTesting
incrementRxLinkSpeedBandCount(int rxLinkSpeed, int frequency)3413     public void incrementRxLinkSpeedBandCount(int rxLinkSpeed, int frequency) {
3414         if (!(mContext.getResources().getBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled)
3415                 && rxLinkSpeed >= MIN_LINK_SPEED_MBPS)) {
3416             return;
3417         }
3418         synchronized (mLock) {
3419             if (ScanResult.is24GHz(frequency)) {
3420                 mRxLinkSpeedCount2g.increment(rxLinkSpeed);
3421             } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_LOW_END_FREQ) {
3422                 mRxLinkSpeedCount5gLow.increment(rxLinkSpeed);
3423             } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_MID_END_FREQ) {
3424                 mRxLinkSpeedCount5gMid.increment(rxLinkSpeed);
3425             } else if (frequency <= KnownBandsChannelHelper.BAND_5_GHZ_HIGH_END_FREQ) {
3426                 mRxLinkSpeedCount5gHigh.increment(rxLinkSpeed);
3427             } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_LOW_END_FREQ) {
3428                 mRxLinkSpeedCount6gLow.increment(rxLinkSpeed);
3429             } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_MID_END_FREQ) {
3430                 mRxLinkSpeedCount6gMid.increment(rxLinkSpeed);
3431             } else if (frequency <= KnownBandsChannelHelper.BAND_6_GHZ_HIGH_END_FREQ) {
3432                 mRxLinkSpeedCount6gHigh.increment(rxLinkSpeed);
3433             }
3434         }
3435     }
3436 
3437     /**
3438      * Increment occurrence count of channel utilization
3439      * @param channelUtilization Channel utilization of current network
3440      * @param frequency Channel frequency of current network
3441      */
3442     @VisibleForTesting
incrementChannelUtilizationCount(int channelUtilization, int frequency)3443     public void incrementChannelUtilizationCount(int channelUtilization, int frequency) {
3444         if (channelUtilization < InformationElementUtil.BssLoad.MIN_CHANNEL_UTILIZATION
3445                 || channelUtilization > InformationElementUtil.BssLoad.MAX_CHANNEL_UTILIZATION) {
3446             return;
3447         }
3448         synchronized (mLock) {
3449             if (ScanResult.is24GHz(frequency)) {
3450                 mChannelUtilizationHistogram2G.increment(channelUtilization);
3451             } else {
3452                 mChannelUtilizationHistogramAbove2G.increment(channelUtilization);
3453             }
3454         }
3455     }
3456 
3457     /**
3458      * Increment occurrence count of Tx and Rx throughput
3459      * @param txThroughputKbps Tx throughput of current network in Kbps
3460      * @param rxThroughputKbps Rx throughput of current network in Kbps
3461      * @param frequency Channel frequency of current network in MHz
3462      */
3463     @VisibleForTesting
incrementThroughputKbpsCount(int txThroughputKbps, int rxThroughputKbps, int frequency)3464     public void incrementThroughputKbpsCount(int txThroughputKbps, int rxThroughputKbps,
3465             int frequency) {
3466         synchronized (mLock) {
3467             if (ScanResult.is24GHz(frequency)) {
3468                 if (txThroughputKbps >= 0) {
3469                     mTxThroughputMbpsHistogram2G.increment(txThroughputKbps / 1000);
3470                 }
3471                 if (rxThroughputKbps >= 0) {
3472                     mRxThroughputMbpsHistogram2G.increment(rxThroughputKbps / 1000);
3473                 }
3474             } else {
3475                 if (txThroughputKbps >= 0) {
3476                     mTxThroughputMbpsHistogramAbove2G.increment(txThroughputKbps / 1000);
3477                 }
3478                 if (rxThroughputKbps >= 0) {
3479                     mRxThroughputMbpsHistogramAbove2G.increment(rxThroughputKbps / 1000);
3480                 }
3481             }
3482             mWifiStatusBuilder.setEstimatedTxKbps(txThroughputKbps);
3483             mWifiStatusBuilder.setEstimatedRxKbps(rxThroughputKbps);
3484         }
3485     }
3486 
3487     /**
3488      * Increment count of Watchdog successes.
3489      */
incrementNumLastResortWatchdogSuccesses()3490     public void incrementNumLastResortWatchdogSuccesses() {
3491         synchronized (mLock) {
3492             mWifiLogProto.numLastResortWatchdogSuccesses++;
3493         }
3494     }
3495 
3496     /**
3497      * Increment the count of network connection failures that happened after watchdog has been
3498      * triggered.
3499      */
incrementWatchdogTotalConnectionFailureCountAfterTrigger()3500     public void incrementWatchdogTotalConnectionFailureCountAfterTrigger() {
3501         synchronized (mLock) {
3502             mWifiLogProto.watchdogTotalConnectionFailureCountAfterTrigger++;
3503         }
3504     }
3505 
3506     /**
3507      * Sets the time taken for wifi to connect after a watchdog triggers a restart.
3508      * @param milliseconds
3509      */
setWatchdogSuccessTimeDurationMs(long ms)3510     public void setWatchdogSuccessTimeDurationMs(long ms) {
3511         synchronized (mLock) {
3512             mWifiLogProto.watchdogTriggerToConnectionSuccessDurationMs = ms;
3513         }
3514     }
3515 
3516     /**
3517      * Increments the count of alerts by alert reason.
3518      *
3519      * @param reason The cause of the alert. The reason values are driver-specific.
3520      */
incrementAlertReasonCount(int reason)3521     private void incrementAlertReasonCount(int reason) {
3522         if (reason > WifiLoggerHal.WIFI_ALERT_REASON_MAX
3523                 || reason < WifiLoggerHal.WIFI_ALERT_REASON_MIN) {
3524             reason = WifiLoggerHal.WIFI_ALERT_REASON_RESERVED;
3525         }
3526         synchronized (mLock) {
3527             int alertCount = mWifiAlertReasonCounts.get(reason);
3528             mWifiAlertReasonCounts.put(reason, alertCount + 1);
3529         }
3530     }
3531 
3532     /**
3533      * Counts all the different types of networks seen in a set of scan results
3534      */
countScanResults(List<ScanDetail> scanDetails)3535     public void countScanResults(List<ScanDetail> scanDetails) {
3536         if (scanDetails == null) {
3537             return;
3538         }
3539         int totalResults = 0;
3540         int openNetworks = 0;
3541         int personalNetworks = 0;
3542         int enterpriseNetworks = 0;
3543         int hiddenNetworks = 0;
3544         int hotspot2r1Networks = 0;
3545         int hotspot2r2Networks = 0;
3546         int hotspot2r3Networks = 0;
3547         int enhacedOpenNetworks = 0;
3548         int wpa3PersonalNetworks = 0;
3549         int wpa3EnterpriseNetworks = 0;
3550         int wapiPersonalNetworks = 0;
3551         int wapiEnterpriseNetworks = 0;
3552         int mboSupportedNetworks = 0;
3553         int mboCellularDataAwareNetworks = 0;
3554         int oceSupportedNetworks = 0;
3555         int filsSupportedNetworks = 0;
3556         int band6gNetworks = 0;
3557         int band6gPscNetworks = 0;
3558         int standard11axNetworks = 0;
3559 
3560         for (ScanDetail scanDetail : scanDetails) {
3561             NetworkDetail networkDetail = scanDetail.getNetworkDetail();
3562             ScanResult scanResult = scanDetail.getScanResult();
3563             totalResults++;
3564             if (networkDetail != null) {
3565                 if (networkDetail.isHiddenBeaconFrame()) {
3566                     hiddenNetworks++;
3567                 }
3568                 if (networkDetail.getHSRelease() != null) {
3569                     if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R1) {
3570                         hotspot2r1Networks++;
3571                     } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R2) {
3572                         hotspot2r2Networks++;
3573                     } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R3) {
3574                         hotspot2r3Networks++;
3575                     }
3576                 }
3577                 if (networkDetail.isMboSupported()) {
3578                     mboSupportedNetworks++;
3579                     if (networkDetail.isMboCellularDataAware()) {
3580                         mboCellularDataAwareNetworks++;
3581                     }
3582                     if (networkDetail.isOceSupported()) {
3583                         oceSupportedNetworks++;
3584                     }
3585                 }
3586                 if (networkDetail.getWifiMode() == InformationElementUtil.WifiMode.MODE_11AX) {
3587                     standard11axNetworks++;
3588                 }
3589             }
3590             if (scanResult != null && scanResult.capabilities != null) {
3591                 if (ScanResultUtil.isScanResultForFilsSha256Network(scanResult)
3592                         || ScanResultUtil.isScanResultForFilsSha384Network(scanResult)) {
3593                     filsSupportedNetworks++;
3594                 }
3595                 if (scanResult.is6GHz()) {
3596                     band6gNetworks++;
3597                     if (scanResult.is6GhzPsc()) {
3598                         band6gPscNetworks++;
3599                     }
3600                 }
3601                 if (ScanResultUtil.isScanResultForEapSuiteBNetwork(scanResult)
3602                         || ScanResultUtil.isScanResultForWpa3EnterpriseTransitionNetwork(scanResult)
3603                         || ScanResultUtil.isScanResultForWpa3EnterpriseOnlyNetwork(scanResult)) {
3604                     wpa3EnterpriseNetworks++;
3605                 } else if (ScanResultUtil.isScanResultForWapiPskNetwork(scanResult)) {
3606                     wapiPersonalNetworks++;
3607                 } else if (ScanResultUtil.isScanResultForWapiCertNetwork(scanResult)) {
3608                     wapiEnterpriseNetworks++;
3609                 } else if (ScanResultUtil.isScanResultForWpa2EnterpriseOnlyNetwork(scanResult)) {
3610                     enterpriseNetworks++;
3611                 } else if (ScanResultUtil.isScanResultForSaeNetwork(scanResult)) {
3612                     wpa3PersonalNetworks++;
3613                 } else if (ScanResultUtil.isScanResultForPskNetwork(scanResult)
3614                         || ScanResultUtil.isScanResultForWepNetwork(scanResult)) {
3615                     personalNetworks++;
3616                 } else if (ScanResultUtil.isScanResultForOweNetwork(scanResult)) {
3617                     enhacedOpenNetworks++;
3618                 } else {
3619                     openNetworks++;
3620                 }
3621             }
3622         }
3623         synchronized (mLock) {
3624             mWifiLogProto.numTotalScanResults += totalResults;
3625             mWifiLogProto.numOpenNetworkScanResults += openNetworks;
3626             mWifiLogProto.numLegacyPersonalNetworkScanResults += personalNetworks;
3627             mWifiLogProto.numLegacyEnterpriseNetworkScanResults += enterpriseNetworks;
3628             mWifiLogProto.numEnhancedOpenNetworkScanResults += enhacedOpenNetworks;
3629             mWifiLogProto.numWpa3PersonalNetworkScanResults += wpa3PersonalNetworks;
3630             mWifiLogProto.numWpa3EnterpriseNetworkScanResults += wpa3EnterpriseNetworks;
3631             mWifiLogProto.numWapiPersonalNetworkScanResults += wapiPersonalNetworks;
3632             mWifiLogProto.numWapiEnterpriseNetworkScanResults += wapiEnterpriseNetworks;
3633             mWifiLogProto.numHiddenNetworkScanResults += hiddenNetworks;
3634             mWifiLogProto.numHotspot2R1NetworkScanResults += hotspot2r1Networks;
3635             mWifiLogProto.numHotspot2R2NetworkScanResults += hotspot2r2Networks;
3636             mWifiLogProto.numHotspot2R3NetworkScanResults += hotspot2r3Networks;
3637             mWifiLogProto.numMboSupportedNetworkScanResults += mboSupportedNetworks;
3638             mWifiLogProto.numMboCellularDataAwareNetworkScanResults += mboCellularDataAwareNetworks;
3639             mWifiLogProto.numOceSupportedNetworkScanResults += oceSupportedNetworks;
3640             mWifiLogProto.numFilsSupportedNetworkScanResults += filsSupportedNetworks;
3641             mWifiLogProto.num11AxNetworkScanResults += standard11axNetworks;
3642             mWifiLogProto.num6GNetworkScanResults += band6gNetworks;
3643             mWifiLogProto.num6GPscNetworkScanResults += band6gPscNetworks;
3644             mWifiLogProto.numScans++;
3645         }
3646     }
3647 
3648     private boolean mWifiWins = false; // Based on scores, use wifi instead of mobile data?
3649     // Based on Wifi usability scores. use wifi instead of mobile data?
3650     private boolean mWifiWinsUsabilityScore = false;
3651 
3652     /**
3653      * Increments occurence of a particular wifi score calculated
3654      * in WifiScoreReport by current connected network. Scores are bounded
3655      * within  [MIN_WIFI_SCORE, MAX_WIFI_SCORE] to limit size of SparseArray.
3656      *
3657      * Also records events when the current score breaches significant thresholds.
3658      */
incrementWifiScoreCount(String ifaceName, int score)3659     public void incrementWifiScoreCount(String ifaceName, int score) {
3660         if (score < MIN_WIFI_SCORE || score > MAX_WIFI_SCORE) {
3661             return;
3662         }
3663         synchronized (mLock) {
3664             int count = mWifiScoreCounts.get(score);
3665             mWifiScoreCounts.put(score, count + 1);
3666 
3667             boolean wifiWins = mWifiWins;
3668             if (mWifiWins && score < LOW_WIFI_SCORE) {
3669                 wifiWins = false;
3670             } else if (!mWifiWins && score > LOW_WIFI_SCORE) {
3671                 wifiWins = true;
3672             }
3673             mLastScore = score;
3674             mLastScoreNoReset = score;
3675             if (wifiWins != mWifiWins) {
3676                 mWifiWins = wifiWins;
3677                 StaEvent event = new StaEvent();
3678                 event.type = StaEvent.TYPE_SCORE_BREACH;
3679                 addStaEvent(ifaceName, event);
3680                 // Only record the first score breach by checking whether mScoreBreachLowTimeMillis
3681                 // has been set to -1
3682                 if (!wifiWins && mScoreBreachLowTimeMillis == -1) {
3683                     mScoreBreachLowTimeMillis = mClock.getElapsedSinceBootMillis();
3684                 }
3685             }
3686         }
3687     }
3688 
3689     /**
3690      * Increments occurence of the results from attempting to start SoftAp.
3691      * Maps the |result| and WifiManager |failureCode| constant to proto defined SoftApStartResult
3692      * codes.
3693      */
incrementSoftApStartResult(boolean result, int failureCode)3694     public void incrementSoftApStartResult(boolean result, int failureCode) {
3695         synchronized (mLock) {
3696             if (result) {
3697                 int count = mSoftApManagerReturnCodeCounts.get(
3698                         WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY);
3699                 mSoftApManagerReturnCodeCounts.put(
3700                         WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY,
3701                         count + 1);
3702                 return;
3703             }
3704 
3705             // now increment failure modes - if not explicitly handled, dump into the general
3706             // error bucket.
3707             if (failureCode == WifiManager.SAP_START_FAILURE_NO_CHANNEL) {
3708                 int count = mSoftApManagerReturnCodeCounts.get(
3709                         WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL);
3710                 mSoftApManagerReturnCodeCounts.put(
3711                         WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL,
3712                         count + 1);
3713             } else if (failureCode == WifiManager.SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION) {
3714                 int count = mSoftApManagerReturnCodeCounts.get(
3715                         WifiMetricsProto.SoftApReturnCodeCount
3716                         .SOFT_AP_FAILED_UNSUPPORTED_CONFIGURATION);
3717                 mSoftApManagerReturnCodeCounts.put(
3718                         WifiMetricsProto.SoftApReturnCodeCount
3719                         .SOFT_AP_FAILED_UNSUPPORTED_CONFIGURATION,
3720                         count + 1);
3721             } else {
3722                 // failure mode not tracked at this time...  count as a general error for now.
3723                 int count = mSoftApManagerReturnCodeCounts.get(
3724                         WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR);
3725                 mSoftApManagerReturnCodeCounts.put(
3726                         WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR,
3727                         count + 1);
3728             }
3729         }
3730     }
3731 
3732     /**
3733      * Adds a record indicating the current up state of soft AP
3734      */
addSoftApUpChangedEvent(boolean isUp, int mode, long defaultShutdownTimeoutMillis, boolean isBridged)3735     public void addSoftApUpChangedEvent(boolean isUp, int mode, long defaultShutdownTimeoutMillis,
3736             boolean isBridged) {
3737         int numOfEventNeedToAdd = isBridged && isUp ? 2 : 1;
3738         for (int i = 0; i < numOfEventNeedToAdd; i++) {
3739             SoftApConnectedClientsEvent event = new SoftApConnectedClientsEvent();
3740             if (isUp) {
3741                 event.eventType = isBridged ? SoftApConnectedClientsEvent.DUAL_AP_BOTH_INSTANCES_UP
3742                         : SoftApConnectedClientsEvent.SOFT_AP_UP;
3743             } else {
3744                 event.eventType = SoftApConnectedClientsEvent.SOFT_AP_DOWN;
3745             }
3746             event.numConnectedClients = 0;
3747             event.defaultShutdownTimeoutSetting = defaultShutdownTimeoutMillis;
3748             addSoftApConnectedClientsEvent(event, mode);
3749         }
3750     }
3751 
3752     /**
3753      * Adds a record indicating the one of the dual AP instances is down.
3754      */
addSoftApInstanceDownEventInDualMode(int mode, @NonNull SoftApInfo info)3755     public void addSoftApInstanceDownEventInDualMode(int mode, @NonNull SoftApInfo info) {
3756         SoftApConnectedClientsEvent event = new SoftApConnectedClientsEvent();
3757         event.eventType = SoftApConnectedClientsEvent.DUAL_AP_ONE_INSTANCE_DOWN;
3758         event.channelFrequency = info.getFrequency();
3759         event.channelBandwidth = info.getBandwidth();
3760         event.generation = info.getWifiStandardInternal();
3761         addSoftApConnectedClientsEvent(event, mode);
3762     }
3763 
3764     /**
3765      * Adds a record for current number of associated stations to soft AP
3766      */
addSoftApNumAssociatedStationsChangedEvent(int numTotalStations, int numStationsOnCurrentFrequency, int mode, @Nullable SoftApInfo info)3767     public void addSoftApNumAssociatedStationsChangedEvent(int numTotalStations,
3768             int numStationsOnCurrentFrequency, int mode, @Nullable SoftApInfo info) {
3769         SoftApConnectedClientsEvent event = new SoftApConnectedClientsEvent();
3770         event.eventType = SoftApConnectedClientsEvent.NUM_CLIENTS_CHANGED;
3771         if (info != null) {
3772             event.channelFrequency = info.getFrequency();
3773             event.channelBandwidth = info.getBandwidth();
3774             event.generation = info.getWifiStandardInternal();
3775         }
3776         event.numConnectedClients = numTotalStations;
3777         event.numConnectedClientsOnCurrentFrequency = numStationsOnCurrentFrequency;
3778         addSoftApConnectedClientsEvent(event, mode);
3779     }
3780 
3781     /**
3782      * Adds a record to the corresponding event list based on mode param
3783      */
addSoftApConnectedClientsEvent(SoftApConnectedClientsEvent event, int mode)3784     private void addSoftApConnectedClientsEvent(SoftApConnectedClientsEvent event, int mode) {
3785         synchronized (mLock) {
3786             List<SoftApConnectedClientsEvent> softApEventList;
3787             switch (mode) {
3788                 case WifiManager.IFACE_IP_MODE_TETHERED:
3789                     softApEventList = mSoftApEventListTethered;
3790                     break;
3791                 case WifiManager.IFACE_IP_MODE_LOCAL_ONLY:
3792                     softApEventList = mSoftApEventListLocalOnly;
3793                     break;
3794                 default:
3795                     return;
3796             }
3797 
3798             if (softApEventList.size() > MAX_NUM_SOFT_AP_EVENTS) {
3799                 return;
3800             }
3801 
3802             event.timeStampMillis = mClock.getElapsedSinceBootMillis();
3803             softApEventList.add(event);
3804         }
3805     }
3806 
3807     /**
3808      * Updates current soft AP events with channel info
3809      */
addSoftApChannelSwitchedEvent(List<SoftApInfo> infos, int mode, boolean isBridged)3810     public void addSoftApChannelSwitchedEvent(List<SoftApInfo> infos, int mode, boolean isBridged) {
3811         synchronized (mLock) {
3812             int numOfEventNeededToUpdate = infos.size();
3813             if (isBridged && numOfEventNeededToUpdate == 1) {
3814                 // Ignore the channel info update when only 1 info in bridged mode because it means
3815                 // that one of the instance was been shutdown.
3816                 return;
3817             }
3818             int apUpEvent = isBridged ? SoftApConnectedClientsEvent.DUAL_AP_BOTH_INSTANCES_UP
3819                     : SoftApConnectedClientsEvent.SOFT_AP_UP;
3820             List<SoftApConnectedClientsEvent> softApEventList;
3821             switch (mode) {
3822                 case WifiManager.IFACE_IP_MODE_TETHERED:
3823                     softApEventList = mSoftApEventListTethered;
3824                     break;
3825                 case WifiManager.IFACE_IP_MODE_LOCAL_ONLY:
3826                     softApEventList = mSoftApEventListLocalOnly;
3827                     break;
3828                 default:
3829                     return;
3830             }
3831 
3832             for (int index = softApEventList.size() - 1;
3833                     index >= 0 && numOfEventNeededToUpdate != 0; index--) {
3834                 SoftApConnectedClientsEvent event = softApEventList.get(index);
3835                 if (event != null && event.eventType == apUpEvent) {
3836                     int infoIndex = numOfEventNeededToUpdate - 1;
3837                     event.channelFrequency = infos.get(infoIndex).getFrequency();
3838                     event.channelBandwidth = infos.get(infoIndex).getBandwidth();
3839                     event.generation = infos.get(infoIndex).getWifiStandardInternal();
3840                     numOfEventNeededToUpdate--;
3841                 }
3842             }
3843         }
3844     }
3845 
3846     /**
3847      * Updates current soft AP events with softap configuration
3848      */
updateSoftApConfiguration(SoftApConfiguration config, int mode, boolean isBridged)3849     public void updateSoftApConfiguration(SoftApConfiguration config, int mode, boolean isBridged) {
3850         synchronized (mLock) {
3851             List<SoftApConnectedClientsEvent> softApEventList;
3852             switch (mode) {
3853                 case WifiManager.IFACE_IP_MODE_TETHERED:
3854                     softApEventList = mSoftApEventListTethered;
3855                     break;
3856                 case WifiManager.IFACE_IP_MODE_LOCAL_ONLY:
3857                     softApEventList = mSoftApEventListLocalOnly;
3858                     break;
3859                 default:
3860                     return;
3861             }
3862 
3863             int numOfEventNeededToUpdate = isBridged ? 2 : 1;
3864             int apUpEvent = isBridged ? SoftApConnectedClientsEvent.DUAL_AP_BOTH_INSTANCES_UP
3865                     : SoftApConnectedClientsEvent.SOFT_AP_UP;
3866 
3867             for (int index = softApEventList.size() - 1;
3868                     index >= 0 && numOfEventNeededToUpdate != 0; index--) {
3869                 SoftApConnectedClientsEvent event = softApEventList.get(index);
3870                 if (event != null && event.eventType == apUpEvent) {
3871                     event.maxNumClientsSettingInSoftapConfiguration =
3872                             config.getMaxNumberOfClients();
3873                     event.shutdownTimeoutSettingInSoftapConfiguration =
3874                             config.getShutdownTimeoutMillis();
3875                     event.clientControlIsEnabled = config.isClientControlByUserEnabled();
3876                     numOfEventNeededToUpdate--;
3877                 }
3878             }
3879         }
3880     }
3881 
3882     /**
3883      * Updates current soft AP events with softap capability
3884      */
updateSoftApCapability(SoftApCapability capability, int mode, boolean isBridged)3885     public void updateSoftApCapability(SoftApCapability capability, int mode, boolean isBridged) {
3886         synchronized (mLock) {
3887             List<SoftApConnectedClientsEvent> softApEventList;
3888             switch (mode) {
3889                 case WifiManager.IFACE_IP_MODE_TETHERED:
3890                     softApEventList = mSoftApEventListTethered;
3891                     break;
3892                 case WifiManager.IFACE_IP_MODE_LOCAL_ONLY:
3893                     softApEventList = mSoftApEventListLocalOnly;
3894                     break;
3895                 default:
3896                     return;
3897             }
3898 
3899             int numOfEventNeededToUpdate = isBridged ? 2 : 1;
3900             int apUpEvent = isBridged ? SoftApConnectedClientsEvent.DUAL_AP_BOTH_INSTANCES_UP
3901                     : SoftApConnectedClientsEvent.SOFT_AP_UP;
3902 
3903             for (int index = softApEventList.size() - 1;
3904                     index >= 0 && numOfEventNeededToUpdate != 0; index--) {
3905                 SoftApConnectedClientsEvent event = softApEventList.get(index);
3906                 if (event != null && event.eventType == apUpEvent) {
3907                     event.maxNumClientsSettingInSoftapCapability =
3908                             capability.getMaxSupportedClients();
3909                     numOfEventNeededToUpdate--;
3910                 }
3911             }
3912         }
3913     }
3914 
3915     /**
3916      * Increment number of times the HAL crashed.
3917      */
incrementNumHalCrashes()3918     public synchronized void incrementNumHalCrashes() {
3919         mWifiLogProto.numHalCrashes++;
3920         WifiStatsLog.write(WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED,
3921                 WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED__TYPE__HAL_CRASH);
3922     }
3923 
3924     /**
3925      * Increment number of times the Wificond crashed.
3926      */
incrementNumWificondCrashes()3927     public synchronized void incrementNumWificondCrashes() {
3928         mWifiLogProto.numWificondCrashes++;
3929         WifiStatsLog.write(WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED,
3930                 WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED__TYPE__WIFICOND_CRASH);
3931     }
3932 
3933     /**
3934      * Increment number of times the supplicant crashed.
3935      */
incrementNumSupplicantCrashes()3936     public synchronized void incrementNumSupplicantCrashes() {
3937         mWifiLogProto.numSupplicantCrashes++;
3938         WifiStatsLog.write(WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED,
3939                 WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED__TYPE__SUPPLICANT_CRASH);
3940     }
3941 
3942     /**
3943      * Increment number of times the hostapd crashed.
3944      */
incrementNumHostapdCrashes()3945     public synchronized void incrementNumHostapdCrashes() {
3946         mWifiLogProto.numHostapdCrashes++;
3947         WifiStatsLog.write(WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED,
3948                 WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED__TYPE__HOSTAPD_CRASH);
3949     }
3950 
3951     /**
3952      * Increment number of times the wifi on failed due to an error in HAL.
3953      */
incrementNumSetupClientInterfaceFailureDueToHal()3954     public synchronized void incrementNumSetupClientInterfaceFailureDueToHal() {
3955         mWifiLogProto.numSetupClientInterfaceFailureDueToHal++;
3956         WifiStatsLog.write(WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED,
3957                 WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED__TYPE__CLIENT_FAILURE_HAL);
3958     }
3959 
3960     /**
3961      * Increment number of times the wifi on failed due to an error in wificond.
3962      */
incrementNumSetupClientInterfaceFailureDueToWificond()3963     public synchronized void incrementNumSetupClientInterfaceFailureDueToWificond() {
3964         mWifiLogProto.numSetupClientInterfaceFailureDueToWificond++;
3965         WifiStatsLog.write(WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED,
3966                 WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED__TYPE__CLIENT_FAILURE_WIFICOND);
3967     }
3968 
3969     /**
3970      * Increment number of times the wifi on failed due to an error in supplicant.
3971      */
incrementNumSetupClientInterfaceFailureDueToSupplicant()3972     public synchronized void incrementNumSetupClientInterfaceFailureDueToSupplicant() {
3973         mWifiLogProto.numSetupClientInterfaceFailureDueToSupplicant++;
3974         WifiStatsLog.write(WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED,
3975                 WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED__TYPE__CLIENT_FAILURE_SUPPLICANT);
3976     }
3977 
3978     /**
3979      * Increment number of times the SoftAp on failed due to an error in HAL.
3980      */
incrementNumSetupSoftApInterfaceFailureDueToHal()3981     public synchronized void incrementNumSetupSoftApInterfaceFailureDueToHal() {
3982         mWifiLogProto.numSetupSoftApInterfaceFailureDueToHal++;
3983         WifiStatsLog.write(WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED,
3984                 WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED__TYPE__SOFT_AP_FAILURE_HAL);
3985     }
3986 
3987     /**
3988      * Increment number of times the SoftAp on failed due to an error in wificond.
3989      */
incrementNumSetupSoftApInterfaceFailureDueToWificond()3990     public synchronized void incrementNumSetupSoftApInterfaceFailureDueToWificond() {
3991         mWifiLogProto.numSetupSoftApInterfaceFailureDueToWificond++;
3992         WifiStatsLog.write(WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED,
3993                 WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED__TYPE__SOFT_AP_FAILURE_WIFICOND);
3994     }
3995 
3996     /**
3997      * Increment number of times the SoftAp on failed due to an error in hostapd.
3998      */
incrementNumSetupSoftApInterfaceFailureDueToHostapd()3999     public synchronized void incrementNumSetupSoftApInterfaceFailureDueToHostapd() {
4000         mWifiLogProto.numSetupSoftApInterfaceFailureDueToHostapd++;
4001         WifiStatsLog.write(WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED,
4002                 WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED__TYPE__SOFT_AP_FAILURE_HOSTAPD);
4003     }
4004 
4005     /**
4006      * Increment number of times the P2p on failed due to an error in HAL.
4007      */
incrementNumSetupP2pInterfaceFailureDueToHal()4008     public synchronized void incrementNumSetupP2pInterfaceFailureDueToHal() {
4009         WifiStatsLog.write(WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED,
4010                 WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED__TYPE__P2P_FAILURE_HAL);
4011     }
4012 
4013     /**
4014      * Increment number of times the P2p on failed due to an error in supplicant.
4015      */
incrementNumSetupP2pInterfaceFailureDueToSupplicant()4016     public synchronized void incrementNumSetupP2pInterfaceFailureDueToSupplicant() {
4017         WifiStatsLog.write(WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED,
4018                 WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED__TYPE__P2P_FAILURE_SUPPLICANT);
4019     }
4020 
4021     /**
4022      * Increment number of times we got client interface down.
4023      */
incrementNumClientInterfaceDown()4024     public void incrementNumClientInterfaceDown() {
4025         synchronized (mLock) {
4026             mWifiLogProto.numClientInterfaceDown++;
4027         }
4028     }
4029 
4030     /**
4031      * Increment number of times we got client interface down.
4032      */
incrementNumSoftApInterfaceDown()4033     public void incrementNumSoftApInterfaceDown() {
4034         synchronized (mLock) {
4035             mWifiLogProto.numSoftApInterfaceDown++;
4036         }
4037     }
4038 
4039     /**
4040      * Increment number of times Passpoint provider being installed.
4041      */
incrementNumPasspointProviderInstallation()4042     public void incrementNumPasspointProviderInstallation() {
4043         synchronized (mLock) {
4044             mWifiLogProto.numPasspointProviderInstallation++;
4045         }
4046     }
4047 
4048     /**
4049      * Increment number of times Passpoint provider is installed successfully.
4050      */
incrementNumPasspointProviderInstallSuccess()4051     public void incrementNumPasspointProviderInstallSuccess() {
4052         synchronized (mLock) {
4053             mWifiLogProto.numPasspointProviderInstallSuccess++;
4054         }
4055     }
4056 
4057     /**
4058      * Increment number of times Passpoint provider being uninstalled.
4059      */
incrementNumPasspointProviderUninstallation()4060     public void incrementNumPasspointProviderUninstallation() {
4061         synchronized (mLock) {
4062             mWifiLogProto.numPasspointProviderUninstallation++;
4063         }
4064     }
4065 
4066     /**
4067      * Increment number of times Passpoint provider is uninstalled successfully.
4068      */
incrementNumPasspointProviderUninstallSuccess()4069     public void incrementNumPasspointProviderUninstallSuccess() {
4070         synchronized (mLock) {
4071             mWifiLogProto.numPasspointProviderUninstallSuccess++;
4072         }
4073     }
4074 
4075     /**
4076      * Increment number of Passpoint providers with no Root CA in their profile.
4077      */
incrementNumPasspointProviderWithNoRootCa()4078     public void incrementNumPasspointProviderWithNoRootCa() {
4079         synchronized (mLock) {
4080             mWifiLogProto.numPasspointProviderWithNoRootCa++;
4081         }
4082     }
4083 
4084     /**
4085      * Increment number of Passpoint providers with a self-signed Root CA in their profile.
4086      */
incrementNumPasspointProviderWithSelfSignedRootCa()4087     public void incrementNumPasspointProviderWithSelfSignedRootCa() {
4088         synchronized (mLock) {
4089             mWifiLogProto.numPasspointProviderWithSelfSignedRootCa++;
4090         }
4091     }
4092 
4093     /**
4094      * Increment number of Passpoint providers with subscription expiration date in their profile.
4095      */
incrementNumPasspointProviderWithSubscriptionExpiration()4096     public void incrementNumPasspointProviderWithSubscriptionExpiration() {
4097         synchronized (mLock) {
4098             mWifiLogProto.numPasspointProviderWithSubscriptionExpiration++;
4099         }
4100     }
4101 
4102     /**
4103      * Increment number of times we detected a radio mode change to MCC.
4104      */
incrementNumRadioModeChangeToMcc()4105     public void incrementNumRadioModeChangeToMcc() {
4106         synchronized (mLock) {
4107             mWifiLogProto.numRadioModeChangeToMcc++;
4108         }
4109     }
4110 
4111     /**
4112      * Increment number of times we detected a radio mode change to SCC.
4113      */
incrementNumRadioModeChangeToScc()4114     public void incrementNumRadioModeChangeToScc() {
4115         synchronized (mLock) {
4116             mWifiLogProto.numRadioModeChangeToScc++;
4117         }
4118     }
4119 
4120     /**
4121      * Increment number of times we detected a radio mode change to SBS.
4122      */
incrementNumRadioModeChangeToSbs()4123     public void incrementNumRadioModeChangeToSbs() {
4124         synchronized (mLock) {
4125             mWifiLogProto.numRadioModeChangeToSbs++;
4126         }
4127     }
4128 
4129     /**
4130      * Increment number of times we detected a radio mode change to DBS.
4131      */
incrementNumRadioModeChangeToDbs()4132     public void incrementNumRadioModeChangeToDbs() {
4133         synchronized (mLock) {
4134             mWifiLogProto.numRadioModeChangeToDbs++;
4135         }
4136     }
4137 
4138     /**
4139      * Increment number of times we detected a channel did not satisfy user band preference.
4140      */
incrementNumSoftApUserBandPreferenceUnsatisfied()4141     public void incrementNumSoftApUserBandPreferenceUnsatisfied() {
4142         synchronized (mLock) {
4143             mWifiLogProto.numSoftApUserBandPreferenceUnsatisfied++;
4144         }
4145     }
4146 
4147     /**
4148      * Increment N-Way network selection decision histograms:
4149      * Counts the size of various sets of scanDetails within a scan, and increment the occurrence
4150      * of that size for the associated histogram. There are ten histograms generated for each
4151      * combination of: {SSID, BSSID} *{Total, Saved, Open, Saved_or_Open, Passpoint}
4152      * Only performs this count if isFullBand is true, otherwise, increments the partial scan count
4153      */
incrementAvailableNetworksHistograms(List<ScanDetail> scanDetails, boolean isFullBand)4154     public void incrementAvailableNetworksHistograms(List<ScanDetail> scanDetails,
4155             boolean isFullBand) {
4156         synchronized (mLock) {
4157             if (mWifiConfigManager == null || mWifiNetworkSelector == null
4158                     || mPasspointManager == null) {
4159                 return;
4160             }
4161             if (!isFullBand) {
4162                 mWifiLogProto.partialAllSingleScanListenerResults++;
4163                 return;
4164             }
4165 
4166             Set<ScanResultMatchInfo> ssids = new HashSet<ScanResultMatchInfo>();
4167             int bssids = 0;
4168             Set<ScanResultMatchInfo> openSsids = new HashSet<ScanResultMatchInfo>();
4169             int openBssids = 0;
4170             Set<ScanResultMatchInfo> savedSsids = new HashSet<ScanResultMatchInfo>();
4171             int savedBssids = 0;
4172             // openOrSavedSsids calculated from union of savedSsids & openSsids
4173             int openOrSavedBssids = 0;
4174             Set<PasspointProvider> savedPasspointProviderProfiles =
4175                     new HashSet<PasspointProvider>();
4176             int savedPasspointProviderBssids = 0;
4177             int passpointR1Aps = 0;
4178             int passpointR2Aps = 0;
4179             int passpointR3Aps = 0;
4180             Map<ANQPNetworkKey, Integer> passpointR1UniqueEss = new HashMap<>();
4181             Map<ANQPNetworkKey, Integer> passpointR2UniqueEss = new HashMap<>();
4182             Map<ANQPNetworkKey, Integer> passpointR3UniqueEss = new HashMap<>();
4183             int supporting80211mcAps = 0;
4184             for (ScanDetail scanDetail : scanDetails) {
4185                 NetworkDetail networkDetail = scanDetail.getNetworkDetail();
4186                 ScanResult scanResult = scanDetail.getScanResult();
4187 
4188                 // statistics to be collected for ALL APs (irrespective of signal power)
4189                 if (networkDetail.is80211McResponderSupport()) {
4190                     supporting80211mcAps++;
4191                 }
4192 
4193                 ScanResultMatchInfo matchInfo = ScanResultMatchInfo.fromScanResult(scanResult);
4194                 List<Pair<PasspointProvider, PasspointMatch>> matchedProviders = null;
4195                 if (networkDetail.isInterworking()) {
4196                     // Try to match provider, but do not allow new ANQP messages. Use cached data.
4197                     matchedProviders = mPasspointManager.matchProvider(scanResult, false);
4198                     if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R1) {
4199                         passpointR1Aps++;
4200                     } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R2) {
4201                         passpointR2Aps++;
4202                     } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R3) {
4203                         passpointR3Aps++;
4204                     }
4205 
4206                     long bssid = 0;
4207                     boolean validBssid = false;
4208                     try {
4209                         bssid = Utils.parseMac(scanResult.BSSID);
4210                         validBssid = true;
4211                     } catch (IllegalArgumentException e) {
4212                         Log.e(TAG,
4213                                 "Invalid BSSID provided in the scan result: " + scanResult.BSSID);
4214                     }
4215                     if (validBssid) {
4216                         ANQPNetworkKey uniqueEss = ANQPNetworkKey.buildKey(scanResult.SSID, bssid,
4217                                 scanResult.hessid, networkDetail.getAnqpDomainID());
4218                         if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R1) {
4219                             Integer countObj = passpointR1UniqueEss.get(uniqueEss);
4220                             int count = countObj == null ? 0 : countObj;
4221                             passpointR1UniqueEss.put(uniqueEss, count + 1);
4222                         } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R2) {
4223                             Integer countObj = passpointR2UniqueEss.get(uniqueEss);
4224                             int count = countObj == null ? 0 : countObj;
4225                             passpointR2UniqueEss.put(uniqueEss, count + 1);
4226                         } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R3) {
4227                             Integer countObj = passpointR3UniqueEss.get(uniqueEss);
4228                             int count = countObj == null ? 0 : countObj;
4229                             passpointR3UniqueEss.put(uniqueEss, count + 1);
4230                         }
4231                     }
4232                 }
4233 
4234                 if (mWifiNetworkSelector.isSignalTooWeak(scanResult)) {
4235                     continue;
4236                 }
4237 
4238                 // statistics to be collected ONLY for those APs with sufficient signal power
4239 
4240                 ssids.add(matchInfo);
4241                 bssids++;
4242                 boolean isOpen = ScanResultUtil.isScanResultForOpenNetwork(scanResult)
4243                         || ScanResultUtil.isScanResultForOweNetwork(scanResult);
4244                 WifiConfiguration config =
4245                         mWifiConfigManager.getSavedNetworkForScanDetail(scanDetail);
4246                 boolean isSaved = (config != null) && !config.isEphemeral()
4247                         && !config.isPasspoint();
4248                 if (isOpen) {
4249                     openSsids.add(matchInfo);
4250                     openBssids++;
4251                 }
4252                 if (isSaved) {
4253                     savedSsids.add(matchInfo);
4254                     savedBssids++;
4255                 }
4256                 if (isOpen || isSaved) {
4257                     openOrSavedBssids++;
4258                     // Calculate openOrSavedSsids union later
4259                 }
4260                 if (matchedProviders != null && !matchedProviders.isEmpty()) {
4261                     for (Pair<PasspointProvider, PasspointMatch> passpointProvider :
4262                             matchedProviders) {
4263                         savedPasspointProviderProfiles.add(passpointProvider.first);
4264                     }
4265                     savedPasspointProviderBssids++;
4266                 }
4267             }
4268             mWifiLogProto.fullBandAllSingleScanListenerResults++;
4269             incrementTotalScanSsids(mTotalSsidsInScanHistogram, ssids.size());
4270             incrementTotalScanResults(mTotalBssidsInScanHistogram, bssids);
4271             incrementSsid(mAvailableOpenSsidsInScanHistogram, openSsids.size());
4272             incrementBssid(mAvailableOpenBssidsInScanHistogram, openBssids);
4273             incrementSsid(mAvailableSavedSsidsInScanHistogram, savedSsids.size());
4274             incrementBssid(mAvailableSavedBssidsInScanHistogram, savedBssids);
4275             openSsids.addAll(savedSsids); // openSsids = Union(openSsids, savedSsids)
4276             incrementSsid(mAvailableOpenOrSavedSsidsInScanHistogram, openSsids.size());
4277             incrementBssid(mAvailableOpenOrSavedBssidsInScanHistogram, openOrSavedBssids);
4278             incrementSsid(mAvailableSavedPasspointProviderProfilesInScanHistogram,
4279                     savedPasspointProviderProfiles.size());
4280             incrementBssid(mAvailableSavedPasspointProviderBssidsInScanHistogram,
4281                     savedPasspointProviderBssids);
4282             incrementTotalPasspointAps(mObservedHotspotR1ApInScanHistogram, passpointR1Aps);
4283             incrementTotalPasspointAps(mObservedHotspotR2ApInScanHistogram, passpointR2Aps);
4284             incrementTotalPasspointAps(mObservedHotspotR3ApInScanHistogram, passpointR3Aps);
4285             incrementTotalUniquePasspointEss(mObservedHotspotR1EssInScanHistogram,
4286                     passpointR1UniqueEss.size());
4287             incrementTotalUniquePasspointEss(mObservedHotspotR2EssInScanHistogram,
4288                     passpointR2UniqueEss.size());
4289             incrementTotalUniquePasspointEss(mObservedHotspotR3EssInScanHistogram,
4290                     passpointR3UniqueEss.size());
4291             for (Integer count : passpointR1UniqueEss.values()) {
4292                 incrementPasspointPerUniqueEss(mObservedHotspotR1ApsPerEssInScanHistogram, count);
4293             }
4294             for (Integer count : passpointR2UniqueEss.values()) {
4295                 incrementPasspointPerUniqueEss(mObservedHotspotR2ApsPerEssInScanHistogram, count);
4296             }
4297             for (Integer count : passpointR3UniqueEss.values()) {
4298                 incrementPasspointPerUniqueEss(mObservedHotspotR3ApsPerEssInScanHistogram, count);
4299             }
4300             increment80211mcAps(mObserved80211mcApInScanHistogram, supporting80211mcAps);
4301         }
4302     }
4303 
4304     /** Increments the occurence of a "Connect to Network" notification. */
incrementConnectToNetworkNotification(String notifierTag, int notificationType)4305     public void incrementConnectToNetworkNotification(String notifierTag, int notificationType) {
4306         synchronized (mLock) {
4307             int count = mConnectToNetworkNotificationCount.get(notificationType);
4308             mConnectToNetworkNotificationCount.put(notificationType, count + 1);
4309         }
4310     }
4311 
4312     /** Increments the occurence of an "Connect to Network" notification user action. */
incrementConnectToNetworkNotificationAction(String notifierTag, int notificationType, int actionType)4313     public void incrementConnectToNetworkNotificationAction(String notifierTag,
4314             int notificationType, int actionType) {
4315         synchronized (mLock) {
4316             int key = notificationType * CONNECT_TO_NETWORK_NOTIFICATION_ACTION_KEY_MULTIPLIER
4317                     + actionType;
4318             int count = mConnectToNetworkNotificationActionCount.get(key);
4319             mConnectToNetworkNotificationActionCount.put(key, count + 1);
4320         }
4321     }
4322 
4323     /**
4324      * Sets the number of SSIDs blocklisted from recommendation by the open network notification
4325      * recommender.
4326      */
setNetworkRecommenderBlocklistSize(String notifierTag, int size)4327     public void setNetworkRecommenderBlocklistSize(String notifierTag, int size) {
4328         synchronized (mLock) {
4329             mOpenNetworkRecommenderBlocklistSize = size;
4330         }
4331     }
4332 
4333     /** Sets if the available network notification feature is enabled. */
setIsWifiNetworksAvailableNotificationEnabled(String notifierTag, boolean enabled)4334     public void setIsWifiNetworksAvailableNotificationEnabled(String notifierTag, boolean enabled) {
4335         synchronized (mLock) {
4336             mIsWifiNetworksAvailableNotificationOn = enabled;
4337         }
4338     }
4339 
4340     /** Increments the occurence of connection attempts that were initiated unsuccessfully */
incrementNumNetworkRecommendationUpdates(String notifierTag)4341     public void incrementNumNetworkRecommendationUpdates(String notifierTag) {
4342         synchronized (mLock) {
4343             mNumOpenNetworkRecommendationUpdates++;
4344         }
4345     }
4346 
4347     /** Increments the occurence of connection attempts that were initiated unsuccessfully */
incrementNumNetworkConnectMessageFailedToSend(String notifierTag)4348     public void incrementNumNetworkConnectMessageFailedToSend(String notifierTag) {
4349         synchronized (mLock) {
4350             mNumOpenNetworkConnectMessageFailedToSend++;
4351         }
4352     }
4353 
4354     /** Log firmware alert related metrics */
logFirmwareAlert(String ifaceName, int errorCode)4355     public void logFirmwareAlert(String ifaceName, int errorCode) {
4356         incrementAlertReasonCount(errorCode);
4357         logWifiIsUnusableEvent(ifaceName, WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT, errorCode);
4358         addToWifiUsabilityStatsList(ifaceName, WifiUsabilityStats.LABEL_BAD,
4359                 WifiUsabilityStats.TYPE_FIRMWARE_ALERT, errorCode);
4360     }
4361 
4362     public static final String PROTO_DUMP_ARG = "wifiMetricsProto";
4363     public static final String CLEAN_DUMP_ARG = "clean";
4364 
4365     /**
4366      * Dump all WifiMetrics. Collects some metrics from ConfigStore, Settings and WifiManager
4367      * at this time.
4368      *
4369      * @param fd unused
4370      * @param pw PrintWriter for writing dump to
4371      * @param args [wifiMetricsProto [clean]]
4372      */
dump(FileDescriptor fd, PrintWriter pw, String[] args)4373     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
4374         synchronized (mLock) {
4375             consolidateScoringParams();
4376             if (args != null && args.length > 0 && PROTO_DUMP_ARG.equals(args[0])) {
4377                 // Dump serialized WifiLog proto
4378                 consolidateProto();
4379                 byte[] wifiMetricsProto = WifiMetricsProto.WifiLog.toByteArray(mWifiLogProto);
4380                 String metricsProtoDump = Base64.encodeToString(wifiMetricsProto, Base64.DEFAULT);
4381                 if (args.length > 1 && CLEAN_DUMP_ARG.equals(args[1])) {
4382                     // Output metrics proto bytes (base64) and nothing else
4383                     pw.print(metricsProtoDump);
4384                 } else {
4385                     // Tag the start and end of the metrics proto bytes
4386                     pw.println("WifiMetrics:");
4387                     pw.println(metricsProtoDump);
4388                     pw.println("EndWifiMetrics");
4389                 }
4390                 clear();
4391             } else {
4392                 pw.println("WifiMetrics:");
4393                 pw.println("mConnectionEvents:");
4394                 for (ConnectionEvent event : mConnectionEventList) {
4395                     String eventLine = event.toString();
4396                     if (mCurrentConnectionEventPerIface.containsValue(event)) {
4397                         eventLine += " CURRENTLY OPEN EVENT";
4398                     }
4399                     pw.println(eventLine);
4400                 }
4401                 pw.println("mWifiLogProto.numSavedNetworks=" + mWifiLogProto.numSavedNetworks);
4402                 pw.println("mWifiLogProto.numSavedNetworksWithMacRandomization="
4403                         + mWifiLogProto.numSavedNetworksWithMacRandomization);
4404                 pw.println("mWifiLogProto.numOpenNetworks=" + mWifiLogProto.numOpenNetworks);
4405                 pw.println("mWifiLogProto.numLegacyPersonalNetworks="
4406                         + mWifiLogProto.numLegacyPersonalNetworks);
4407                 pw.println("mWifiLogProto.numLegacyEnterpriseNetworks="
4408                         + mWifiLogProto.numLegacyEnterpriseNetworks);
4409                 pw.println("mWifiLogProto.numEnhancedOpenNetworks="
4410                         + mWifiLogProto.numEnhancedOpenNetworks);
4411                 pw.println("mWifiLogProto.numWpa3PersonalNetworks="
4412                         + mWifiLogProto.numWpa3PersonalNetworks);
4413                 pw.println("mWifiLogProto.numWpa3EnterpriseNetworks="
4414                         + mWifiLogProto.numWpa3EnterpriseNetworks);
4415                 pw.println("mWifiLogProto.numWapiPersonalNetworks="
4416                         + mWifiLogProto.numWapiPersonalNetworks);
4417                 pw.println("mWifiLogProto.numWapiEnterpriseNetworks="
4418                         + mWifiLogProto.numWapiEnterpriseNetworks);
4419                 pw.println("mWifiLogProto.numHiddenNetworks=" + mWifiLogProto.numHiddenNetworks);
4420                 pw.println("mWifiLogProto.numPasspointNetworks="
4421                         + mWifiLogProto.numPasspointNetworks);
4422                 pw.println("mWifiLogProto.isLocationEnabled=" + mWifiLogProto.isLocationEnabled);
4423                 pw.println("mWifiLogProto.isScanningAlwaysEnabled="
4424                         + mWifiLogProto.isScanningAlwaysEnabled);
4425                 pw.println("mWifiLogProto.isVerboseLoggingEnabled="
4426                         + mWifiLogProto.isVerboseLoggingEnabled);
4427                 pw.println("mWifiLogProto.isEnhancedMacRandomizationForceEnabled="
4428                         + mWifiLogProto.isEnhancedMacRandomizationForceEnabled);
4429                 pw.println("mWifiLogProto.isWifiWakeEnabled=" + mWifiLogProto.isWifiWakeEnabled);
4430                 pw.println("mWifiLogProto.numNetworksAddedByUser="
4431                         + mWifiLogProto.numNetworksAddedByUser);
4432                 pw.println("mWifiLogProto.numNetworksAddedByApps="
4433                         + mWifiLogProto.numNetworksAddedByApps);
4434                 pw.println("mWifiLogProto.numNonEmptyScanResults="
4435                         + mWifiLogProto.numNonEmptyScanResults);
4436                 pw.println("mWifiLogProto.numEmptyScanResults="
4437                         + mWifiLogProto.numEmptyScanResults);
4438                 pw.println("mWifiLogProto.numConnecitvityOneshotScans="
4439                         + mWifiLogProto.numConnectivityOneshotScans);
4440                 pw.println("mWifiLogProto.numOneshotScans="
4441                         + mWifiLogProto.numOneshotScans);
4442                 pw.println("mWifiLogProto.numOneshotHasDfsChannelScans="
4443                         + mWifiLogProto.numOneshotHasDfsChannelScans);
4444                 pw.println("mWifiLogProto.numBackgroundScans="
4445                         + mWifiLogProto.numBackgroundScans);
4446                 pw.println("mWifiLogProto.numExternalAppOneshotScanRequests="
4447                         + mWifiLogProto.numExternalAppOneshotScanRequests);
4448                 pw.println("mWifiLogProto.numExternalForegroundAppOneshotScanRequestsThrottled="
4449                         + mWifiLogProto.numExternalForegroundAppOneshotScanRequestsThrottled);
4450                 pw.println("mWifiLogProto.numExternalBackgroundAppOneshotScanRequestsThrottled="
4451                         + mWifiLogProto.numExternalBackgroundAppOneshotScanRequestsThrottled);
4452                 pw.println("mWifiLogProto.meteredNetworkStatsSaved=");
4453                 pw.println(mMeteredNetworkStatsBuilder.toProto(false));
4454                 pw.println("mWifiLogProto.meteredNetworkStatsSuggestion=");
4455                 pw.println(mMeteredNetworkStatsBuilder.toProto(true));
4456                 pw.println("mScanReturnEntries:");
4457                 pw.println("  SCAN_UNKNOWN: " + getScanReturnEntry(
4458                         WifiMetricsProto.WifiLog.SCAN_UNKNOWN));
4459                 pw.println("  SCAN_SUCCESS: " + getScanReturnEntry(
4460                         WifiMetricsProto.WifiLog.SCAN_SUCCESS));
4461                 pw.println("  SCAN_FAILURE_INTERRUPTED: " + getScanReturnEntry(
4462                         WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED));
4463                 pw.println("  SCAN_FAILURE_INVALID_CONFIGURATION: " + getScanReturnEntry(
4464                         WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION));
4465                 pw.println("  FAILURE_WIFI_DISABLED: " + getScanReturnEntry(
4466                         WifiMetricsProto.WifiLog.FAILURE_WIFI_DISABLED));
4467 
4468                 pw.println("mSystemStateEntries: <state><screenOn> : <scansInitiated>");
4469                 pw.println("  WIFI_UNKNOWN       ON: "
4470                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, true));
4471                 pw.println("  WIFI_DISABLED      ON: "
4472                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISABLED, true));
4473                 pw.println("  WIFI_DISCONNECTED  ON: "
4474                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED, true));
4475                 pw.println("  WIFI_ASSOCIATED    ON: "
4476                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, true));
4477                 pw.println("  WIFI_UNKNOWN      OFF: "
4478                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, false));
4479                 pw.println("  WIFI_DISABLED     OFF: "
4480                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISABLED, false));
4481                 pw.println("  WIFI_DISCONNECTED OFF: "
4482                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED, false));
4483                 pw.println("  WIFI_ASSOCIATED   OFF: "
4484                         + getSystemStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, false));
4485                 pw.println("mWifiLogProto.numConnectivityWatchdogPnoGood="
4486                         + mWifiLogProto.numConnectivityWatchdogPnoGood);
4487                 pw.println("mWifiLogProto.numConnectivityWatchdogPnoBad="
4488                         + mWifiLogProto.numConnectivityWatchdogPnoBad);
4489                 pw.println("mWifiLogProto.numConnectivityWatchdogBackgroundGood="
4490                         + mWifiLogProto.numConnectivityWatchdogBackgroundGood);
4491                 pw.println("mWifiLogProto.numConnectivityWatchdogBackgroundBad="
4492                         + mWifiLogProto.numConnectivityWatchdogBackgroundBad);
4493                 pw.println("mWifiLogProto.numLastResortWatchdogTriggers="
4494                         + mWifiLogProto.numLastResortWatchdogTriggers);
4495                 pw.println("mWifiLogProto.numLastResortWatchdogBadAssociationNetworksTotal="
4496                         + mWifiLogProto.numLastResortWatchdogBadAssociationNetworksTotal);
4497                 pw.println("mWifiLogProto.numLastResortWatchdogBadAuthenticationNetworksTotal="
4498                         + mWifiLogProto.numLastResortWatchdogBadAuthenticationNetworksTotal);
4499                 pw.println("mWifiLogProto.numLastResortWatchdogBadDhcpNetworksTotal="
4500                         + mWifiLogProto.numLastResortWatchdogBadDhcpNetworksTotal);
4501                 pw.println("mWifiLogProto.numLastResortWatchdogBadOtherNetworksTotal="
4502                         + mWifiLogProto.numLastResortWatchdogBadOtherNetworksTotal);
4503                 pw.println("mWifiLogProto.numLastResortWatchdogAvailableNetworksTotal="
4504                         + mWifiLogProto.numLastResortWatchdogAvailableNetworksTotal);
4505                 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadAssociation="
4506                         + mWifiLogProto.numLastResortWatchdogTriggersWithBadAssociation);
4507                 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadAuthentication="
4508                         + mWifiLogProto.numLastResortWatchdogTriggersWithBadAuthentication);
4509                 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadDhcp="
4510                         + mWifiLogProto.numLastResortWatchdogTriggersWithBadDhcp);
4511                 pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadOther="
4512                         + mWifiLogProto.numLastResortWatchdogTriggersWithBadOther);
4513                 pw.println("mWifiLogProto.numLastResortWatchdogSuccesses="
4514                         + mWifiLogProto.numLastResortWatchdogSuccesses);
4515                 pw.println("mWifiLogProto.watchdogTotalConnectionFailureCountAfterTrigger="
4516                         + mWifiLogProto.watchdogTotalConnectionFailureCountAfterTrigger);
4517                 pw.println("mWifiLogProto.watchdogTriggerToConnectionSuccessDurationMs="
4518                         + mWifiLogProto.watchdogTriggerToConnectionSuccessDurationMs);
4519                 pw.println("mWifiLogProto.recordDurationSec="
4520                         + ((mClock.getElapsedSinceBootMillis() / 1000) - mRecordStartTimeSec));
4521 
4522                 try {
4523                     JSONObject rssiMap = new JSONObject();
4524                     for (Map.Entry<Integer, SparseIntArray> entry : mRssiPollCountsMap.entrySet()) {
4525                         int frequency = entry.getKey();
4526                         final SparseIntArray histogram = entry.getValue();
4527                         JSONArray histogramElements = new JSONArray();
4528                         for (int i = MIN_RSSI_POLL; i <= MAX_RSSI_POLL; i++) {
4529                             int count = histogram.get(i);
4530                             if (count == 0) {
4531                                 continue;
4532                             }
4533                             JSONObject histogramElement = new JSONObject();
4534                             histogramElement.put(Integer.toString(i), count);
4535                             histogramElements.put(histogramElement);
4536                         }
4537                         rssiMap.put(Integer.toString(frequency), histogramElements);
4538                     }
4539                     pw.println("mWifiLogProto.rssiPollCount: " + rssiMap.toString());
4540                 } catch (JSONException e) {
4541                     pw.println("JSONException occurred: " + e.getMessage());
4542                 }
4543 
4544                 pw.println("mWifiLogProto.rssiPollDeltaCount: Printing counts for ["
4545                         + MIN_RSSI_DELTA + ", " + MAX_RSSI_DELTA + "]");
4546                 StringBuilder sb = new StringBuilder();
4547                 for (int i = MIN_RSSI_DELTA; i <= MAX_RSSI_DELTA; i++) {
4548                     sb.append(mRssiDeltaCounts.get(i) + " ");
4549                 }
4550                 pw.println("  " + sb.toString());
4551                 pw.println("mWifiLogProto.linkSpeedCounts: ");
4552                 sb.setLength(0);
4553                 for (int i = 0; i < mLinkSpeedCounts.size(); i++) {
4554                     LinkSpeedCount linkSpeedCount = mLinkSpeedCounts.valueAt(i);
4555                     sb.append(linkSpeedCount.linkSpeedMbps).append(":{")
4556                             .append(linkSpeedCount.count).append(", ")
4557                             .append(linkSpeedCount.rssiSumDbm).append(", ")
4558                             .append(linkSpeedCount.rssiSumOfSquaresDbmSq).append("} ");
4559                 }
4560                 if (sb.length() > 0) {
4561                     pw.println(sb.toString());
4562                 }
4563                 pw.print("mWifiLogProto.alertReasonCounts=");
4564                 sb.setLength(0);
4565                 for (int i = WifiLoggerHal.WIFI_ALERT_REASON_MIN;
4566                         i <= WifiLoggerHal.WIFI_ALERT_REASON_MAX; i++) {
4567                     int count = mWifiAlertReasonCounts.get(i);
4568                     if (count > 0) {
4569                         sb.append("(" + i + "," + count + "),");
4570                     }
4571                 }
4572                 if (sb.length() > 1) {
4573                     sb.setLength(sb.length() - 1);  // strip trailing comma
4574                     pw.println(sb.toString());
4575                 } else {
4576                     pw.println("()");
4577                 }
4578                 pw.println("mWifiLogProto.numTotalScanResults="
4579                         + mWifiLogProto.numTotalScanResults);
4580                 pw.println("mWifiLogProto.numOpenNetworkScanResults="
4581                         + mWifiLogProto.numOpenNetworkScanResults);
4582                 pw.println("mWifiLogProto.numLegacyPersonalNetworkScanResults="
4583                         + mWifiLogProto.numLegacyPersonalNetworkScanResults);
4584                 pw.println("mWifiLogProto.numLegacyEnterpriseNetworkScanResults="
4585                         + mWifiLogProto.numLegacyEnterpriseNetworkScanResults);
4586                 pw.println("mWifiLogProto.numEnhancedOpenNetworkScanResults="
4587                         + mWifiLogProto.numEnhancedOpenNetworkScanResults);
4588                 pw.println("mWifiLogProto.numWpa3PersonalNetworkScanResults="
4589                         + mWifiLogProto.numWpa3PersonalNetworkScanResults);
4590                 pw.println("mWifiLogProto.numWpa3EnterpriseNetworkScanResults="
4591                         + mWifiLogProto.numWpa3EnterpriseNetworkScanResults);
4592                 pw.println("mWifiLogProto.numWapiPersonalNetworkScanResults="
4593                         + mWifiLogProto.numWapiPersonalNetworkScanResults);
4594                 pw.println("mWifiLogProto.numWapiEnterpriseNetworkScanResults="
4595                         + mWifiLogProto.numWapiEnterpriseNetworkScanResults);
4596                 pw.println("mWifiLogProto.numHiddenNetworkScanResults="
4597                         + mWifiLogProto.numHiddenNetworkScanResults);
4598                 pw.println("mWifiLogProto.numHotspot2R1NetworkScanResults="
4599                         + mWifiLogProto.numHotspot2R1NetworkScanResults);
4600                 pw.println("mWifiLogProto.numHotspot2R2NetworkScanResults="
4601                         + mWifiLogProto.numHotspot2R2NetworkScanResults);
4602                 pw.println("mWifiLogProto.numHotspot2R3NetworkScanResults="
4603                         + mWifiLogProto.numHotspot2R3NetworkScanResults);
4604                 pw.println("mWifiLogProto.numMboSupportedNetworkScanResults="
4605                         + mWifiLogProto.numMboSupportedNetworkScanResults);
4606                 pw.println("mWifiLogProto.numMboCellularDataAwareNetworkScanResults="
4607                         + mWifiLogProto.numMboCellularDataAwareNetworkScanResults);
4608                 pw.println("mWifiLogProto.numOceSupportedNetworkScanResults="
4609                         + mWifiLogProto.numOceSupportedNetworkScanResults);
4610                 pw.println("mWifiLogProto.numFilsSupportedNetworkScanResults="
4611                         + mWifiLogProto.numFilsSupportedNetworkScanResults);
4612                 pw.println("mWifiLogProto.num11AxNetworkScanResults="
4613                         + mWifiLogProto.num11AxNetworkScanResults);
4614                 pw.println("mWifiLogProto.num6GNetworkScanResults"
4615                         + mWifiLogProto.num6GNetworkScanResults);
4616                 pw.println("mWifiLogProto.num6GPscNetworkScanResults"
4617                         + mWifiLogProto.num6GPscNetworkScanResults);
4618                 pw.println("mWifiLogProto.numBssidFilteredDueToMboAssocDisallowInd="
4619                         + mWifiLogProto.numBssidFilteredDueToMboAssocDisallowInd);
4620                 pw.println("mWifiLogProto.numConnectToNetworkSupportingMbo="
4621                         + mWifiLogProto.numConnectToNetworkSupportingMbo);
4622                 pw.println("mWifiLogProto.numConnectToNetworkSupportingOce="
4623                         + mWifiLogProto.numConnectToNetworkSupportingOce);
4624                 pw.println("mWifiLogProto.numSteeringRequest="
4625                         + mWifiLogProto.numSteeringRequest);
4626                 pw.println("mWifiLogProto.numForceScanDueToSteeringRequest="
4627                         + mWifiLogProto.numForceScanDueToSteeringRequest);
4628                 pw.println("mWifiLogProto.numMboCellularSwitchRequest="
4629                         + mWifiLogProto.numMboCellularSwitchRequest);
4630                 pw.println("mWifiLogProto.numSteeringRequestIncludingMboAssocRetryDelay="
4631                         + mWifiLogProto.numSteeringRequestIncludingMboAssocRetryDelay);
4632                 pw.println("mWifiLogProto.numConnectRequestWithFilsAkm="
4633                         + mWifiLogProto.numConnectRequestWithFilsAkm);
4634                 pw.println("mWifiLogProto.numL2ConnectionThroughFilsAuthentication="
4635                         + mWifiLogProto.numL2ConnectionThroughFilsAuthentication);
4636                 pw.println("mWifiLogProto.recentFailureAssociationStatus="
4637                         + mRecentFailureAssociationStatus.toString());
4638 
4639                 pw.println("mWifiLogProto.numScans=" + mWifiLogProto.numScans);
4640                 pw.println("mWifiLogProto.WifiScoreCount: [" + MIN_WIFI_SCORE + ", "
4641                         + MAX_WIFI_SCORE + "]");
4642                 for (int i = 0; i <= MAX_WIFI_SCORE; i++) {
4643                     pw.print(mWifiScoreCounts.get(i) + " ");
4644                 }
4645                 pw.println(); // add a line after wifi scores
4646                 pw.println("mWifiLogProto.WifiUsabilityScoreCount: [" + MIN_WIFI_USABILITY_SCORE
4647                         + ", " + MAX_WIFI_USABILITY_SCORE + "]");
4648                 for (int i = MIN_WIFI_USABILITY_SCORE; i <= MAX_WIFI_USABILITY_SCORE; i++) {
4649                     pw.print(mWifiUsabilityScoreCounts.get(i) + " ");
4650                 }
4651                 pw.println(); // add a line after wifi usability scores
4652                 pw.println("mWifiLogProto.SoftApManagerReturnCodeCounts:");
4653                 pw.println("  SUCCESS: " + mSoftApManagerReturnCodeCounts.get(
4654                         WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY));
4655                 pw.println("  FAILED_GENERAL_ERROR: " + mSoftApManagerReturnCodeCounts.get(
4656                         WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR));
4657                 pw.println("  FAILED_NO_CHANNEL: " + mSoftApManagerReturnCodeCounts.get(
4658                         WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL));
4659                 pw.println("  FAILED_UNSUPPORTED_CONFIGURATION: "
4660                         + mSoftApManagerReturnCodeCounts.get(
4661                         WifiMetricsProto.SoftApReturnCodeCount
4662                         .SOFT_AP_FAILED_UNSUPPORTED_CONFIGURATION));
4663                 pw.print("\n");
4664                 pw.println("mWifiLogProto.numHalCrashes="
4665                         + mWifiLogProto.numHalCrashes);
4666                 pw.println("mWifiLogProto.numWificondCrashes="
4667                         + mWifiLogProto.numWificondCrashes);
4668                 pw.println("mWifiLogProto.numSupplicantCrashes="
4669                         + mWifiLogProto.numSupplicantCrashes);
4670                 pw.println("mWifiLogProto.numHostapdCrashes="
4671                         + mWifiLogProto.numHostapdCrashes);
4672                 pw.println("mWifiLogProto.numSetupClientInterfaceFailureDueToHal="
4673                         + mWifiLogProto.numSetupClientInterfaceFailureDueToHal);
4674                 pw.println("mWifiLogProto.numSetupClientInterfaceFailureDueToWificond="
4675                         + mWifiLogProto.numSetupClientInterfaceFailureDueToWificond);
4676                 pw.println("mWifiLogProto.numSetupClientInterfaceFailureDueToSupplicant="
4677                         + mWifiLogProto.numSetupClientInterfaceFailureDueToSupplicant);
4678                 pw.println("mWifiLogProto.numSetupSoftApInterfaceFailureDueToHal="
4679                         + mWifiLogProto.numSetupSoftApInterfaceFailureDueToHal);
4680                 pw.println("mWifiLogProto.numSetupSoftApInterfaceFailureDueToWificond="
4681                         + mWifiLogProto.numSetupSoftApInterfaceFailureDueToWificond);
4682                 pw.println("mWifiLogProto.numSetupSoftApInterfaceFailureDueToHostapd="
4683                         + mWifiLogProto.numSetupSoftApInterfaceFailureDueToHostapd);
4684                 pw.println("StaEventList:");
4685                 for (StaEventWithTime event : mStaEventList) {
4686                     pw.println(event);
4687                 }
4688                 pw.println("UserActionEvents:");
4689                 for (UserActionEventWithTime event : mUserActionEventList) {
4690                     pw.println(event);
4691                 }
4692 
4693                 pw.println("mWifiLogProto.numPasspointProviders="
4694                         + mWifiLogProto.numPasspointProviders);
4695                 pw.println("mWifiLogProto.numPasspointProviderInstallation="
4696                         + mWifiLogProto.numPasspointProviderInstallation);
4697                 pw.println("mWifiLogProto.numPasspointProviderInstallSuccess="
4698                         + mWifiLogProto.numPasspointProviderInstallSuccess);
4699                 pw.println("mWifiLogProto.numPasspointProviderUninstallation="
4700                         + mWifiLogProto.numPasspointProviderUninstallation);
4701                 pw.println("mWifiLogProto.numPasspointProviderUninstallSuccess="
4702                         + mWifiLogProto.numPasspointProviderUninstallSuccess);
4703                 pw.println("mWifiLogProto.numPasspointProvidersSuccessfullyConnected="
4704                         + mWifiLogProto.numPasspointProvidersSuccessfullyConnected);
4705 
4706                 pw.println("mWifiLogProto.installedPasspointProfileTypeForR1:"
4707                         + mInstalledPasspointProfileTypeForR1);
4708                 pw.println("mWifiLogProto.installedPasspointProfileTypeForR2:"
4709                         + mInstalledPasspointProfileTypeForR2);
4710 
4711                 pw.println("mWifiLogProto.passpointProvisionStats.numProvisionSuccess="
4712                         + mNumProvisionSuccess);
4713                 pw.println("mWifiLogProto.passpointProvisionStats.provisionFailureCount:"
4714                         + mPasspointProvisionFailureCounts);
4715                 pw.println("mWifiLogProto.totalNumberOfPasspointConnectionsWithVenueUrl="
4716                         + mWifiLogProto.totalNumberOfPasspointConnectionsWithVenueUrl);
4717                 pw.println(
4718                         "mWifiLogProto.totalNumberOfPasspointConnectionsWithTermsAndConditionsUrl="
4719                                 + mWifiLogProto
4720                                 .totalNumberOfPasspointConnectionsWithTermsAndConditionsUrl);
4721                 pw.println(
4722                         "mWifiLogProto"
4723                                 + ".totalNumberOfPasspointAcceptanceOfTermsAndConditions="
4724                                 + mWifiLogProto
4725                                 .totalNumberOfPasspointAcceptanceOfTermsAndConditions);
4726                 pw.println("mWifiLogProto.totalNumberOfPasspointProfilesWithDecoratedIdentity="
4727                         + mWifiLogProto.totalNumberOfPasspointProfilesWithDecoratedIdentity);
4728                 pw.println("mWifiLogProto.passpointDeauthImminentScope="
4729                         + mPasspointDeauthImminentScope.toString());
4730 
4731                 pw.println("mWifiLogProto.numRadioModeChangeToMcc="
4732                         + mWifiLogProto.numRadioModeChangeToMcc);
4733                 pw.println("mWifiLogProto.numRadioModeChangeToScc="
4734                         + mWifiLogProto.numRadioModeChangeToScc);
4735                 pw.println("mWifiLogProto.numRadioModeChangeToSbs="
4736                         + mWifiLogProto.numRadioModeChangeToSbs);
4737                 pw.println("mWifiLogProto.numRadioModeChangeToDbs="
4738                         + mWifiLogProto.numRadioModeChangeToDbs);
4739                 pw.println("mWifiLogProto.numSoftApUserBandPreferenceUnsatisfied="
4740                         + mWifiLogProto.numSoftApUserBandPreferenceUnsatisfied);
4741                 pw.println("mTotalSsidsInScanHistogram:"
4742                         + mTotalSsidsInScanHistogram.toString());
4743                 pw.println("mTotalBssidsInScanHistogram:"
4744                         + mTotalBssidsInScanHistogram.toString());
4745                 pw.println("mAvailableOpenSsidsInScanHistogram:"
4746                         + mAvailableOpenSsidsInScanHistogram.toString());
4747                 pw.println("mAvailableOpenBssidsInScanHistogram:"
4748                         + mAvailableOpenBssidsInScanHistogram.toString());
4749                 pw.println("mAvailableSavedSsidsInScanHistogram:"
4750                         + mAvailableSavedSsidsInScanHistogram.toString());
4751                 pw.println("mAvailableSavedBssidsInScanHistogram:"
4752                         + mAvailableSavedBssidsInScanHistogram.toString());
4753                 pw.println("mAvailableOpenOrSavedSsidsInScanHistogram:"
4754                         + mAvailableOpenOrSavedSsidsInScanHistogram.toString());
4755                 pw.println("mAvailableOpenOrSavedBssidsInScanHistogram:"
4756                         + mAvailableOpenOrSavedBssidsInScanHistogram.toString());
4757                 pw.println("mAvailableSavedPasspointProviderProfilesInScanHistogram:"
4758                         + mAvailableSavedPasspointProviderProfilesInScanHistogram.toString());
4759                 pw.println("mAvailableSavedPasspointProviderBssidsInScanHistogram:"
4760                         + mAvailableSavedPasspointProviderBssidsInScanHistogram.toString());
4761                 pw.println("mWifiLogProto.partialAllSingleScanListenerResults="
4762                         + mWifiLogProto.partialAllSingleScanListenerResults);
4763                 pw.println("mWifiLogProto.fullBandAllSingleScanListenerResults="
4764                         + mWifiLogProto.fullBandAllSingleScanListenerResults);
4765                 pw.println("mWifiAwareMetrics:");
4766                 mWifiAwareMetrics.dump(fd, pw, args);
4767                 pw.println("mRttMetrics:");
4768                 mRttMetrics.dump(fd, pw, args);
4769 
4770                 pw.println("mPnoScanMetrics.numPnoScanAttempts="
4771                         + mPnoScanMetrics.numPnoScanAttempts);
4772                 pw.println("mPnoScanMetrics.numPnoScanFailed="
4773                         + mPnoScanMetrics.numPnoScanFailed);
4774                 pw.println("mPnoScanMetrics.numPnoScanStartedOverOffload="
4775                         + mPnoScanMetrics.numPnoScanStartedOverOffload);
4776                 pw.println("mPnoScanMetrics.numPnoScanFailedOverOffload="
4777                         + mPnoScanMetrics.numPnoScanFailedOverOffload);
4778                 pw.println("mPnoScanMetrics.numPnoFoundNetworkEvents="
4779                         + mPnoScanMetrics.numPnoFoundNetworkEvents);
4780 
4781                 pw.println("mWifiLinkLayerUsageStats.loggingDurationMs="
4782                         + mWifiLinkLayerUsageStats.loggingDurationMs);
4783                 pw.println("mWifiLinkLayerUsageStats.radioOnTimeMs="
4784                         + mWifiLinkLayerUsageStats.radioOnTimeMs);
4785                 pw.println("mWifiLinkLayerUsageStats.radioTxTimeMs="
4786                         + mWifiLinkLayerUsageStats.radioTxTimeMs);
4787                 pw.println("mWifiLinkLayerUsageStats.radioRxTimeMs="
4788                         + mWifiLinkLayerUsageStats.radioRxTimeMs);
4789                 pw.println("mWifiLinkLayerUsageStats.radioScanTimeMs="
4790                         + mWifiLinkLayerUsageStats.radioScanTimeMs);
4791                 pw.println("mWifiLinkLayerUsageStats.radioNanScanTimeMs="
4792                         + mWifiLinkLayerUsageStats.radioNanScanTimeMs);
4793                 pw.println("mWifiLinkLayerUsageStats.radioBackgroundScanTimeMs="
4794                         + mWifiLinkLayerUsageStats.radioBackgroundScanTimeMs);
4795                 pw.println("mWifiLinkLayerUsageStats.radioRoamScanTimeMs="
4796                         + mWifiLinkLayerUsageStats.radioRoamScanTimeMs);
4797                 pw.println("mWifiLinkLayerUsageStats.radioPnoScanTimeMs="
4798                         + mWifiLinkLayerUsageStats.radioPnoScanTimeMs);
4799                 pw.println("mWifiLinkLayerUsageStats.radioHs20ScanTimeMs="
4800                         + mWifiLinkLayerUsageStats.radioHs20ScanTimeMs);
4801                 pw.println("mWifiLinkLayerUsageStats per Radio Stats: ");
4802                 for (int i = 0; i < mRadioStats.size(); i++) {
4803                     RadioStats radioStat = mRadioStats.valueAt(i);
4804                     pw.println("radioId=" + radioStat.radioId);
4805                     pw.println("totalRadioOnTimeMs=" + radioStat.totalRadioOnTimeMs);
4806                     pw.println("totalRadioTxTimeMs=" + radioStat.totalRadioTxTimeMs);
4807                     pw.println("totalRadioRxTimeMs=" + radioStat.totalRadioRxTimeMs);
4808                     pw.println("totalScanTimeMs=" + radioStat.totalScanTimeMs);
4809                     pw.println("totalNanScanTimeMs=" + radioStat.totalNanScanTimeMs);
4810                     pw.println("totalBackgroundScanTimeMs=" + radioStat.totalBackgroundScanTimeMs);
4811                     pw.println("totalRoamScanTimeMs=" + radioStat.totalRoamScanTimeMs);
4812                     pw.println("totalPnoScanTimeMs=" + radioStat.totalPnoScanTimeMs);
4813                     pw.println("totalHotspot2ScanTimeMs=" + radioStat.totalHotspot2ScanTimeMs);
4814                 }
4815 
4816                 pw.println("mWifiLogProto.connectToNetworkNotificationCount="
4817                         + mConnectToNetworkNotificationCount.toString());
4818                 pw.println("mWifiLogProto.connectToNetworkNotificationActionCount="
4819                         + mConnectToNetworkNotificationActionCount.toString());
4820                 pw.println("mWifiLogProto.openNetworkRecommenderBlocklistSize="
4821                         + mOpenNetworkRecommenderBlocklistSize);
4822                 pw.println("mWifiLogProto.isWifiNetworksAvailableNotificationOn="
4823                         + mIsWifiNetworksAvailableNotificationOn);
4824                 pw.println("mWifiLogProto.numOpenNetworkRecommendationUpdates="
4825                         + mNumOpenNetworkRecommendationUpdates);
4826                 pw.println("mWifiLogProto.numOpenNetworkConnectMessageFailedToSend="
4827                         + mNumOpenNetworkConnectMessageFailedToSend);
4828 
4829                 pw.println("mWifiLogProto.observedHotspotR1ApInScanHistogram="
4830                         + mObservedHotspotR1ApInScanHistogram);
4831                 pw.println("mWifiLogProto.observedHotspotR2ApInScanHistogram="
4832                         + mObservedHotspotR2ApInScanHistogram);
4833                 pw.println("mWifiLogProto.observedHotspotR3ApInScanHistogram="
4834                         + mObservedHotspotR3ApInScanHistogram);
4835                 pw.println("mWifiLogProto.observedHotspotR1EssInScanHistogram="
4836                         + mObservedHotspotR1EssInScanHistogram);
4837                 pw.println("mWifiLogProto.observedHotspotR2EssInScanHistogram="
4838                         + mObservedHotspotR2EssInScanHistogram);
4839                 pw.println("mWifiLogProto.observedHotspotR3EssInScanHistogram="
4840                         + mObservedHotspotR3EssInScanHistogram);
4841                 pw.println("mWifiLogProto.observedHotspotR1ApsPerEssInScanHistogram="
4842                         + mObservedHotspotR1ApsPerEssInScanHistogram);
4843                 pw.println("mWifiLogProto.observedHotspotR2ApsPerEssInScanHistogram="
4844                         + mObservedHotspotR2ApsPerEssInScanHistogram);
4845                 pw.println("mWifiLogProto.observedHotspotR3ApsPerEssInScanHistogram="
4846                         + mObservedHotspotR3ApsPerEssInScanHistogram);
4847 
4848                 pw.println("mWifiLogProto.observed80211mcSupportingApsInScanHistogram"
4849                         + mObserved80211mcApInScanHistogram);
4850                 pw.println("mWifiLogProto.bssidBlocklistStats:");
4851                 pw.println(mBssidBlocklistStats.toString());
4852 
4853                 pw.println("mSoftApTetheredEvents:");
4854                 for (SoftApConnectedClientsEvent event : mSoftApEventListTethered) {
4855                     StringBuilder eventLine = new StringBuilder();
4856                     eventLine.append("event_type=" + event.eventType);
4857                     eventLine.append(",time_stamp_millis=" + event.timeStampMillis);
4858                     eventLine.append(",num_connected_clients=" + event.numConnectedClients);
4859                     eventLine.append(",num_connected_clients_on_current_frequency="
4860                             + event.numConnectedClientsOnCurrentFrequency);
4861                     eventLine.append(",channel_frequency=" + event.channelFrequency);
4862                     eventLine.append(",channel_bandwidth=" + event.channelBandwidth);
4863                     eventLine.append(",generation=" + event.generation);
4864                     eventLine.append(",max_num_clients_setting_in_softap_configuration="
4865                             + event.maxNumClientsSettingInSoftapConfiguration);
4866                     eventLine.append(",max_num_clients_setting_in_softap_capability="
4867                             + event.maxNumClientsSettingInSoftapCapability);
4868                     eventLine.append(",shutdown_timeout_setting_in_softap_configuration="
4869                             + event.shutdownTimeoutSettingInSoftapConfiguration);
4870                     eventLine.append(",default_shutdown_timeout_setting="
4871                             + event.defaultShutdownTimeoutSetting);
4872                     eventLine.append(",client_control_is_enabled=" + event.clientControlIsEnabled);
4873                     pw.println(eventLine.toString());
4874                 }
4875                 pw.println("mSoftApLocalOnlyEvents:");
4876                 for (SoftApConnectedClientsEvent event : mSoftApEventListLocalOnly) {
4877                     StringBuilder eventLine = new StringBuilder();
4878                     eventLine.append("event_type=" + event.eventType);
4879                     eventLine.append(",time_stamp_millis=" + event.timeStampMillis);
4880                     eventLine.append(",num_connected_clients=" + event.numConnectedClients);
4881                     eventLine.append(",num_connected_clients_on_current_frequency="
4882                             + event.numConnectedClientsOnCurrentFrequency);
4883                     eventLine.append(",channel_frequency=" + event.channelFrequency);
4884                     eventLine.append(",channel_bandwidth=" + event.channelBandwidth);
4885                     eventLine.append(",generation=" + event.generation);
4886                     eventLine.append(",max_num_clients_setting_in_softap_configuration="
4887                             + event.maxNumClientsSettingInSoftapConfiguration);
4888                     eventLine.append(",max_num_clients_setting_in_softap_capability="
4889                             + event.maxNumClientsSettingInSoftapCapability);
4890                     eventLine.append(",shutdown_timeout_setting_in_softap_configuration="
4891                             + event.shutdownTimeoutSettingInSoftapConfiguration);
4892                     eventLine.append(",default_shutdown_timeout_setting="
4893                             + event.defaultShutdownTimeoutSetting);
4894                     eventLine.append(",client_control_is_enabled=" + event.clientControlIsEnabled);
4895                     pw.println(eventLine.toString());
4896                 }
4897 
4898                 mWifiPowerMetrics.dump(pw);
4899                 mWifiWakeMetrics.dump(pw);
4900 
4901                 pw.println("mWifiLogProto.isMacRandomizationOn="
4902                         + mContext.getResources().getBoolean(
4903                                 R.bool.config_wifi_connected_mac_randomization_supported));
4904                 pw.println("mWifiLogProto.scoreExperimentId=" + mWifiLogProto.scoreExperimentId);
4905                 pw.println("mExperimentValues.wifiDataStallMinTxBad="
4906                         + mContext.getResources().getInteger(
4907                                 R.integer.config_wifiDataStallMinTxBad));
4908                 pw.println("mExperimentValues.wifiDataStallMinTxSuccessWithoutRx="
4909                         + mContext.getResources().getInteger(
4910                                 R.integer.config_wifiDataStallMinTxSuccessWithoutRx));
4911                 pw.println("mExperimentValues.linkSpeedCountsLoggingEnabled="
4912                         + mContext.getResources().getBoolean(
4913                                 R.bool.config_wifiLinkSpeedMetricsEnabled));
4914                 pw.println("mExperimentValues.dataStallDurationMs="
4915                         + mExperimentValues.dataStallDurationMs);
4916                 pw.println("mExperimentValues.dataStallTxTputThrKbps="
4917                         + mExperimentValues.dataStallTxTputThrKbps);
4918                 pw.println("mExperimentValues.dataStallRxTputThrKbps="
4919                         + mExperimentValues.dataStallRxTputThrKbps);
4920                 pw.println("mExperimentValues.dataStallTxPerThr="
4921                         + mExperimentValues.dataStallTxPerThr);
4922                 pw.println("mExperimentValues.dataStallCcaLevelThr="
4923                         + mExperimentValues.dataStallCcaLevelThr);
4924                 pw.println("WifiIsUnusableEventList: ");
4925                 for (WifiIsUnusableWithTime event : mWifiIsUnusableList) {
4926                     pw.println(event);
4927                 }
4928                 pw.println("Hardware Version: " + SystemProperties.get("ro.boot.revision", ""));
4929 
4930                 pw.println("mWifiUsabilityStatsEntriesList:");
4931                 for (WifiUsabilityStatsEntry stats : mWifiUsabilityStatsEntriesList) {
4932                     printWifiUsabilityStatsEntry(pw, stats);
4933                 }
4934                 pw.println("mWifiUsabilityStatsList:");
4935                 for (WifiUsabilityStats stats : mWifiUsabilityStatsListGood) {
4936                     pw.println("\nlabel=" + stats.label);
4937                     pw.println("\ntrigger_type=" + stats.triggerType);
4938                     pw.println("\ntime_stamp_ms=" + stats.timeStampMs);
4939                     for (WifiUsabilityStatsEntry entry : stats.stats) {
4940                         printWifiUsabilityStatsEntry(pw, entry);
4941                     }
4942                 }
4943                 for (WifiUsabilityStats stats : mWifiUsabilityStatsListBad) {
4944                     pw.println("\nlabel=" + stats.label);
4945                     pw.println("\ntrigger_type=" + stats.triggerType);
4946                     pw.println("\ntime_stamp_ms=" + stats.timeStampMs);
4947                     for (WifiUsabilityStatsEntry entry : stats.stats) {
4948                         printWifiUsabilityStatsEntry(pw, entry);
4949                     }
4950                 }
4951 
4952                 pw.println("mMobilityStatePnoStatsMap:");
4953                 for (int i = 0; i < mMobilityStatePnoStatsMap.size(); i++) {
4954                     printDeviceMobilityStatePnoScanStats(pw, mMobilityStatePnoStatsMap.valueAt(i));
4955                 }
4956 
4957                 mWifiP2pMetrics.dump(pw);
4958                 pw.println("mDppMetrics:");
4959                 mDppMetrics.dump(pw);
4960 
4961                 pw.println("mWifiConfigStoreReadDurationHistogram:"
4962                         + mWifiConfigStoreReadDurationHistogram.toString());
4963                 pw.println("mWifiConfigStoreWriteDurationHistogram:"
4964                         + mWifiConfigStoreWriteDurationHistogram.toString());
4965 
4966                 pw.println("mLinkProbeSuccessRssiCounts:" + mLinkProbeSuccessRssiCounts);
4967                 pw.println("mLinkProbeFailureRssiCounts:" + mLinkProbeFailureRssiCounts);
4968                 pw.println("mLinkProbeSuccessLinkSpeedCounts:" + mLinkProbeSuccessLinkSpeedCounts);
4969                 pw.println("mLinkProbeFailureLinkSpeedCounts:" + mLinkProbeFailureLinkSpeedCounts);
4970                 pw.println("mLinkProbeSuccessSecondsSinceLastTxSuccessHistogram:"
4971                         + mLinkProbeSuccessSecondsSinceLastTxSuccessHistogram);
4972                 pw.println("mLinkProbeFailureSecondsSinceLastTxSuccessHistogram:"
4973                         + mLinkProbeFailureSecondsSinceLastTxSuccessHistogram);
4974                 pw.println("mLinkProbeSuccessElapsedTimeMsHistogram:"
4975                         + mLinkProbeSuccessElapsedTimeMsHistogram);
4976                 pw.println("mLinkProbeFailureReasonCounts:" + mLinkProbeFailureReasonCounts);
4977                 pw.println("mLinkProbeExperimentProbeCounts:" + mLinkProbeExperimentProbeCounts);
4978 
4979                 pw.println("mNetworkSelectionExperimentPairNumChoicesCounts:"
4980                         + mNetworkSelectionExperimentPairNumChoicesCounts);
4981                 pw.println("mLinkProbeStaEventCount:" + mLinkProbeStaEventCount);
4982 
4983                 pw.println("mWifiNetworkRequestApiLog:\n" + mWifiNetworkRequestApiLog);
4984                 pw.println("mWifiNetworkRequestApiMatchSizeHistogram:\n"
4985                         + mWifiNetworkRequestApiMatchSizeHistogram);
4986                 pw.println("mWifiNetworkRequestApiConnectionDurationSecOnPrimaryIfaceHistogram:\n"
4987                         + mWifiNetworkRequestApiConnectionDurationSecOnPrimaryIfaceHistogram);
4988                 pw.println("mWifiNetworkRequestApiConnectionDurationSecOnSecondaryIfaceHistogram:\n"
4989                         + mWifiNetworkRequestApiConnectionDurationSecOnSecondaryIfaceHistogram);
4990                 pw.println("mWifiNetworkRequestApiConcurrentConnectionDurationSecHistogram:\n"
4991                         + mWifiNetworkRequestApiConcurrentConnectionDurationSecHistogram);
4992                 pw.println("mWifiNetworkSuggestionApiLog:\n" + mWifiNetworkSuggestionApiLog);
4993                 pw.println("mWifiNetworkSuggestionApiMatchSizeHistogram:\n"
4994                         + mWifiNetworkSuggestionApiListSizeHistogram);
4995                 pw.println("mWifiNetworkSuggestionApiAppTypeCounter:\n"
4996                         + mWifiNetworkSuggestionApiAppTypeCounter);
4997                 pw.println("mWifiNetworkSuggestionPriorityGroups:\n"
4998                         + mWifiNetworkSuggestionPriorityGroups.toString());
4999                 pw.println("mWifiNetworkSuggestionCoexistSavedNetworks:\n"
5000                         + mWifiNetworkSuggestionCoexistSavedNetworks.toString());
5001                 printUserApprovalSuggestionAppReaction(pw);
5002                 printUserApprovalCarrierReaction(pw);
5003                 pw.println("mNetworkIdToNominatorId:\n" + mNetworkIdToNominatorId);
5004                 pw.println("mWifiLockStats:\n" + mWifiLockStats);
5005                 pw.println("mWifiLockHighPerfAcqDurationSecHistogram:\n"
5006                         + mWifiLockHighPerfAcqDurationSecHistogram);
5007                 pw.println("mWifiLockLowLatencyAcqDurationSecHistogram:\n"
5008                         + mWifiLockLowLatencyAcqDurationSecHistogram);
5009                 pw.println("mWifiLockHighPerfActiveSessionDurationSecHistogram:\n"
5010                         + mWifiLockHighPerfActiveSessionDurationSecHistogram);
5011                 pw.println("mWifiLockLowLatencyActiveSessionDurationSecHistogram:\n"
5012                         + mWifiLockLowLatencyActiveSessionDurationSecHistogram);
5013                 pw.println("mWifiToggleStats:\n" + mWifiToggleStats);
5014                 pw.println("mWifiLogProto.numAddOrUpdateNetworkCalls="
5015                         + mWifiLogProto.numAddOrUpdateNetworkCalls);
5016                 pw.println("mWifiLogProto.numEnableNetworkCalls="
5017                         + mWifiLogProto.numEnableNetworkCalls);
5018 
5019                 pw.println("mWifiLogProto.txLinkSpeedCount2g=" + mTxLinkSpeedCount2g);
5020                 pw.println("mWifiLogProto.txLinkSpeedCount5gLow=" + mTxLinkSpeedCount5gLow);
5021                 pw.println("mWifiLogProto.txLinkSpeedCount5gMid=" + mTxLinkSpeedCount5gMid);
5022                 pw.println("mWifiLogProto.txLinkSpeedCount5gHigh=" + mTxLinkSpeedCount5gHigh);
5023                 pw.println("mWifiLogProto.txLinkSpeedCount6gLow=" + mTxLinkSpeedCount6gLow);
5024                 pw.println("mWifiLogProto.txLinkSpeedCount6gMid=" + mTxLinkSpeedCount6gMid);
5025                 pw.println("mWifiLogProto.txLinkSpeedCount6gHigh=" + mTxLinkSpeedCount6gHigh);
5026 
5027                 pw.println("mWifiLogProto.rxLinkSpeedCount2g=" + mRxLinkSpeedCount2g);
5028                 pw.println("mWifiLogProto.rxLinkSpeedCount5gLow=" + mRxLinkSpeedCount5gLow);
5029                 pw.println("mWifiLogProto.rxLinkSpeedCount5gMid=" + mRxLinkSpeedCount5gMid);
5030                 pw.println("mWifiLogProto.rxLinkSpeedCount5gHigh=" + mRxLinkSpeedCount5gHigh);
5031                 pw.println("mWifiLogProto.rxLinkSpeedCount6gLow=" + mRxLinkSpeedCount6gLow);
5032                 pw.println("mWifiLogProto.rxLinkSpeedCount6gMid=" + mRxLinkSpeedCount6gMid);
5033                 pw.println("mWifiLogProto.rxLinkSpeedCount6gHigh=" + mRxLinkSpeedCount6gHigh);
5034 
5035                 pw.println("mWifiLogProto.numIpRenewalFailure="
5036                         + mWifiLogProto.numIpRenewalFailure);
5037                 pw.println("mWifiLogProto.connectionDurationStats="
5038                         + mConnectionDurationStats.toString());
5039                 pw.println("mWifiLogProto.isExternalWifiScorerOn="
5040                         + mWifiLogProto.isExternalWifiScorerOn);
5041                 pw.println("mWifiLogProto.wifiOffMetrics="
5042                         + mWifiOffMetrics.toString());
5043                 pw.println("mWifiLogProto.softApConfigLimitationMetrics="
5044                         + mSoftApConfigLimitationMetrics.toString());
5045                 pw.println("mChannelUtilizationHistogram2G:\n"
5046                         + mChannelUtilizationHistogram2G);
5047                 pw.println("mChannelUtilizationHistogramAbove2G:\n"
5048                         + mChannelUtilizationHistogramAbove2G);
5049                 pw.println("mTxThroughputMbpsHistogram2G:\n"
5050                         + mTxThroughputMbpsHistogram2G);
5051                 pw.println("mRxThroughputMbpsHistogram2G:\n"
5052                         + mRxThroughputMbpsHistogram2G);
5053                 pw.println("mTxThroughputMbpsHistogramAbove2G:\n"
5054                         + mTxThroughputMbpsHistogramAbove2G);
5055                 pw.println("mRxThroughputMbpsHistogramAbove2G:\n"
5056                         + mRxThroughputMbpsHistogramAbove2G);
5057                 pw.println("mCarrierWifiMetrics:\n"
5058                         + mCarrierWifiMetrics);
5059                 pw.println(firstConnectAfterBootStatsToString(mFirstConnectAfterBootStats));
5060                 pw.println(wifiToWifiSwitchStatsToString(mWifiToWifiSwitchStats));
5061 
5062                 dumpInitPartialScanMetrics(pw);
5063             }
5064         }
5065     }
5066 
dumpInitPartialScanMetrics(PrintWriter pw)5067     private void dumpInitPartialScanMetrics(PrintWriter pw) {
5068         pw.println("mInitPartialScanTotalCount:\n" + mInitPartialScanTotalCount);
5069         pw.println("mInitPartialScanSuccessCount:\n" + mInitPartialScanSuccessCount);
5070         pw.println("mInitPartialScanFailureCount:\n" + mInitPartialScanFailureCount);
5071         pw.println("mInitPartialScanSuccessHistogram:\n" + mInitPartialScanSuccessHistogram);
5072         pw.println("mInitPartialScanFailureHistogram:\n" + mInitPartialScanFailureHistogram);
5073     }
5074 
printWifiUsabilityStatsEntry(PrintWriter pw, WifiUsabilityStatsEntry entry)5075     private void printWifiUsabilityStatsEntry(PrintWriter pw, WifiUsabilityStatsEntry entry) {
5076         StringBuilder line = new StringBuilder();
5077         line.append("timestamp_ms=" + entry.timeStampMs);
5078         line.append(",rssi=" + entry.rssi);
5079         line.append(",link_speed_mbps=" + entry.linkSpeedMbps);
5080         line.append(",total_tx_success=" + entry.totalTxSuccess);
5081         line.append(",total_tx_retries=" + entry.totalTxRetries);
5082         line.append(",total_tx_bad=" + entry.totalTxBad);
5083         line.append(",total_rx_success=" + entry.totalRxSuccess);
5084         if (entry.radioStats != null) {
5085             for (RadioStats radioStat : entry.radioStats) {
5086                 line.append(",Radio Stats from radio_id=" + radioStat.radioId);
5087                 line.append(",radio_on_time_ms=" + radioStat.totalRadioOnTimeMs);
5088                 line.append(",radio_tx_time_ms=" + radioStat.totalRadioTxTimeMs);
5089                 line.append(",radio_rx_time_ms=" + radioStat.totalRadioRxTimeMs);
5090                 line.append(",scan_time_ms=" + radioStat.totalScanTimeMs);
5091                 line.append(",nan_scan_time_ms=" + radioStat.totalNanScanTimeMs);
5092                 line.append(",background_scan_time_ms=" + radioStat.totalBackgroundScanTimeMs);
5093                 line.append(",roam_scan_time_ms=" + radioStat.totalRoamScanTimeMs);
5094                 line.append(",pno_scan_time_ms=" + radioStat.totalPnoScanTimeMs);
5095                 line.append(",hotspot_2_scan_time_ms=" + radioStat.totalHotspot2ScanTimeMs);
5096             }
5097         }
5098         line.append(",total_radio_on_time_ms=" + entry.totalRadioOnTimeMs);
5099         line.append(",total_radio_tx_time_ms=" + entry.totalRadioTxTimeMs);
5100         line.append(",total_radio_rx_time_ms=" + entry.totalRadioRxTimeMs);
5101         line.append(",total_scan_time_ms=" + entry.totalScanTimeMs);
5102         line.append(",total_nan_scan_time_ms=" + entry.totalNanScanTimeMs);
5103         line.append(",total_background_scan_time_ms=" + entry.totalBackgroundScanTimeMs);
5104         line.append(",total_roam_scan_time_ms=" + entry.totalRoamScanTimeMs);
5105         line.append(",total_pno_scan_time_ms=" + entry.totalPnoScanTimeMs);
5106         line.append(",total_hotspot_2_scan_time_ms=" + entry.totalHotspot2ScanTimeMs);
5107         line.append(",wifi_score=" + entry.wifiScore);
5108         line.append(",wifi_usability_score=" + entry.wifiUsabilityScore);
5109         line.append(",seq_num_to_framework=" + entry.seqNumToFramework);
5110         line.append(",prediction_horizon_sec=" + entry.predictionHorizonSec);
5111         line.append(",total_cca_busy_freq_time_ms=" + entry.totalCcaBusyFreqTimeMs);
5112         line.append(",total_radio_on_freq_time_ms=" + entry.totalRadioOnFreqTimeMs);
5113         line.append(",total_beacon_rx=" + entry.totalBeaconRx);
5114         line.append(",probe_status_since_last_update=" + entry.probeStatusSinceLastUpdate);
5115         line.append(",probe_elapsed_time_ms_since_last_update="
5116                 + entry.probeElapsedTimeSinceLastUpdateMs);
5117         line.append(",probe_mcs_rate_since_last_update=" + entry.probeMcsRateSinceLastUpdate);
5118         line.append(",rx_link_speed_mbps=" + entry.rxLinkSpeedMbps);
5119         line.append(",seq_num_inside_framework=" + entry.seqNumInsideFramework);
5120         line.append(",is_same_bssid_and_freq=" + entry.isSameBssidAndFreq);
5121         line.append(",device_mobility_state=" + entry.deviceMobilityState);
5122         line.append(",time_slice_duty_cycle_in_percent=" + entry.timeSliceDutyCycleInPercent);
5123         if (entry.contentionTimeStats != null) {
5124             for (ContentionTimeStats stat : entry.contentionTimeStats) {
5125                 line.append(",access_category=" + stat.accessCategory);
5126                 line.append(",contention_time_min_micros=" + stat.contentionTimeMinMicros);
5127                 line.append(",contention_time_max_micros=" + stat.contentionTimeMaxMicros);
5128                 line.append(",contention_time_avg_micros=" + stat.contentionTimeAvgMicros);
5129                 line.append(",contention_num_samples=" + stat.contentionNumSamples);
5130             }
5131         }
5132         line.append(",channel_utilization_ratio=" + entry.channelUtilizationRatio);
5133         line.append(",is_throughput_sufficient=" + entry.isThroughputSufficient);
5134         line.append(",is_wifi_scoring_enabled=" + entry.isWifiScoringEnabled);
5135         line.append(",is_cellular_data_available=" + entry.isCellularDataAvailable);
5136         line.append(",sta_count=" + entry.staCount);
5137         line.append(",channel_utilization=" + entry.channelUtilization);
5138         if (entry.rateStats != null) {
5139             for (RateStats rateStat : entry.rateStats) {
5140                 line.append(",preamble=" + rateStat.preamble);
5141                 line.append(",nss=" + rateStat.nss);
5142                 line.append(",bw=" + rateStat.bw);
5143                 line.append(",rate_mcs_idx=" + rateStat.rateMcsIdx);
5144                 line.append(",bit_rate_in_kbps=" + rateStat.bitRateInKbps);
5145                 line.append(",tx_mpdu=" + rateStat.txMpdu);
5146                 line.append(",rx_mpdu=" + rateStat.rxMpdu);
5147                 line.append(",mpdu_lost=" + rateStat.mpduLost);
5148                 line.append(",retries=" + rateStat.retries);
5149             }
5150         }
5151         pw.println(line.toString());
5152     }
5153 
printDeviceMobilityStatePnoScanStats(PrintWriter pw, DeviceMobilityStatePnoScanStats stats)5154     private void printDeviceMobilityStatePnoScanStats(PrintWriter pw,
5155             DeviceMobilityStatePnoScanStats stats) {
5156         StringBuilder line = new StringBuilder();
5157         line.append("device_mobility_state=" + stats.deviceMobilityState);
5158         line.append(",num_times_entered_state=" + stats.numTimesEnteredState);
5159         line.append(",total_duration_ms=" + stats.totalDurationMs);
5160         line.append(",pno_duration_ms=" + stats.pnoDurationMs);
5161         pw.println(line.toString());
5162     }
5163 
printUserApprovalSuggestionAppReaction(PrintWriter pw)5164     private void printUserApprovalSuggestionAppReaction(PrintWriter pw) {
5165         pw.println("mUserApprovalSuggestionAppUiUserReaction:");
5166         for (UserReaction event : mUserApprovalSuggestionAppUiReactionList) {
5167             pw.println(event);
5168         }
5169     }
5170 
printUserApprovalCarrierReaction(PrintWriter pw)5171     private void printUserApprovalCarrierReaction(PrintWriter pw) {
5172         pw.println("mUserApprovalCarrierUiUserReaction:");
5173         for (UserReaction event : mUserApprovalCarrierUiReactionList) {
5174             pw.println(event);
5175         }
5176     }
5177 
5178     /**
5179      * Update various counts of saved network types
5180      * @param networks List of WifiConfigurations representing all saved networks, must not be null
5181      */
updateSavedNetworks(List<WifiConfiguration> networks)5182     public void updateSavedNetworks(List<WifiConfiguration> networks) {
5183         synchronized (mLock) {
5184             mWifiLogProto.numSavedNetworks = networks.size();
5185             mWifiLogProto.numSavedNetworksWithMacRandomization = 0;
5186             mWifiLogProto.numOpenNetworks = 0;
5187             mWifiLogProto.numLegacyPersonalNetworks = 0;
5188             mWifiLogProto.numLegacyEnterpriseNetworks = 0;
5189             mWifiLogProto.numEnhancedOpenNetworks = 0;
5190             mWifiLogProto.numWpa3PersonalNetworks = 0;
5191             mWifiLogProto.numWpa3EnterpriseNetworks = 0;
5192             mWifiLogProto.numWapiPersonalNetworks = 0;
5193             mWifiLogProto.numWapiEnterpriseNetworks = 0;
5194             mWifiLogProto.numNetworksAddedByUser = 0;
5195             mWifiLogProto.numNetworksAddedByApps = 0;
5196             mWifiLogProto.numHiddenNetworks = 0;
5197             mWifiLogProto.numPasspointNetworks = 0;
5198 
5199             for (WifiConfiguration config : networks) {
5200                 if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_OPEN)) {
5201                     mWifiLogProto.numOpenNetworks++;
5202                 } else if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_OWE)) {
5203                     mWifiLogProto.numEnhancedOpenNetworks++;
5204                 } else if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_WAPI_PSK)) {
5205                     mWifiLogProto.numWapiPersonalNetworks++;
5206                 } else if (config.isEnterprise()) {
5207                     if (config.isSecurityType(
5208                             WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT)) {
5209                         mWifiLogProto.numWpa3EnterpriseNetworks++;
5210                     } else if (config.isSecurityType(
5211                             WifiConfiguration.SECURITY_TYPE_WAPI_CERT)) {
5212                         mWifiLogProto.numWapiEnterpriseNetworks++;
5213                     } else {
5214                         mWifiLogProto.numLegacyEnterpriseNetworks++;
5215                     }
5216                 } else {
5217                     if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_PSK)) {
5218                         mWifiLogProto.numLegacyPersonalNetworks++;
5219                     }
5220                     else if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_SAE)) {
5221                         mWifiLogProto.numWpa3PersonalNetworks++;
5222                     }
5223                 }
5224                 mWifiLogProto.numNetworksAddedByApps++;
5225                 if (config.hiddenSSID) {
5226                     mWifiLogProto.numHiddenNetworks++;
5227                 }
5228                 if (config.isPasspoint()) {
5229                     mWifiLogProto.numPasspointNetworks++;
5230                 }
5231                 if (config.macRandomizationSetting != WifiConfiguration.RANDOMIZATION_NONE) {
5232                     mWifiLogProto.numSavedNetworksWithMacRandomization++;
5233                 }
5234             }
5235         }
5236     }
5237 
5238     /**
5239      * Update metrics for saved Passpoint profiles.
5240      *
5241      * @param numSavedProfiles The number of saved Passpoint profiles
5242      * @param numConnectedProfiles The number of saved Passpoint profiles that have ever resulted
5243      *                             in a successful network connection
5244      */
updateSavedPasspointProfiles(int numSavedProfiles, int numConnectedProfiles)5245     public void updateSavedPasspointProfiles(int numSavedProfiles, int numConnectedProfiles) {
5246         synchronized (mLock) {
5247             mWifiLogProto.numPasspointProviders = numSavedProfiles;
5248             mWifiLogProto.numPasspointProvidersSuccessfullyConnected = numConnectedProfiles;
5249         }
5250     }
5251 
5252     /**
5253      * Update number of times for type of saved Passpoint profile.
5254      *
5255      * @param providers Passpoint providers installed on the device.
5256      */
updateSavedPasspointProfilesInfo( Map<String, PasspointProvider> providers)5257     public void updateSavedPasspointProfilesInfo(
5258             Map<String, PasspointProvider> providers) {
5259         int passpointType;
5260         int eapType;
5261         PasspointConfiguration config;
5262         synchronized (mLock) {
5263             mInstalledPasspointProfileTypeForR1.clear();
5264             mInstalledPasspointProfileTypeForR2.clear();
5265             for (Map.Entry<String, PasspointProvider> entry : providers.entrySet()) {
5266                 config = entry.getValue().getConfig();
5267                 if (config.getCredential().getUserCredential() != null) {
5268                     eapType = EAPConstants.EAP_TTLS;
5269                 } else if (config.getCredential().getCertCredential() != null) {
5270                     eapType = EAPConstants.EAP_TLS;
5271                 } else if (config.getCredential().getSimCredential() != null) {
5272                     eapType = config.getCredential().getSimCredential().getEapType();
5273                 } else {
5274                     eapType = -1;
5275                 }
5276                 switch (eapType) {
5277                     case EAPConstants.EAP_TLS:
5278                         passpointType = WifiMetricsProto.PasspointProfileTypeCount.TYPE_EAP_TLS;
5279                         break;
5280                     case EAPConstants.EAP_TTLS:
5281                         passpointType = WifiMetricsProto.PasspointProfileTypeCount.TYPE_EAP_TTLS;
5282                         break;
5283                     case EAPConstants.EAP_SIM:
5284                         passpointType = WifiMetricsProto.PasspointProfileTypeCount.TYPE_EAP_SIM;
5285                         break;
5286                     case EAPConstants.EAP_AKA:
5287                         passpointType = WifiMetricsProto.PasspointProfileTypeCount.TYPE_EAP_AKA;
5288                         break;
5289                     case EAPConstants.EAP_AKA_PRIME:
5290                         passpointType =
5291                                 WifiMetricsProto.PasspointProfileTypeCount.TYPE_EAP_AKA_PRIME;
5292                         break;
5293                     default:
5294                         passpointType = WifiMetricsProto.PasspointProfileTypeCount.TYPE_UNKNOWN;
5295 
5296                 }
5297                 if (config.validateForR2()) {
5298                     mInstalledPasspointProfileTypeForR2.increment(passpointType);
5299                 } else {
5300                     mInstalledPasspointProfileTypeForR1.increment(passpointType);
5301                 }
5302             }
5303         }
5304     }
5305 
5306     /**
5307      * Increment initial partial scan count
5308      */
incrementInitialPartialScanCount()5309     public void incrementInitialPartialScanCount() {
5310         synchronized (mLock) {
5311             mInitPartialScanTotalCount++;
5312         }
5313     }
5314 
5315     /**
5316      * Report of initial partial scan
5317      * @param channelCount number of channels used in this scan
5318      * @param status true if scan resulted in a network connection attempt, false otherwise
5319      */
reportInitialPartialScan(int channelCount, boolean status)5320     public void reportInitialPartialScan(int channelCount, boolean status) {
5321         synchronized (mLock) {
5322             if (status) {
5323                 mInitPartialScanSuccessCount++;
5324                 mInitPartialScanSuccessHistogram.increment(channelCount);
5325             } else {
5326                 mInitPartialScanFailureCount++;
5327                 mInitPartialScanFailureHistogram.increment(channelCount);
5328             }
5329         }
5330     }
5331 
5332     /**
5333      * Put all metrics that were being tracked separately into mWifiLogProto
5334      */
consolidateProto()5335     private void consolidateProto() {
5336         List<WifiMetricsProto.RssiPollCount> rssis = new ArrayList<>();
5337         synchronized (mLock) {
5338             mWifiLogProto.connectionEvent = mConnectionEventList
5339                     .stream()
5340                     // Exclude active un-ended connection events
5341                     .filter(connectionEvent ->
5342                             !mCurrentConnectionEventPerIface.containsValue(connectionEvent))
5343                     // unwrap WifiMetrics.ConnectionEvent to get WifiMetricsProto.ConnectionEvent
5344                     .map(connectionEvent -> connectionEvent.mConnectionEvent)
5345                     .toArray(WifiMetricsProto.ConnectionEvent[]::new);
5346 
5347             //Convert the SparseIntArray of scanReturnEntry integers into ScanReturnEntry proto list
5348             mWifiLogProto.scanReturnEntries =
5349                     new WifiMetricsProto.WifiLog.ScanReturnEntry[mScanReturnEntries.size()];
5350             for (int i = 0; i < mScanReturnEntries.size(); i++) {
5351                 mWifiLogProto.scanReturnEntries[i] = new WifiMetricsProto.WifiLog.ScanReturnEntry();
5352                 mWifiLogProto.scanReturnEntries[i].scanReturnCode = mScanReturnEntries.keyAt(i);
5353                 mWifiLogProto.scanReturnEntries[i].scanResultsCount = mScanReturnEntries.valueAt(i);
5354             }
5355 
5356             // Convert the SparseIntArray of systemStateEntry into WifiSystemStateEntry proto list
5357             // This one is slightly more complex, as the Sparse are indexed with:
5358             //     key: wifiState * 2 + isScreenOn, value: wifiStateCount
5359             mWifiLogProto.wifiSystemStateEntries =
5360                     new WifiMetricsProto.WifiLog
5361                     .WifiSystemStateEntry[mWifiSystemStateEntries.size()];
5362             for (int i = 0; i < mWifiSystemStateEntries.size(); i++) {
5363                 mWifiLogProto.wifiSystemStateEntries[i] =
5364                         new WifiMetricsProto.WifiLog.WifiSystemStateEntry();
5365                 mWifiLogProto.wifiSystemStateEntries[i].wifiState =
5366                         mWifiSystemStateEntries.keyAt(i) / 2;
5367                 mWifiLogProto.wifiSystemStateEntries[i].wifiStateCount =
5368                         mWifiSystemStateEntries.valueAt(i);
5369                 mWifiLogProto.wifiSystemStateEntries[i].isScreenOn =
5370                         (mWifiSystemStateEntries.keyAt(i) % 2) > 0;
5371             }
5372             mWifiLogProto.recordDurationSec = (int) ((mClock.getElapsedSinceBootMillis() / 1000)
5373                     - mRecordStartTimeSec);
5374 
5375             /**
5376              * Convert the SparseIntArrays of RSSI poll rssi, counts, and frequency to the
5377              * proto's repeated IntKeyVal array.
5378              */
5379             for (Map.Entry<Integer, SparseIntArray> entry : mRssiPollCountsMap.entrySet()) {
5380                 int frequency = entry.getKey();
5381                 SparseIntArray histogram = entry.getValue();
5382                 for (int i = 0; i < histogram.size(); i++) {
5383                     WifiMetricsProto.RssiPollCount keyVal = new WifiMetricsProto.RssiPollCount();
5384                     keyVal.rssi = histogram.keyAt(i);
5385                     keyVal.count = histogram.valueAt(i);
5386                     keyVal.frequency = frequency;
5387                     rssis.add(keyVal);
5388                 }
5389             }
5390             mWifiLogProto.rssiPollRssiCount = rssis.toArray(mWifiLogProto.rssiPollRssiCount);
5391 
5392             /**
5393              * Convert the SparseIntArray of RSSI delta rssi's and counts to the proto's repeated
5394              * IntKeyVal array.
5395              */
5396             mWifiLogProto.rssiPollDeltaCount =
5397                     new WifiMetricsProto.RssiPollCount[mRssiDeltaCounts.size()];
5398             for (int i = 0; i < mRssiDeltaCounts.size(); i++) {
5399                 mWifiLogProto.rssiPollDeltaCount[i] = new WifiMetricsProto.RssiPollCount();
5400                 mWifiLogProto.rssiPollDeltaCount[i].rssi = mRssiDeltaCounts.keyAt(i);
5401                 mWifiLogProto.rssiPollDeltaCount[i].count = mRssiDeltaCounts.valueAt(i);
5402             }
5403 
5404             /**
5405              * Add LinkSpeedCount objects from mLinkSpeedCounts to proto.
5406              */
5407             mWifiLogProto.linkSpeedCounts =
5408                     new WifiMetricsProto.LinkSpeedCount[mLinkSpeedCounts.size()];
5409             for (int i = 0; i < mLinkSpeedCounts.size(); i++) {
5410                 mWifiLogProto.linkSpeedCounts[i] = mLinkSpeedCounts.valueAt(i);
5411             }
5412 
5413             /**
5414              * Convert the SparseIntArray of alert reasons and counts to the proto's repeated
5415              * IntKeyVal array.
5416              */
5417             mWifiLogProto.alertReasonCount =
5418                     new WifiMetricsProto.AlertReasonCount[mWifiAlertReasonCounts.size()];
5419             for (int i = 0; i < mWifiAlertReasonCounts.size(); i++) {
5420                 mWifiLogProto.alertReasonCount[i] = new WifiMetricsProto.AlertReasonCount();
5421                 mWifiLogProto.alertReasonCount[i].reason = mWifiAlertReasonCounts.keyAt(i);
5422                 mWifiLogProto.alertReasonCount[i].count = mWifiAlertReasonCounts.valueAt(i);
5423             }
5424 
5425             /**
5426             *  Convert the SparseIntArray of Wifi Score and counts to proto's repeated
5427             * IntKeyVal array.
5428             */
5429             mWifiLogProto.wifiScoreCount =
5430                     new WifiMetricsProto.WifiScoreCount[mWifiScoreCounts.size()];
5431             for (int score = 0; score < mWifiScoreCounts.size(); score++) {
5432                 mWifiLogProto.wifiScoreCount[score] = new WifiMetricsProto.WifiScoreCount();
5433                 mWifiLogProto.wifiScoreCount[score].score = mWifiScoreCounts.keyAt(score);
5434                 mWifiLogProto.wifiScoreCount[score].count = mWifiScoreCounts.valueAt(score);
5435             }
5436 
5437             /**
5438              * Convert the SparseIntArray of Wifi Usability Score and counts to proto's repeated
5439              * IntKeyVal array.
5440              */
5441             mWifiLogProto.wifiUsabilityScoreCount =
5442                 new WifiMetricsProto.WifiUsabilityScoreCount[mWifiUsabilityScoreCounts.size()];
5443             for (int scoreIdx = 0; scoreIdx < mWifiUsabilityScoreCounts.size(); scoreIdx++) {
5444                 mWifiLogProto.wifiUsabilityScoreCount[scoreIdx] =
5445                     new WifiMetricsProto.WifiUsabilityScoreCount();
5446                 mWifiLogProto.wifiUsabilityScoreCount[scoreIdx].score =
5447                     mWifiUsabilityScoreCounts.keyAt(scoreIdx);
5448                 mWifiLogProto.wifiUsabilityScoreCount[scoreIdx].count =
5449                     mWifiUsabilityScoreCounts.valueAt(scoreIdx);
5450             }
5451 
5452             /**
5453              * Convert the SparseIntArray of SoftAp Return codes and counts to proto's repeated
5454              * IntKeyVal array.
5455              */
5456             int codeCounts = mSoftApManagerReturnCodeCounts.size();
5457             mWifiLogProto.softApReturnCode = new WifiMetricsProto.SoftApReturnCodeCount[codeCounts];
5458             for (int sapCode = 0; sapCode < codeCounts; sapCode++) {
5459                 mWifiLogProto.softApReturnCode[sapCode] =
5460                         new WifiMetricsProto.SoftApReturnCodeCount();
5461                 mWifiLogProto.softApReturnCode[sapCode].startResult =
5462                         mSoftApManagerReturnCodeCounts.keyAt(sapCode);
5463                 mWifiLogProto.softApReturnCode[sapCode].count =
5464                         mSoftApManagerReturnCodeCounts.valueAt(sapCode);
5465             }
5466 
5467             /**
5468              * Convert StaEventList to array of StaEvents
5469              */
5470             mWifiLogProto.staEventList = new StaEvent[mStaEventList.size()];
5471             for (int i = 0; i < mStaEventList.size(); i++) {
5472                 mWifiLogProto.staEventList[i] = mStaEventList.get(i).staEvent;
5473             }
5474             mWifiLogProto.userActionEvents = new UserActionEvent[mUserActionEventList.size()];
5475             for (int i = 0; i < mUserActionEventList.size(); i++) {
5476                 mWifiLogProto.userActionEvents[i] = mUserActionEventList.get(i).toProto();
5477             }
5478             mWifiLogProto.totalSsidsInScanHistogram =
5479                     makeNumConnectableNetworksBucketArray(mTotalSsidsInScanHistogram);
5480             mWifiLogProto.totalBssidsInScanHistogram =
5481                     makeNumConnectableNetworksBucketArray(mTotalBssidsInScanHistogram);
5482             mWifiLogProto.availableOpenSsidsInScanHistogram =
5483                     makeNumConnectableNetworksBucketArray(mAvailableOpenSsidsInScanHistogram);
5484             mWifiLogProto.availableOpenBssidsInScanHistogram =
5485                     makeNumConnectableNetworksBucketArray(mAvailableOpenBssidsInScanHistogram);
5486             mWifiLogProto.availableSavedSsidsInScanHistogram =
5487                     makeNumConnectableNetworksBucketArray(mAvailableSavedSsidsInScanHistogram);
5488             mWifiLogProto.availableSavedBssidsInScanHistogram =
5489                     makeNumConnectableNetworksBucketArray(mAvailableSavedBssidsInScanHistogram);
5490             mWifiLogProto.availableOpenOrSavedSsidsInScanHistogram =
5491                     makeNumConnectableNetworksBucketArray(
5492                     mAvailableOpenOrSavedSsidsInScanHistogram);
5493             mWifiLogProto.availableOpenOrSavedBssidsInScanHistogram =
5494                     makeNumConnectableNetworksBucketArray(
5495                     mAvailableOpenOrSavedBssidsInScanHistogram);
5496             mWifiLogProto.availableSavedPasspointProviderProfilesInScanHistogram =
5497                     makeNumConnectableNetworksBucketArray(
5498                     mAvailableSavedPasspointProviderProfilesInScanHistogram);
5499             mWifiLogProto.availableSavedPasspointProviderBssidsInScanHistogram =
5500                     makeNumConnectableNetworksBucketArray(
5501                     mAvailableSavedPasspointProviderBssidsInScanHistogram);
5502             mWifiLogProto.wifiAwareLog = mWifiAwareMetrics.consolidateProto();
5503             mWifiLogProto.wifiRttLog = mRttMetrics.consolidateProto();
5504 
5505             mWifiLogProto.pnoScanMetrics = mPnoScanMetrics;
5506             mWifiLogProto.wifiLinkLayerUsageStats = mWifiLinkLayerUsageStats;
5507             mWifiLogProto.wifiLinkLayerUsageStats.radioStats =
5508                     new WifiMetricsProto.RadioStats[mRadioStats.size()];
5509             for (int i = 0; i < mRadioStats.size(); i++) {
5510                 mWifiLogProto.wifiLinkLayerUsageStats.radioStats[i] = mRadioStats.valueAt(i);
5511             }
5512 
5513             /**
5514              * Convert the SparseIntArray of "Connect to Network" notification types and counts to
5515              * proto's repeated IntKeyVal array.
5516              */
5517             ConnectToNetworkNotificationAndActionCount[] notificationCountArray =
5518                     new ConnectToNetworkNotificationAndActionCount[
5519                             mConnectToNetworkNotificationCount.size()];
5520             for (int i = 0; i < mConnectToNetworkNotificationCount.size(); i++) {
5521                 ConnectToNetworkNotificationAndActionCount keyVal =
5522                         new ConnectToNetworkNotificationAndActionCount();
5523                 keyVal.notification = mConnectToNetworkNotificationCount.keyAt(i);
5524                 keyVal.recommender =
5525                         ConnectToNetworkNotificationAndActionCount.RECOMMENDER_OPEN;
5526                 keyVal.count = mConnectToNetworkNotificationCount.valueAt(i);
5527                 notificationCountArray[i] = keyVal;
5528             }
5529             mWifiLogProto.connectToNetworkNotificationCount = notificationCountArray;
5530 
5531             /**
5532              * Convert the SparseIntArray of "Connect to Network" notification types and counts to
5533              * proto's repeated IntKeyVal array.
5534              */
5535             ConnectToNetworkNotificationAndActionCount[] notificationActionCountArray =
5536                     new ConnectToNetworkNotificationAndActionCount[
5537                             mConnectToNetworkNotificationActionCount.size()];
5538             for (int i = 0; i < mConnectToNetworkNotificationActionCount.size(); i++) {
5539                 ConnectToNetworkNotificationAndActionCount keyVal =
5540                         new ConnectToNetworkNotificationAndActionCount();
5541                 int k = mConnectToNetworkNotificationActionCount.keyAt(i);
5542                 keyVal.notification =  k / CONNECT_TO_NETWORK_NOTIFICATION_ACTION_KEY_MULTIPLIER;
5543                 keyVal.action = k % CONNECT_TO_NETWORK_NOTIFICATION_ACTION_KEY_MULTIPLIER;
5544                 keyVal.recommender =
5545                         ConnectToNetworkNotificationAndActionCount.RECOMMENDER_OPEN;
5546                 keyVal.count = mConnectToNetworkNotificationActionCount.valueAt(i);
5547                 notificationActionCountArray[i] = keyVal;
5548             }
5549 
5550             mWifiLogProto.installedPasspointProfileTypeForR1 =
5551                     convertPasspointProfilesToProto(mInstalledPasspointProfileTypeForR1);
5552             mWifiLogProto.installedPasspointProfileTypeForR2 =
5553                     convertPasspointProfilesToProto(mInstalledPasspointProfileTypeForR2);
5554 
5555             mWifiLogProto.connectToNetworkNotificationActionCount = notificationActionCountArray;
5556 
5557             mWifiLogProto.openNetworkRecommenderBlocklistSize =
5558                     mOpenNetworkRecommenderBlocklistSize;
5559             mWifiLogProto.isWifiNetworksAvailableNotificationOn =
5560                     mIsWifiNetworksAvailableNotificationOn;
5561             mWifiLogProto.numOpenNetworkRecommendationUpdates =
5562                     mNumOpenNetworkRecommendationUpdates;
5563             mWifiLogProto.numOpenNetworkConnectMessageFailedToSend =
5564                     mNumOpenNetworkConnectMessageFailedToSend;
5565 
5566             mWifiLogProto.observedHotspotR1ApsInScanHistogram =
5567                     makeNumConnectableNetworksBucketArray(mObservedHotspotR1ApInScanHistogram);
5568             mWifiLogProto.observedHotspotR2ApsInScanHistogram =
5569                     makeNumConnectableNetworksBucketArray(mObservedHotspotR2ApInScanHistogram);
5570             mWifiLogProto.observedHotspotR3ApsInScanHistogram =
5571                 makeNumConnectableNetworksBucketArray(mObservedHotspotR3ApInScanHistogram);
5572             mWifiLogProto.observedHotspotR1EssInScanHistogram =
5573                     makeNumConnectableNetworksBucketArray(mObservedHotspotR1EssInScanHistogram);
5574             mWifiLogProto.observedHotspotR2EssInScanHistogram =
5575                     makeNumConnectableNetworksBucketArray(mObservedHotspotR2EssInScanHistogram);
5576             mWifiLogProto.observedHotspotR3EssInScanHistogram =
5577                     makeNumConnectableNetworksBucketArray(mObservedHotspotR3EssInScanHistogram);
5578             mWifiLogProto.observedHotspotR1ApsPerEssInScanHistogram =
5579                     makeNumConnectableNetworksBucketArray(
5580                             mObservedHotspotR1ApsPerEssInScanHistogram);
5581             mWifiLogProto.observedHotspotR2ApsPerEssInScanHistogram =
5582                     makeNumConnectableNetworksBucketArray(
5583                             mObservedHotspotR2ApsPerEssInScanHistogram);
5584             mWifiLogProto.observedHotspotR3ApsPerEssInScanHistogram =
5585                 makeNumConnectableNetworksBucketArray(
5586                     mObservedHotspotR3ApsPerEssInScanHistogram);
5587 
5588             mWifiLogProto.observed80211McSupportingApsInScanHistogram =
5589                     makeNumConnectableNetworksBucketArray(mObserved80211mcApInScanHistogram);
5590 
5591             if (mSoftApEventListTethered.size() > 0) {
5592                 mWifiLogProto.softApConnectedClientsEventsTethered =
5593                         mSoftApEventListTethered.toArray(
5594                         mWifiLogProto.softApConnectedClientsEventsTethered);
5595             }
5596             if (mSoftApEventListLocalOnly.size() > 0) {
5597                 mWifiLogProto.softApConnectedClientsEventsLocalOnly =
5598                         mSoftApEventListLocalOnly.toArray(
5599                         mWifiLogProto.softApConnectedClientsEventsLocalOnly);
5600             }
5601 
5602             mWifiLogProto.wifiPowerStats = mWifiPowerMetrics.buildProto();
5603             mWifiLogProto.wifiRadioUsage = mWifiPowerMetrics.buildWifiRadioUsageProto();
5604             mWifiLogProto.wifiWakeStats = mWifiWakeMetrics.buildProto();
5605             mWifiLogProto.isMacRandomizationOn = mContext.getResources().getBoolean(
5606                     R.bool.config_wifi_connected_mac_randomization_supported);
5607             mExperimentValues.linkSpeedCountsLoggingEnabled = mContext.getResources().getBoolean(
5608                     R.bool.config_wifiLinkSpeedMetricsEnabled);
5609             mExperimentValues.wifiDataStallMinTxBad = mContext.getResources().getInteger(
5610                     R.integer.config_wifiDataStallMinTxBad);
5611             mExperimentValues.wifiDataStallMinTxSuccessWithoutRx =
5612                     mContext.getResources().getInteger(
5613                             R.integer.config_wifiDataStallMinTxSuccessWithoutRx);
5614             mWifiLogProto.experimentValues = mExperimentValues;
5615             mWifiLogProto.wifiIsUnusableEventList =
5616                     new WifiIsUnusableEvent[mWifiIsUnusableList.size()];
5617             for (int i = 0; i < mWifiIsUnusableList.size(); i++) {
5618                 mWifiLogProto.wifiIsUnusableEventList[i] = mWifiIsUnusableList.get(i).event;
5619             }
5620             mWifiLogProto.hardwareRevision = SystemProperties.get("ro.boot.revision", "");
5621 
5622             // Postprocessing on WifiUsabilityStats to upload an equal number of LABEL_GOOD and
5623             // LABEL_BAD WifiUsabilityStats
5624             final int numUsabilityStats = Math.min(
5625                     Math.min(mWifiUsabilityStatsListBad.size(),
5626                             mWifiUsabilityStatsListGood.size()),
5627                     MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD);
5628             LinkedList<WifiUsabilityStats> usabilityStatsGoodCopy =
5629                     new LinkedList<>(mWifiUsabilityStatsListGood);
5630             LinkedList<WifiUsabilityStats> usabilityStatsBadCopy =
5631                     new LinkedList<>(mWifiUsabilityStatsListBad);
5632             mWifiLogProto.wifiUsabilityStatsList = new WifiUsabilityStats[numUsabilityStats * 2];
5633             for (int i = 0; i < numUsabilityStats; i++) {
5634                 mWifiLogProto.wifiUsabilityStatsList[2 * i] = usabilityStatsGoodCopy.remove(
5635                         mRand.nextInt(usabilityStatsGoodCopy.size()));
5636                 mWifiLogProto.wifiUsabilityStatsList[2 * i + 1] = usabilityStatsBadCopy.remove(
5637                         mRand.nextInt(usabilityStatsBadCopy.size()));
5638             }
5639             mWifiLogProto.mobilityStatePnoStatsList =
5640                     new DeviceMobilityStatePnoScanStats[mMobilityStatePnoStatsMap.size()];
5641             for (int i = 0; i < mMobilityStatePnoStatsMap.size(); i++) {
5642                 mWifiLogProto.mobilityStatePnoStatsList[i] = mMobilityStatePnoStatsMap.valueAt(i);
5643             }
5644             mWifiLogProto.wifiP2PStats = mWifiP2pMetrics.consolidateProto();
5645             mWifiLogProto.wifiDppLog = mDppMetrics.consolidateProto();
5646             mWifiLogProto.wifiConfigStoreIo = new WifiMetricsProto.WifiConfigStoreIO();
5647             mWifiLogProto.wifiConfigStoreIo.readDurations =
5648                     makeWifiConfigStoreIODurationBucketArray(mWifiConfigStoreReadDurationHistogram);
5649             mWifiLogProto.wifiConfigStoreIo.writeDurations =
5650                     makeWifiConfigStoreIODurationBucketArray(
5651                             mWifiConfigStoreWriteDurationHistogram);
5652 
5653             LinkProbeStats linkProbeStats = new LinkProbeStats();
5654             linkProbeStats.successRssiCounts = mLinkProbeSuccessRssiCounts.toProto();
5655             linkProbeStats.failureRssiCounts = mLinkProbeFailureRssiCounts.toProto();
5656             linkProbeStats.successLinkSpeedCounts = mLinkProbeSuccessLinkSpeedCounts.toProto();
5657             linkProbeStats.failureLinkSpeedCounts = mLinkProbeFailureLinkSpeedCounts.toProto();
5658             linkProbeStats.successSecondsSinceLastTxSuccessHistogram =
5659                     mLinkProbeSuccessSecondsSinceLastTxSuccessHistogram.toProto();
5660             linkProbeStats.failureSecondsSinceLastTxSuccessHistogram =
5661                     mLinkProbeFailureSecondsSinceLastTxSuccessHistogram.toProto();
5662             linkProbeStats.successElapsedTimeMsHistogram =
5663                     mLinkProbeSuccessElapsedTimeMsHistogram.toProto();
5664             linkProbeStats.failureReasonCounts = mLinkProbeFailureReasonCounts.toProto(
5665                     LinkProbeFailureReasonCount.class,
5666                     (reason, count) -> {
5667                         LinkProbeFailureReasonCount c = new LinkProbeFailureReasonCount();
5668                         c.failureReason = linkProbeFailureReasonToProto(reason);
5669                         c.count = count;
5670                         return c;
5671                     });
5672             linkProbeStats.experimentProbeCounts = mLinkProbeExperimentProbeCounts.toProto(
5673                     ExperimentProbeCounts.class,
5674                     (experimentId, probeCount) -> {
5675                         ExperimentProbeCounts c = new ExperimentProbeCounts();
5676                         c.experimentId = experimentId;
5677                         c.probeCount = probeCount;
5678                         return c;
5679                     });
5680             mWifiLogProto.linkProbeStats = linkProbeStats;
5681 
5682             mWifiLogProto.networkSelectionExperimentDecisionsList =
5683                     makeNetworkSelectionExperimentDecisionsList();
5684 
5685             mWifiNetworkRequestApiLog.networkMatchSizeHistogram =
5686                     mWifiNetworkRequestApiMatchSizeHistogram.toProto();
5687             mWifiNetworkRequestApiLog.connectionDurationSecOnPrimaryIfaceHistogram =
5688                     mWifiNetworkRequestApiConnectionDurationSecOnPrimaryIfaceHistogram.toProto();
5689             mWifiNetworkRequestApiLog.connectionDurationSecOnSecondaryIfaceHistogram =
5690                     mWifiNetworkRequestApiConnectionDurationSecOnSecondaryIfaceHistogram.toProto();
5691             mWifiNetworkRequestApiLog.concurrentConnectionDurationSecHistogram =
5692                     mWifiNetworkRequestApiConcurrentConnectionDurationSecHistogram.toProto();
5693             mWifiLogProto.wifiNetworkRequestApiLog = mWifiNetworkRequestApiLog;
5694 
5695             mWifiNetworkSuggestionApiLog.networkListSizeHistogram =
5696                     mWifiNetworkSuggestionApiListSizeHistogram.toProto();
5697             mWifiNetworkSuggestionApiLog.appCountPerType =
5698                     mWifiNetworkSuggestionApiAppTypeCounter.toProto(SuggestionAppCount.class,
5699                             (key, count) -> {
5700                                 SuggestionAppCount entry = new SuggestionAppCount();
5701                                 entry.appType = key;
5702                                 entry.count = count;
5703                                 return entry;
5704                             });
5705             mWifiNetworkSuggestionApiLog.numPriorityGroups =
5706                     mWifiNetworkSuggestionPriorityGroups.size();
5707             mWifiNetworkSuggestionApiLog.numSavedNetworksWithConfiguredSuggestion =
5708                     mWifiNetworkSuggestionCoexistSavedNetworks.size();
5709             mWifiLogProto.wifiNetworkSuggestionApiLog = mWifiNetworkSuggestionApiLog;
5710 
5711             UserReactionToApprovalUiEvent events = new UserReactionToApprovalUiEvent();
5712             events.userApprovalAppUiReaction = mUserApprovalSuggestionAppUiReactionList
5713                     .toArray(new UserReaction[0]);
5714             events.userApprovalCarrierUiReaction = mUserApprovalCarrierUiReactionList
5715                     .toArray(new UserReaction[0]);
5716             mWifiLogProto.userReactionToApprovalUiEvent = events;
5717 
5718             mWifiLockStats.highPerfLockAcqDurationSecHistogram =
5719                     mWifiLockHighPerfAcqDurationSecHistogram.toProto();
5720 
5721             mWifiLockStats.lowLatencyLockAcqDurationSecHistogram =
5722                     mWifiLockLowLatencyAcqDurationSecHistogram.toProto();
5723 
5724             mWifiLockStats.highPerfActiveSessionDurationSecHistogram =
5725                     mWifiLockHighPerfActiveSessionDurationSecHistogram.toProto();
5726 
5727             mWifiLockStats.lowLatencyActiveSessionDurationSecHistogram =
5728                     mWifiLockLowLatencyActiveSessionDurationSecHistogram.toProto();
5729 
5730             mWifiLogProto.wifiLockStats = mWifiLockStats;
5731             mWifiLogProto.wifiToggleStats = mWifiToggleStats;
5732 
5733             /**
5734              * Convert the SparseIntArray of passpoint provision failure code
5735              * and counts to the proto's repeated IntKeyVal array.
5736              */
5737             mWifiLogProto.passpointProvisionStats = new PasspointProvisionStats();
5738             mWifiLogProto.passpointProvisionStats.numProvisionSuccess = mNumProvisionSuccess;
5739             mWifiLogProto.passpointProvisionStats.provisionFailureCount =
5740                     mPasspointProvisionFailureCounts.toProto(ProvisionFailureCount.class,
5741                             (key, count) -> {
5742                                 ProvisionFailureCount entry = new ProvisionFailureCount();
5743                                 entry.failureCode = key;
5744                                 entry.count = count;
5745                                 return entry;
5746                             });
5747             // 'G' is due to that 1st Letter after _ becomes capital during protobuff compilation
5748             mWifiLogProto.txLinkSpeedCount2G = mTxLinkSpeedCount2g.toProto();
5749             mWifiLogProto.txLinkSpeedCount5GLow = mTxLinkSpeedCount5gLow.toProto();
5750             mWifiLogProto.txLinkSpeedCount5GMid = mTxLinkSpeedCount5gMid.toProto();
5751             mWifiLogProto.txLinkSpeedCount5GHigh = mTxLinkSpeedCount5gHigh.toProto();
5752             mWifiLogProto.txLinkSpeedCount6GLow = mTxLinkSpeedCount6gLow.toProto();
5753             mWifiLogProto.txLinkSpeedCount6GMid = mTxLinkSpeedCount6gMid.toProto();
5754             mWifiLogProto.txLinkSpeedCount6GHigh = mTxLinkSpeedCount6gHigh.toProto();
5755 
5756             mWifiLogProto.rxLinkSpeedCount2G = mRxLinkSpeedCount2g.toProto();
5757             mWifiLogProto.rxLinkSpeedCount5GLow = mRxLinkSpeedCount5gLow.toProto();
5758             mWifiLogProto.rxLinkSpeedCount5GMid = mRxLinkSpeedCount5gMid.toProto();
5759             mWifiLogProto.rxLinkSpeedCount5GHigh = mRxLinkSpeedCount5gHigh.toProto();
5760             mWifiLogProto.rxLinkSpeedCount6GLow = mRxLinkSpeedCount6gLow.toProto();
5761             mWifiLogProto.rxLinkSpeedCount6GMid = mRxLinkSpeedCount6gMid.toProto();
5762             mWifiLogProto.rxLinkSpeedCount6GHigh = mRxLinkSpeedCount6gHigh.toProto();
5763 
5764             HealthMonitorMetrics healthMonitorMetrics = mWifiHealthMonitor.buildProto();
5765             if (healthMonitorMetrics != null) {
5766                 mWifiLogProto.healthMonitorMetrics = healthMonitorMetrics;
5767             }
5768             mWifiLogProto.bssidBlocklistStats = mBssidBlocklistStats.toProto();
5769             mWifiLogProto.connectionDurationStats = mConnectionDurationStats.toProto();
5770             mWifiLogProto.wifiOffMetrics = mWifiOffMetrics.toProto();
5771             mWifiLogProto.softApConfigLimitationMetrics = mSoftApConfigLimitationMetrics.toProto();
5772             mWifiLogProto.channelUtilizationHistogram =
5773                     new WifiMetricsProto.ChannelUtilizationHistogram();
5774             mWifiLogProto.channelUtilizationHistogram.utilization2G =
5775                     mChannelUtilizationHistogram2G.toProto();
5776             mWifiLogProto.channelUtilizationHistogram.utilizationAbove2G =
5777                     mChannelUtilizationHistogramAbove2G.toProto();
5778             mWifiLogProto.throughputMbpsHistogram =
5779                     new WifiMetricsProto.ThroughputMbpsHistogram();
5780             mWifiLogProto.throughputMbpsHistogram.tx2G =
5781                     mTxThroughputMbpsHistogram2G.toProto();
5782             mWifiLogProto.throughputMbpsHistogram.txAbove2G =
5783                     mTxThroughputMbpsHistogramAbove2G.toProto();
5784             mWifiLogProto.throughputMbpsHistogram.rx2G =
5785                     mRxThroughputMbpsHistogram2G.toProto();
5786             mWifiLogProto.throughputMbpsHistogram.rxAbove2G =
5787                     mRxThroughputMbpsHistogramAbove2G.toProto();
5788             mWifiLogProto.meteredNetworkStatsSaved = mMeteredNetworkStatsBuilder.toProto(false);
5789             mWifiLogProto.meteredNetworkStatsSuggestion = mMeteredNetworkStatsBuilder.toProto(true);
5790 
5791             InitPartialScanStats initialPartialScanStats = new InitPartialScanStats();
5792             initialPartialScanStats.numScans = mInitPartialScanTotalCount;
5793             initialPartialScanStats.numSuccessScans = mInitPartialScanSuccessCount;
5794             initialPartialScanStats.numFailureScans = mInitPartialScanFailureCount;
5795             initialPartialScanStats.successfulScanChannelCountHistogram =
5796                     mInitPartialScanSuccessHistogram.toProto();
5797             initialPartialScanStats.failedScanChannelCountHistogram =
5798                     mInitPartialScanFailureHistogram.toProto();
5799             mWifiLogProto.initPartialScanStats = initialPartialScanStats;
5800             mWifiLogProto.carrierWifiMetrics = mCarrierWifiMetrics.toProto();
5801             mWifiLogProto.mainlineModuleVersion = mWifiHealthMonitor.getWifiStackVersion();
5802             mWifiLogProto.firstConnectAfterBootStats = mFirstConnectAfterBootStats;
5803             mWifiLogProto.wifiToWifiSwitchStats = buildWifiToWifiSwitchStats();
5804             mWifiLogProto.bandwidthEstimatorStats = mWifiScoreCard.dumpBandwidthEstimatorStats();
5805             mWifiLogProto.passpointDeauthImminentScope = mPasspointDeauthImminentScope.toProto();
5806             mWifiLogProto.recentFailureAssociationStatus =
5807                     mRecentFailureAssociationStatus.toProto();
5808         }
5809     }
5810 
buildWifiToWifiSwitchStats()5811     private WifiToWifiSwitchStats buildWifiToWifiSwitchStats() {
5812         mWifiToWifiSwitchStats.makeBeforeBreakLingerDurationSeconds =
5813                 mMakeBeforeBreakLingeringDurationSeconds.toProto();
5814         return mWifiToWifiSwitchStats;
5815     }
5816 
linkProbeFailureReasonToProto(int reason)5817     private static int linkProbeFailureReasonToProto(int reason) {
5818         switch (reason) {
5819             case WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED:
5820                 return LinkProbeStats.LINK_PROBE_FAILURE_REASON_MCS_UNSUPPORTED;
5821             case WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_NO_ACK:
5822                 return LinkProbeStats.LINK_PROBE_FAILURE_REASON_NO_ACK;
5823             case WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_TIMEOUT:
5824                 return LinkProbeStats.LINK_PROBE_FAILURE_REASON_TIMEOUT;
5825             case WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_ALREADY_STARTED:
5826                 return LinkProbeStats.LINK_PROBE_FAILURE_REASON_ALREADY_STARTED;
5827             default:
5828                 return LinkProbeStats.LINK_PROBE_FAILURE_REASON_UNKNOWN;
5829         }
5830     }
5831 
makeNetworkSelectionExperimentDecisionsList()5832     private NetworkSelectionExperimentDecisions[] makeNetworkSelectionExperimentDecisionsList() {
5833         NetworkSelectionExperimentDecisions[] results = new NetworkSelectionExperimentDecisions[
5834                 mNetworkSelectionExperimentPairNumChoicesCounts.size()];
5835         int i = 0;
5836         for (Map.Entry<Pair<Integer, Integer>, NetworkSelectionExperimentResults> entry :
5837                 mNetworkSelectionExperimentPairNumChoicesCounts.entrySet()) {
5838             NetworkSelectionExperimentDecisions result = new NetworkSelectionExperimentDecisions();
5839             result.experiment1Id = entry.getKey().first;
5840             result.experiment2Id = entry.getKey().second;
5841             result.sameSelectionNumChoicesCounter =
5842                     entry.getValue().sameSelectionNumChoicesCounter.toProto();
5843             result.differentSelectionNumChoicesCounter =
5844                     entry.getValue().differentSelectionNumChoicesCounter.toProto();
5845             results[i] = result;
5846             i++;
5847         }
5848         return results;
5849     }
5850 
5851     /** Sets the scoring experiment id to current value */
consolidateScoringParams()5852     private void consolidateScoringParams() {
5853         synchronized (mLock) {
5854             if (mScoringParams != null) {
5855                 int experimentIdentifier = mScoringParams.getExperimentIdentifier();
5856                 if (experimentIdentifier == 0) {
5857                     mWifiLogProto.scoreExperimentId = "";
5858                 } else {
5859                     mWifiLogProto.scoreExperimentId = "x" + experimentIdentifier;
5860                 }
5861             }
5862         }
5863     }
5864 
makeNumConnectableNetworksBucketArray( SparseIntArray sia)5865     private WifiMetricsProto.NumConnectableNetworksBucket[] makeNumConnectableNetworksBucketArray(
5866             SparseIntArray sia) {
5867         WifiMetricsProto.NumConnectableNetworksBucket[] array =
5868                 new WifiMetricsProto.NumConnectableNetworksBucket[sia.size()];
5869         for (int i = 0; i < sia.size(); i++) {
5870             WifiMetricsProto.NumConnectableNetworksBucket keyVal =
5871                     new WifiMetricsProto.NumConnectableNetworksBucket();
5872             keyVal.numConnectableNetworks = sia.keyAt(i);
5873             keyVal.count = sia.valueAt(i);
5874             array[i] = keyVal;
5875         }
5876         return array;
5877     }
5878 
5879     private WifiMetricsProto.WifiConfigStoreIO.DurationBucket[]
makeWifiConfigStoreIODurationBucketArray(SparseIntArray sia)5880             makeWifiConfigStoreIODurationBucketArray(SparseIntArray sia) {
5881         MetricsUtils.GenericBucket[] genericBuckets =
5882                 MetricsUtils.linearHistogramToGenericBuckets(sia,
5883                         WIFI_CONFIG_STORE_IO_DURATION_BUCKET_RANGES_MS);
5884         WifiMetricsProto.WifiConfigStoreIO.DurationBucket[] array =
5885                 new WifiMetricsProto.WifiConfigStoreIO.DurationBucket[genericBuckets.length];
5886         try {
5887             for (int i = 0; i < genericBuckets.length; i++) {
5888                 array[i] = new WifiMetricsProto.WifiConfigStoreIO.DurationBucket();
5889                 array[i].rangeStartMs = toIntExact(genericBuckets[i].start);
5890                 array[i].rangeEndMs = toIntExact(genericBuckets[i].end);
5891                 array[i].count = genericBuckets[i].count;
5892             }
5893         } catch (ArithmeticException e) {
5894             // Return empty array on any overflow errors.
5895             array = new WifiMetricsProto.WifiConfigStoreIO.DurationBucket[0];
5896         }
5897         return array;
5898     }
5899 
5900     /**
5901      * Clear all WifiMetrics, except for currentConnectionEvent and Open Network Notification
5902      * feature enabled state, blocklist size.
5903      */
clear()5904     private void clear() {
5905         synchronized (mLock) {
5906             mConnectionEventList.clear();
5907             // Add in-progress events back
5908             mConnectionEventList.addAll(mCurrentConnectionEventPerIface.values());
5909 
5910             mScanReturnEntries.clear();
5911             mWifiSystemStateEntries.clear();
5912             mRecordStartTimeSec = mClock.getElapsedSinceBootMillis() / 1000;
5913             mRssiPollCountsMap.clear();
5914             mRssiDeltaCounts.clear();
5915             mLinkSpeedCounts.clear();
5916             mTxLinkSpeedCount2g.clear();
5917             mTxLinkSpeedCount5gLow.clear();
5918             mTxLinkSpeedCount5gMid.clear();
5919             mTxLinkSpeedCount5gHigh.clear();
5920             mTxLinkSpeedCount6gLow.clear();
5921             mTxLinkSpeedCount6gMid.clear();
5922             mTxLinkSpeedCount6gHigh.clear();
5923             mRxLinkSpeedCount2g.clear();
5924             mRxLinkSpeedCount5gLow.clear();
5925             mRxLinkSpeedCount5gMid.clear();
5926             mRxLinkSpeedCount5gHigh.clear();
5927             mRxLinkSpeedCount6gLow.clear();
5928             mRxLinkSpeedCount6gMid.clear();
5929             mRxLinkSpeedCount6gHigh.clear();
5930             mWifiAlertReasonCounts.clear();
5931             mMakeBeforeBreakLingeringDurationSeconds.clear();
5932             mWifiScoreCounts.clear();
5933             mWifiUsabilityScoreCounts.clear();
5934             mWifiLogProto.clear();
5935             mScanResultRssiTimestampMillis = -1;
5936             mSoftApManagerReturnCodeCounts.clear();
5937             mStaEventList.clear();
5938             mUserActionEventList.clear();
5939             mWifiAwareMetrics.clear();
5940             mRttMetrics.clear();
5941             mTotalSsidsInScanHistogram.clear();
5942             mTotalBssidsInScanHistogram.clear();
5943             mAvailableOpenSsidsInScanHistogram.clear();
5944             mAvailableOpenBssidsInScanHistogram.clear();
5945             mAvailableSavedSsidsInScanHistogram.clear();
5946             mAvailableSavedBssidsInScanHistogram.clear();
5947             mAvailableOpenOrSavedSsidsInScanHistogram.clear();
5948             mAvailableOpenOrSavedBssidsInScanHistogram.clear();
5949             mAvailableSavedPasspointProviderProfilesInScanHistogram.clear();
5950             mAvailableSavedPasspointProviderBssidsInScanHistogram.clear();
5951             mPnoScanMetrics.clear();
5952             mWifiLinkLayerUsageStats.clear();
5953             mRadioStats.clear();
5954             mConnectToNetworkNotificationCount.clear();
5955             mConnectToNetworkNotificationActionCount.clear();
5956             mNumOpenNetworkRecommendationUpdates = 0;
5957             mNumOpenNetworkConnectMessageFailedToSend = 0;
5958             mObservedHotspotR1ApInScanHistogram.clear();
5959             mObservedHotspotR2ApInScanHistogram.clear();
5960             mObservedHotspotR3ApInScanHistogram.clear();
5961             mObservedHotspotR1EssInScanHistogram.clear();
5962             mObservedHotspotR2EssInScanHistogram.clear();
5963             mObservedHotspotR3EssInScanHistogram.clear();
5964             mObservedHotspotR1ApsPerEssInScanHistogram.clear();
5965             mObservedHotspotR2ApsPerEssInScanHistogram.clear();
5966             mObservedHotspotR3ApsPerEssInScanHistogram.clear();
5967             mSoftApEventListTethered.clear();
5968             mSoftApEventListLocalOnly.clear();
5969             mWifiWakeMetrics.clear();
5970             mObserved80211mcApInScanHistogram.clear();
5971             mWifiIsUnusableList.clear();
5972             mInstalledPasspointProfileTypeForR1.clear();
5973             mInstalledPasspointProfileTypeForR2.clear();
5974             mWifiUsabilityStatsListGood.clear();
5975             mWifiUsabilityStatsListBad.clear();
5976             mWifiUsabilityStatsEntriesList.clear();
5977             mMobilityStatePnoStatsMap.clear();
5978             mWifiP2pMetrics.clear();
5979             mDppMetrics.clear();
5980             mWifiUsabilityStatsCounter = 0;
5981             mLastBssid = null;
5982             mLastFrequency = -1;
5983             mSeqNumInsideFramework = 0;
5984             mLastWifiUsabilityScore = -1;
5985             mLastWifiUsabilityScoreNoReset = -1;
5986             mLastPredictionHorizonSec = -1;
5987             mLastPredictionHorizonSecNoReset = -1;
5988             mSeqNumToFramework = -1;
5989             mProbeStatusSinceLastUpdate =
5990                     android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE;
5991             mProbeElapsedTimeSinceLastUpdateMs = -1;
5992             mProbeMcsRateSinceLastUpdate = -1;
5993             mScoreBreachLowTimeMillis = -1;
5994             mMeteredNetworkStatsBuilder.clear();
5995             mWifiConfigStoreReadDurationHistogram.clear();
5996             mWifiConfigStoreWriteDurationHistogram.clear();
5997             mLinkProbeSuccessRssiCounts.clear();
5998             mLinkProbeFailureRssiCounts.clear();
5999             mLinkProbeSuccessLinkSpeedCounts.clear();
6000             mLinkProbeFailureLinkSpeedCounts.clear();
6001             mLinkProbeSuccessSecondsSinceLastTxSuccessHistogram.clear();
6002             mLinkProbeFailureSecondsSinceLastTxSuccessHistogram.clear();
6003             mLinkProbeSuccessElapsedTimeMsHistogram.clear();
6004             mLinkProbeFailureReasonCounts.clear();
6005             mLinkProbeExperimentProbeCounts.clear();
6006             mLinkProbeStaEventCount = 0;
6007             mNetworkSelectionExperimentPairNumChoicesCounts.clear();
6008             mWifiNetworkSuggestionApiLog.clear();
6009             mWifiNetworkRequestApiMatchSizeHistogram.clear();
6010             mWifiNetworkRequestApiConnectionDurationSecOnPrimaryIfaceHistogram.clear();
6011             mWifiNetworkRequestApiConnectionDurationSecOnSecondaryIfaceHistogram.clear();
6012             mWifiNetworkRequestApiConcurrentConnectionDurationSecHistogram.clear();
6013             mWifiNetworkSuggestionApiListSizeHistogram.clear();
6014             mWifiNetworkSuggestionApiAppTypeCounter.clear();
6015             mUserApprovalSuggestionAppUiReactionList.clear();
6016             mUserApprovalCarrierUiReactionList.clear();
6017             mWifiLockHighPerfAcqDurationSecHistogram.clear();
6018             mWifiLockLowLatencyAcqDurationSecHistogram.clear();
6019             mWifiLockHighPerfActiveSessionDurationSecHistogram.clear();
6020             mWifiLockLowLatencyActiveSessionDurationSecHistogram.clear();
6021             mWifiLockStats.clear();
6022             mWifiToggleStats.clear();
6023             mChannelUtilizationHistogram2G.clear();
6024             mChannelUtilizationHistogramAbove2G.clear();
6025             mTxThroughputMbpsHistogram2G.clear();
6026             mRxThroughputMbpsHistogram2G.clear();
6027             mTxThroughputMbpsHistogramAbove2G.clear();
6028             mRxThroughputMbpsHistogramAbove2G.clear();
6029             mPasspointProvisionFailureCounts.clear();
6030             mNumProvisionSuccess = 0;
6031             mBssidBlocklistStats = new BssidBlocklistStats();
6032             mConnectionDurationStats.clear();
6033             mWifiOffMetrics.clear();
6034             mSoftApConfigLimitationMetrics.clear();
6035             //Initial partial scan metrics
6036             mInitPartialScanTotalCount = 0;
6037             mInitPartialScanSuccessCount = 0;
6038             mInitPartialScanFailureCount = 0;
6039             mInitPartialScanSuccessHistogram.clear();
6040             mInitPartialScanFailureHistogram.clear();
6041             mCarrierWifiMetrics.clear();
6042             mFirstConnectAfterBootStats = null;
6043             mWifiToWifiSwitchStats.clear();
6044             mPasspointDeauthImminentScope.clear();
6045             mRecentFailureAssociationStatus.clear();
6046             mWifiNetworkSuggestionPriorityGroups.clear();
6047             mWifiNetworkSuggestionCoexistSavedNetworks.clear();
6048         }
6049     }
6050 
6051     /**
6052      *  Set screen state (On/Off)
6053      */
setScreenState(boolean screenOn)6054     private void setScreenState(boolean screenOn) {
6055         synchronized (mLock) {
6056             mScreenOn = screenOn;
6057         }
6058     }
6059 
isPrimary(String ifaceName)6060     private boolean isPrimary(String ifaceName) {
6061         return mIfaceToRoleMap.get(ifaceName) == ActiveModeManager.ROLE_CLIENT_PRIMARY;
6062     }
6063 
6064     /**
6065      *  Set wifi state (WIFI_UNKNOWN, WIFI_DISABLED, WIFI_DISCONNECTED, WIFI_ASSOCIATED)
6066      */
setWifiState(String ifaceName, int wifiState)6067     public void setWifiState(String ifaceName, int wifiState) {
6068         synchronized (mLock) {
6069             mWifiState = wifiState;
6070             // set wifi priority over setting when any STA gets connected.
6071             if (wifiState == WifiMetricsProto.WifiLog.WIFI_ASSOCIATED) {
6072                 mWifiWins = true;
6073                 mWifiWinsUsabilityScore = true;
6074             }
6075             if (isPrimary(ifaceName) && (wifiState == WifiMetricsProto.WifiLog.WIFI_DISCONNECTED
6076                     || wifiState == WifiMetricsProto.WifiLog.WIFI_DISABLED)) {
6077                 mWifiStatusBuilder = new WifiStatusBuilder();
6078             }
6079         }
6080     }
6081 
6082     /**
6083      * Message handler for interesting WifiMonitor messages. Generates StaEvents
6084      */
processMessage(Message msg)6085     private void processMessage(Message msg) {
6086         String ifaceName = msg.getData().getString(WifiMonitor.KEY_IFACE);
6087 
6088         StaEvent event = new StaEvent();
6089         boolean logEvent = true;
6090         switch (msg.what) {
6091             case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
6092                 event.type = StaEvent.TYPE_ASSOCIATION_REJECTION_EVENT;
6093                 AssocRejectEventInfo assocRejectEventInfo = (AssocRejectEventInfo) msg.obj;
6094                 event.associationTimedOut = assocRejectEventInfo.timedOut;
6095                 event.status = assocRejectEventInfo.statusCode;
6096                 break;
6097             case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
6098                 event.type = StaEvent.TYPE_AUTHENTICATION_FAILURE_EVENT;
6099                 AuthenticationFailureEventInfo authenticationFailureEventInfo =
6100                         (AuthenticationFailureEventInfo) msg.obj;
6101                 switch (authenticationFailureEventInfo.reasonCode) {
6102                     case WifiManager.ERROR_AUTH_FAILURE_NONE:
6103                         event.authFailureReason = StaEvent.AUTH_FAILURE_NONE;
6104                         break;
6105                     case WifiManager.ERROR_AUTH_FAILURE_TIMEOUT:
6106                         event.authFailureReason = StaEvent.AUTH_FAILURE_TIMEOUT;
6107                         break;
6108                     case WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD:
6109                         event.authFailureReason = StaEvent.AUTH_FAILURE_WRONG_PSWD;
6110                         break;
6111                     case WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE:
6112                         event.authFailureReason = StaEvent.AUTH_FAILURE_EAP_FAILURE;
6113                         break;
6114                     default:
6115                         break;
6116                 }
6117                 break;
6118             case WifiMonitor.NETWORK_CONNECTION_EVENT:
6119                 event.type = StaEvent.TYPE_NETWORK_CONNECTION_EVENT;
6120                 break;
6121             case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
6122                 event.type = StaEvent.TYPE_NETWORK_DISCONNECTION_EVENT;
6123                 DisconnectEventInfo disconnectEventInfo = (DisconnectEventInfo) msg.obj;
6124                 event.reason = disconnectEventInfo.reasonCode;
6125                 event.localGen = disconnectEventInfo.locallyGenerated;
6126                 break;
6127             case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
6128                 logEvent = false;
6129                 StateChangeResult stateChangeResult = (StateChangeResult) msg.obj;
6130                 mSupplicantStateChangeBitmask |= supplicantStateToBit(stateChangeResult.state);
6131                 break;
6132             case WifiMonitor.ASSOCIATED_BSSID_EVENT:
6133                 event.type = StaEvent.TYPE_CMD_ASSOCIATED_BSSID;
6134                 break;
6135             case WifiMonitor.TARGET_BSSID_EVENT:
6136                 event.type = StaEvent.TYPE_CMD_TARGET_BSSID;
6137                 break;
6138             default:
6139                 return;
6140         }
6141         if (logEvent) {
6142             addStaEvent(ifaceName, event);
6143         }
6144     }
6145     /**
6146      * Log a StaEvent from ClientModeImpl. The StaEvent must not be one of the supplicant
6147      * generated event types, which are logged through 'sendMessage'
6148      * @param type StaEvent.EventType describing the event
6149      */
logStaEvent(String ifaceName, int type)6150     public void logStaEvent(String ifaceName, int type) {
6151         logStaEvent(ifaceName, type, StaEvent.DISCONNECT_UNKNOWN, null);
6152     }
6153     /**
6154      * Log a StaEvent from ClientModeImpl. The StaEvent must not be one of the supplicant
6155      * generated event types, which are logged through 'sendMessage'
6156      * @param type StaEvent.EventType describing the event
6157      * @param config WifiConfiguration for a framework initiated connection attempt
6158      */
logStaEvent(String ifaceName, int type, WifiConfiguration config)6159     public void logStaEvent(String ifaceName, int type, WifiConfiguration config) {
6160         logStaEvent(ifaceName, type, StaEvent.DISCONNECT_UNKNOWN, config);
6161     }
6162     /**
6163      * Log a StaEvent from ClientModeImpl. The StaEvent must not be one of the supplicant
6164      * generated event types, which are logged through 'sendMessage'
6165      * @param type StaEvent.EventType describing the event
6166      * @param frameworkDisconnectReason StaEvent.FrameworkDisconnectReason explaining why framework
6167      *                                  initiated a FRAMEWORK_DISCONNECT
6168      */
logStaEvent(String ifaceName, int type, int frameworkDisconnectReason)6169     public void logStaEvent(String ifaceName, int type, int frameworkDisconnectReason) {
6170         logStaEvent(ifaceName, type, frameworkDisconnectReason, null);
6171     }
6172     /**
6173      * Log a StaEvent from ClientModeImpl. The StaEvent must not be one of the supplicant
6174      * generated event types, which are logged through 'sendMessage'
6175      * @param type StaEvent.EventType describing the event
6176      * @param frameworkDisconnectReason StaEvent.FrameworkDisconnectReason explaining why framework
6177      *                                  initiated a FRAMEWORK_DISCONNECT
6178      * @param config WifiConfiguration for a framework initiated connection attempt
6179      */
logStaEvent(String ifaceName, int type, int frameworkDisconnectReason, WifiConfiguration config)6180     public void logStaEvent(String ifaceName, int type, int frameworkDisconnectReason,
6181             WifiConfiguration config) {
6182         switch (type) {
6183             case StaEvent.TYPE_CMD_START_ROAM:
6184                 ConnectionEvent currentConnectionEvent = mCurrentConnectionEventPerIface.get(
6185                         ifaceName);
6186                 if (currentConnectionEvent != null) {
6187                     currentConnectionEvent.mRouterFingerPrint.mIsFrameworkInitiatedRoaming = true;
6188                 }
6189                 break;
6190             case StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL:
6191             case StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST:
6192             case StaEvent.TYPE_CMD_IP_REACHABILITY_LOST:
6193             case StaEvent.TYPE_CMD_START_CONNECT:
6194             case StaEvent.TYPE_CONNECT_NETWORK:
6195                 break;
6196             case StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK:
6197                 mWifiStatusBuilder.setValidated(true);
6198                 break;
6199             case StaEvent.TYPE_FRAMEWORK_DISCONNECT:
6200             case StaEvent.TYPE_SCORE_BREACH:
6201             case StaEvent.TYPE_MAC_CHANGE:
6202             case StaEvent.TYPE_WIFI_ENABLED:
6203             case StaEvent.TYPE_WIFI_DISABLED:
6204             case StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH:
6205                 break;
6206             default:
6207                 Log.e(TAG, "Unknown StaEvent:" + type);
6208                 return;
6209         }
6210         StaEvent event = new StaEvent();
6211         event.type = type;
6212         if (frameworkDisconnectReason != StaEvent.DISCONNECT_UNKNOWN) {
6213             event.frameworkDisconnectReason = frameworkDisconnectReason;
6214         }
6215         event.configInfo = createConfigInfo(config);
6216         addStaEvent(ifaceName, event);
6217     }
6218 
addStaEvent(String ifaceName, StaEvent staEvent)6219     private void addStaEvent(String ifaceName, StaEvent staEvent) {
6220         // Nano proto runtime will throw a NPE during serialization if interfaceName is null
6221         if (ifaceName == null) {
6222             // Check if any ConcreteClientModeManager's role is switching to ROLE_CLIENT_PRIMARY
6223             ConcreteClientModeManager targetConcreteClientModeManager =
6224                     mActiveModeWarden.getClientModeManagerTransitioningIntoRole(
6225                             ROLE_CLIENT_PRIMARY);
6226             if (targetConcreteClientModeManager == null) {
6227                 Log.wtf(TAG, "Null StaEvent.ifaceName: " + staEventToString(staEvent));
6228             }
6229             return;
6230         }
6231         staEvent.interfaceName = ifaceName;
6232         staEvent.interfaceRole = convertIfaceToEnum(ifaceName);
6233         staEvent.startTimeMillis = mClock.getElapsedSinceBootMillis();
6234         staEvent.lastRssi = mLastPollRssi;
6235         staEvent.lastFreq = mLastPollFreq;
6236         staEvent.lastLinkSpeed = mLastPollLinkSpeed;
6237         staEvent.supplicantStateChangesBitmask = mSupplicantStateChangeBitmask;
6238         staEvent.lastScore = mLastScore;
6239         staEvent.lastWifiUsabilityScore = mLastWifiUsabilityScore;
6240         staEvent.lastPredictionHorizonSec = mLastPredictionHorizonSec;
6241         staEvent.mobileTxBytes = mFacade.getMobileTxBytes();
6242         staEvent.mobileRxBytes = mFacade.getMobileRxBytes();
6243         staEvent.totalTxBytes = mFacade.getTotalTxBytes();
6244         staEvent.totalRxBytes = mFacade.getTotalRxBytes();
6245         staEvent.screenOn = mScreenOn;
6246         if (mWifiDataStall != null) {
6247             staEvent.isCellularDataAvailable = mWifiDataStall.isCellularDataAvailable();
6248         }
6249         staEvent.isAdaptiveConnectivityEnabled = mAdaptiveConnectivityEnabled;
6250         mSupplicantStateChangeBitmask = 0;
6251         mLastPollRssi = -127;
6252         mLastPollFreq = -1;
6253         mLastPollLinkSpeed = -1;
6254         mLastPollRxLinkSpeed = -1;
6255         mLastScore = -1;
6256         mLastWifiUsabilityScore = -1;
6257         mLastPredictionHorizonSec = -1;
6258         synchronized (mLock) {
6259             mStaEventList.add(new StaEventWithTime(staEvent, mClock.getWallClockMillis()));
6260             // Prune StaEventList if it gets too long
6261             if (mStaEventList.size() > MAX_STA_EVENTS) mStaEventList.remove();
6262         }
6263     }
6264 
createConfigInfo(WifiConfiguration config)6265     private ConfigInfo createConfigInfo(WifiConfiguration config) {
6266         if (config == null) return null;
6267         ConfigInfo info = new ConfigInfo();
6268         info.allowedKeyManagement = bitSetToInt(config.allowedKeyManagement);
6269         info.allowedProtocols = bitSetToInt(config.allowedProtocols);
6270         info.allowedAuthAlgorithms = bitSetToInt(config.allowedAuthAlgorithms);
6271         info.allowedPairwiseCiphers = bitSetToInt(config.allowedPairwiseCiphers);
6272         info.allowedGroupCiphers = bitSetToInt(config.allowedGroupCiphers);
6273         info.hiddenSsid = config.hiddenSSID;
6274         info.isPasspoint = config.isPasspoint();
6275         info.isEphemeral = config.isEphemeral();
6276         info.hasEverConnected = config.getNetworkSelectionStatus().hasEverConnected();
6277         ScanResult candidate = config.getNetworkSelectionStatus().getCandidate();
6278         if (candidate != null) {
6279             info.scanRssi = candidate.level;
6280             info.scanFreq = candidate.frequency;
6281         }
6282         return info;
6283     }
6284 
6285     private static final int[] WIFI_MONITOR_EVENTS = {
6286             WifiMonitor.ASSOCIATION_REJECTION_EVENT,
6287             WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
6288             WifiMonitor.NETWORK_CONNECTION_EVENT,
6289             WifiMonitor.NETWORK_DISCONNECTION_EVENT,
6290             WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT,
6291             WifiMonitor.ASSOCIATED_BSSID_EVENT,
6292             WifiMonitor.TARGET_BSSID_EVENT,
6293     };
6294 
registerForWifiMonitorEvents(String ifaceName)6295     public void registerForWifiMonitorEvents(String ifaceName) {
6296         for (int event : WIFI_MONITOR_EVENTS) {
6297             mWifiMonitor.registerHandler(ifaceName, event, mHandler);
6298         }
6299     }
6300 
deregisterForWifiMonitorEvents(String ifaceName)6301     public void deregisterForWifiMonitorEvents(String ifaceName) {
6302         for (int event : WIFI_MONITOR_EVENTS) {
6303             mWifiMonitor.deregisterHandler(ifaceName, event, mHandler);
6304         }
6305     }
6306 
getWifiAwareMetrics()6307     public WifiAwareMetrics getWifiAwareMetrics() {
6308         return mWifiAwareMetrics;
6309     }
6310 
getWakeupMetrics()6311     public WifiWakeMetrics getWakeupMetrics() {
6312         return mWifiWakeMetrics;
6313     }
6314 
getRttMetrics()6315     public RttMetrics getRttMetrics() {
6316         return mRttMetrics;
6317     }
6318 
6319     // Rather than generate a StaEvent for each SUPPLICANT_STATE_CHANGE, cache these in a bitmask
6320     // and attach it to the next event which is generated.
6321     private int mSupplicantStateChangeBitmask = 0;
6322 
6323     /**
6324      * Converts a SupplicantState value to a single bit, with position defined by
6325      * {@code StaEvent.SupplicantState}
6326      */
supplicantStateToBit(SupplicantState state)6327     public static int supplicantStateToBit(SupplicantState state) {
6328         switch(state) {
6329             case DISCONNECTED:
6330                 return 1 << StaEvent.STATE_DISCONNECTED;
6331             case INTERFACE_DISABLED:
6332                 return 1 << StaEvent.STATE_INTERFACE_DISABLED;
6333             case INACTIVE:
6334                 return 1 << StaEvent.STATE_INACTIVE;
6335             case SCANNING:
6336                 return 1 << StaEvent.STATE_SCANNING;
6337             case AUTHENTICATING:
6338                 return 1 << StaEvent.STATE_AUTHENTICATING;
6339             case ASSOCIATING:
6340                 return 1 << StaEvent.STATE_ASSOCIATING;
6341             case ASSOCIATED:
6342                 return 1 << StaEvent.STATE_ASSOCIATED;
6343             case FOUR_WAY_HANDSHAKE:
6344                 return 1 << StaEvent.STATE_FOUR_WAY_HANDSHAKE;
6345             case GROUP_HANDSHAKE:
6346                 return 1 << StaEvent.STATE_GROUP_HANDSHAKE;
6347             case COMPLETED:
6348                 return 1 << StaEvent.STATE_COMPLETED;
6349             case DORMANT:
6350                 return 1 << StaEvent.STATE_DORMANT;
6351             case UNINITIALIZED:
6352                 return 1 << StaEvent.STATE_UNINITIALIZED;
6353             case INVALID:
6354                 return 1 << StaEvent.STATE_INVALID;
6355             default:
6356                 Log.wtf(TAG, "Got unknown supplicant state: " + state.ordinal());
6357                 return 0;
6358         }
6359     }
6360 
supplicantStateChangesBitmaskToString(int mask)6361     private static String supplicantStateChangesBitmaskToString(int mask) {
6362         StringBuilder sb = new StringBuilder();
6363         sb.append("supplicantStateChangeEvents: {");
6364         if ((mask & (1 << StaEvent.STATE_DISCONNECTED)) > 0) sb.append(" DISCONNECTED");
6365         if ((mask & (1 << StaEvent.STATE_INTERFACE_DISABLED)) > 0) sb.append(" INTERFACE_DISABLED");
6366         if ((mask & (1 << StaEvent.STATE_INACTIVE)) > 0) sb.append(" INACTIVE");
6367         if ((mask & (1 << StaEvent.STATE_SCANNING)) > 0) sb.append(" SCANNING");
6368         if ((mask & (1 << StaEvent.STATE_AUTHENTICATING)) > 0) sb.append(" AUTHENTICATING");
6369         if ((mask & (1 << StaEvent.STATE_ASSOCIATING)) > 0) sb.append(" ASSOCIATING");
6370         if ((mask & (1 << StaEvent.STATE_ASSOCIATED)) > 0) sb.append(" ASSOCIATED");
6371         if ((mask & (1 << StaEvent.STATE_FOUR_WAY_HANDSHAKE)) > 0) sb.append(" FOUR_WAY_HANDSHAKE");
6372         if ((mask & (1 << StaEvent.STATE_GROUP_HANDSHAKE)) > 0) sb.append(" GROUP_HANDSHAKE");
6373         if ((mask & (1 << StaEvent.STATE_COMPLETED)) > 0) sb.append(" COMPLETED");
6374         if ((mask & (1 << StaEvent.STATE_DORMANT)) > 0) sb.append(" DORMANT");
6375         if ((mask & (1 << StaEvent.STATE_UNINITIALIZED)) > 0) sb.append(" UNINITIALIZED");
6376         if ((mask & (1 << StaEvent.STATE_INVALID)) > 0) sb.append(" INVALID");
6377         sb.append(" }");
6378         return sb.toString();
6379     }
6380 
6381     /**
6382      * Returns a human readable string from a Sta Event. Only adds information relevant to the event
6383      * type.
6384      */
staEventToString(StaEvent event)6385     public static String staEventToString(StaEvent event) {
6386         if (event == null) return "<NULL>";
6387         StringBuilder sb = new StringBuilder();
6388         switch (event.type) {
6389             case StaEvent.TYPE_ASSOCIATION_REJECTION_EVENT:
6390                 sb.append("ASSOCIATION_REJECTION_EVENT")
6391                         .append(" timedOut=").append(event.associationTimedOut)
6392                         .append(" status=").append(event.status).append(":")
6393                         .append(StaIfaceStatusCode.toString(event.status));
6394                 break;
6395             case StaEvent.TYPE_AUTHENTICATION_FAILURE_EVENT:
6396                 sb.append("AUTHENTICATION_FAILURE_EVENT reason=").append(event.authFailureReason)
6397                         .append(":").append(authFailureReasonToString(event.authFailureReason));
6398                 break;
6399             case StaEvent.TYPE_NETWORK_CONNECTION_EVENT:
6400                 sb.append("NETWORK_CONNECTION_EVENT");
6401                 break;
6402             case StaEvent.TYPE_NETWORK_DISCONNECTION_EVENT:
6403                 sb.append("NETWORK_DISCONNECTION_EVENT")
6404                         .append(" local_gen=").append(event.localGen)
6405                         .append(" reason=").append(event.reason).append(":")
6406                         .append(StaIfaceReasonCode.toString(
6407                                 (event.reason >= 0 ? event.reason : -1 * event.reason)));
6408                 break;
6409             case StaEvent.TYPE_CMD_ASSOCIATED_BSSID:
6410                 sb.append("CMD_ASSOCIATED_BSSID");
6411                 break;
6412             case StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL:
6413                 sb.append("CMD_IP_CONFIGURATION_SUCCESSFUL");
6414                 break;
6415             case StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST:
6416                 sb.append("CMD_IP_CONFIGURATION_LOST");
6417                 break;
6418             case StaEvent.TYPE_CMD_IP_REACHABILITY_LOST:
6419                 sb.append("CMD_IP_REACHABILITY_LOST");
6420                 break;
6421             case StaEvent.TYPE_CMD_TARGET_BSSID:
6422                 sb.append("CMD_TARGET_BSSID");
6423                 break;
6424             case StaEvent.TYPE_CMD_START_CONNECT:
6425                 sb.append("CMD_START_CONNECT");
6426                 break;
6427             case StaEvent.TYPE_CMD_START_ROAM:
6428                 sb.append("CMD_START_ROAM");
6429                 break;
6430             case StaEvent.TYPE_CONNECT_NETWORK:
6431                 sb.append("CONNECT_NETWORK");
6432                 break;
6433             case StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK:
6434                 sb.append("NETWORK_AGENT_VALID_NETWORK");
6435                 break;
6436             case StaEvent.TYPE_FRAMEWORK_DISCONNECT:
6437                 sb.append("FRAMEWORK_DISCONNECT")
6438                         .append(" reason=")
6439                         .append(frameworkDisconnectReasonToString(event.frameworkDisconnectReason));
6440                 break;
6441             case StaEvent.TYPE_SCORE_BREACH:
6442                 sb.append("SCORE_BREACH");
6443                 break;
6444             case StaEvent.TYPE_MAC_CHANGE:
6445                 sb.append("MAC_CHANGE");
6446                 break;
6447             case StaEvent.TYPE_WIFI_ENABLED:
6448                 sb.append("WIFI_ENABLED");
6449                 break;
6450             case StaEvent.TYPE_WIFI_DISABLED:
6451                 sb.append("WIFI_DISABLED");
6452                 break;
6453             case StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH:
6454                 sb.append("WIFI_USABILITY_SCORE_BREACH");
6455                 break;
6456             case StaEvent.TYPE_LINK_PROBE:
6457                 sb.append("LINK_PROBE");
6458                 sb.append(" linkProbeWasSuccess=").append(event.linkProbeWasSuccess);
6459                 if (event.linkProbeWasSuccess) {
6460                     sb.append(" linkProbeSuccessElapsedTimeMs=")
6461                             .append(event.linkProbeSuccessElapsedTimeMs);
6462                 } else {
6463                     sb.append(" linkProbeFailureReason=").append(event.linkProbeFailureReason);
6464                 }
6465                 break;
6466             default:
6467                 sb.append("UNKNOWN " + event.type + ":");
6468                 break;
6469         }
6470         if (event.lastRssi != -127) sb.append(" lastRssi=").append(event.lastRssi);
6471         if (event.lastFreq != -1) sb.append(" lastFreq=").append(event.lastFreq);
6472         if (event.lastLinkSpeed != -1) sb.append(" lastLinkSpeed=").append(event.lastLinkSpeed);
6473         if (event.lastScore != -1) sb.append(" lastScore=").append(event.lastScore);
6474         if (event.lastWifiUsabilityScore != -1) {
6475             sb.append(" lastWifiUsabilityScore=").append(event.lastWifiUsabilityScore);
6476             sb.append(" lastPredictionHorizonSec=").append(event.lastPredictionHorizonSec);
6477         }
6478         sb.append(" screenOn=").append(event.screenOn);
6479         sb.append(" cellularData=").append(event.isCellularDataAvailable);
6480         sb.append(" adaptiveConnectivity=").append(event.isAdaptiveConnectivityEnabled);
6481         if (event.supplicantStateChangesBitmask != 0) {
6482             sb.append(", ").append(supplicantStateChangesBitmaskToString(
6483                     event.supplicantStateChangesBitmask));
6484         }
6485         if (event.configInfo != null) {
6486             sb.append(", ").append(configInfoToString(event.configInfo));
6487         }
6488         if (event.mobileTxBytes > 0) sb.append(" mobileTxBytes=").append(event.mobileTxBytes);
6489         if (event.mobileRxBytes > 0) sb.append(" mobileRxBytes=").append(event.mobileRxBytes);
6490         if (event.totalTxBytes > 0) sb.append(" totalTxBytes=").append(event.totalTxBytes);
6491         if (event.totalRxBytes > 0) sb.append(" totalRxBytes=").append(event.totalRxBytes);
6492         sb.append(" interfaceName=").append(event.interfaceName);
6493         sb.append(" interfaceRole=").append(clientRoleEnumToString(event.interfaceRole));
6494         return sb.toString();
6495     }
6496 
convertIfaceToEnum(String ifaceName)6497     private int convertIfaceToEnum(String ifaceName) {
6498         ActiveModeManager.ClientRole role = mIfaceToRoleMap.get(ifaceName);
6499         if (role == ActiveModeManager.ROLE_CLIENT_SCAN_ONLY) {
6500             return WifiMetricsProto.ROLE_CLIENT_SCAN_ONLY;
6501         } else if (role == ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT) {
6502             return WifiMetricsProto.ROLE_CLIENT_SECONDARY_TRANSIENT;
6503         } else if (role == ActiveModeManager.ROLE_CLIENT_LOCAL_ONLY) {
6504             return WifiMetricsProto.ROLE_CLIENT_LOCAL_ONLY;
6505         } else if (role == ActiveModeManager.ROLE_CLIENT_PRIMARY) {
6506             return WifiMetricsProto.ROLE_CLIENT_PRIMARY;
6507         } else if (role == ActiveModeManager.ROLE_CLIENT_SECONDARY_LONG_LIVED) {
6508             return WifiMetricsProto.ROLE_CLIENT_SECONDARY_LONG_LIVED;
6509         }
6510         return WifiMetricsProto.ROLE_UNKNOWN;
6511     }
6512 
clientRoleEnumToString(int role)6513     private static String clientRoleEnumToString(int role) {
6514         switch (role) {
6515             case WifiMetricsProto.ROLE_CLIENT_SCAN_ONLY:
6516                 return "ROLE_CLIENT_SCAN_ONLY";
6517             case WifiMetricsProto.ROLE_CLIENT_SECONDARY_TRANSIENT:
6518                 return "ROLE_CLIENT_SECONDARY_TRANSIENT";
6519             case WifiMetricsProto.ROLE_CLIENT_LOCAL_ONLY:
6520                 return "ROLE_CLIENT_LOCAL_ONLY";
6521             case WifiMetricsProto.ROLE_CLIENT_PRIMARY:
6522                 return "ROLE_CLIENT_PRIMARY";
6523             case WifiMetricsProto.ROLE_CLIENT_SECONDARY_LONG_LIVED:
6524                 return "ROLE_CLIENT_SECONDARY_LONG_LIVED";
6525             default:
6526                 return "ROLE_UNKNOWN";
6527         }
6528     }
6529 
authFailureReasonToString(int authFailureReason)6530     private static String authFailureReasonToString(int authFailureReason) {
6531         switch (authFailureReason) {
6532             case StaEvent.AUTH_FAILURE_NONE:
6533                 return "ERROR_AUTH_FAILURE_NONE";
6534             case StaEvent.AUTH_FAILURE_TIMEOUT:
6535                 return "ERROR_AUTH_FAILURE_TIMEOUT";
6536             case StaEvent.AUTH_FAILURE_WRONG_PSWD:
6537                 return "ERROR_AUTH_FAILURE_WRONG_PSWD";
6538             case StaEvent.AUTH_FAILURE_EAP_FAILURE:
6539                 return "ERROR_AUTH_FAILURE_EAP_FAILURE";
6540             default:
6541                 return "";
6542         }
6543     }
6544 
frameworkDisconnectReasonToString(int frameworkDisconnectReason)6545     private static String frameworkDisconnectReasonToString(int frameworkDisconnectReason) {
6546         switch (frameworkDisconnectReason) {
6547             case StaEvent.DISCONNECT_API:
6548                 return "DISCONNECT_API";
6549             case StaEvent.DISCONNECT_GENERIC:
6550                 return "DISCONNECT_GENERIC";
6551             case StaEvent.DISCONNECT_UNWANTED:
6552                 return "DISCONNECT_UNWANTED";
6553             case StaEvent.DISCONNECT_ROAM_WATCHDOG_TIMER:
6554                 return "DISCONNECT_ROAM_WATCHDOG_TIMER";
6555             case StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST:
6556                 return "DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST";
6557             case StaEvent.DISCONNECT_RESET_SIM_NETWORKS:
6558                 return "DISCONNECT_RESET_SIM_NETWORKS";
6559             case StaEvent.DISCONNECT_MBB_NO_INTERNET:
6560                 return "DISCONNECT_MBB_NO_INTERNET";
6561             case StaEvent.DISCONNECT_NETWORK_REMOVED:
6562                 return "DISCONNECT_NETWORK_REMOVED";
6563             case StaEvent.DISCONNECT_NETWORK_METERED:
6564                 return "DISCONNECT_NETWORK_METERED";
6565             case StaEvent.DISCONNECT_NETWORK_TEMPORARY_DISABLED:
6566                 return "DISCONNECT_NETWORK_TEMPORARY_DISABLED";
6567             case StaEvent.DISCONNECT_NETWORK_PERMANENT_DISABLED:
6568                 return "DISCONNECT_NETWORK_PERMANENT_DISABLED";
6569             case StaEvent.DISCONNECT_CARRIER_OFFLOAD_DISABLED:
6570                 return "DISCONNECT_CARRIER_OFFLOAD_DISABLED";
6571             case StaEvent.DISCONNECT_PASSPOINT_TAC:
6572                 return "DISCONNECT_PASSPOINT_TAC";
6573             case StaEvent.DISCONNECT_VCN_REQUEST:
6574                 return "DISCONNECT_VCN_REQUEST";
6575             case StaEvent.DISCONNECT_UNKNOWN_NETWORK:
6576                 return "DISCONNECT_UNKNOWN_NETWORK";
6577             default:
6578                 return "DISCONNECT_UNKNOWN=" + frameworkDisconnectReason;
6579         }
6580     }
6581 
configInfoToString(ConfigInfo info)6582     private static String configInfoToString(ConfigInfo info) {
6583         StringBuilder sb = new StringBuilder();
6584         sb.append("ConfigInfo:")
6585                 .append(" allowed_key_management=").append(info.allowedKeyManagement)
6586                 .append(" allowed_protocols=").append(info.allowedProtocols)
6587                 .append(" allowed_auth_algorithms=").append(info.allowedAuthAlgorithms)
6588                 .append(" allowed_pairwise_ciphers=").append(info.allowedPairwiseCiphers)
6589                 .append(" allowed_group_ciphers=").append(info.allowedGroupCiphers)
6590                 .append(" hidden_ssid=").append(info.hiddenSsid)
6591                 .append(" is_passpoint=").append(info.isPasspoint)
6592                 .append(" is_ephemeral=").append(info.isEphemeral)
6593                 .append(" has_ever_connected=").append(info.hasEverConnected)
6594                 .append(" scan_rssi=").append(info.scanRssi)
6595                 .append(" scan_freq=").append(info.scanFreq);
6596         return sb.toString();
6597     }
6598 
6599     /**
6600      * Converts the first 31 bits of a BitSet to a little endian int
6601      */
bitSetToInt(BitSet bits)6602     private static int bitSetToInt(BitSet bits) {
6603         int value = 0;
6604         int nBits = bits.length() < 31 ? bits.length() : 31;
6605         for (int i = 0; i < nBits; i++) {
6606             value += bits.get(i) ? (1 << i) : 0;
6607         }
6608         return value;
6609     }
6610     private void incrementSsid(SparseIntArray sia, int element) {
6611         increment(sia, Math.min(element, MAX_CONNECTABLE_SSID_NETWORK_BUCKET));
6612     }
6613     private void incrementBssid(SparseIntArray sia, int element) {
6614         increment(sia, Math.min(element, MAX_CONNECTABLE_BSSID_NETWORK_BUCKET));
6615     }
6616     private void incrementTotalScanResults(SparseIntArray sia, int element) {
6617         increment(sia, Math.min(element, MAX_TOTAL_SCAN_RESULTS_BUCKET));
6618     }
6619     private void incrementTotalScanSsids(SparseIntArray sia, int element) {
6620         increment(sia, Math.min(element, MAX_TOTAL_SCAN_RESULT_SSIDS_BUCKET));
6621     }
6622     private void incrementTotalPasspointAps(SparseIntArray sia, int element) {
6623         increment(sia, Math.min(element, MAX_TOTAL_PASSPOINT_APS_BUCKET));
6624     }
6625     private void incrementTotalUniquePasspointEss(SparseIntArray sia, int element) {
6626         increment(sia, Math.min(element, MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET));
6627     }
6628     private void incrementPasspointPerUniqueEss(SparseIntArray sia, int element) {
6629         increment(sia, Math.min(element, MAX_PASSPOINT_APS_PER_UNIQUE_ESS_BUCKET));
6630     }
6631     private void increment80211mcAps(SparseIntArray sia, int element) {
6632         increment(sia, Math.min(element, MAX_TOTAL_80211MC_APS_BUCKET));
6633     }
6634     private void increment(SparseIntArray sia, int element) {
6635         int count = sia.get(element);
6636         sia.put(element, count + 1);
6637     }
6638 
6639     private static class StaEventWithTime {
6640         public StaEvent staEvent;
6641         public long wallClockMillis;
6642 
6643         StaEventWithTime(StaEvent event, long wallClockMillis) {
6644             staEvent = event;
6645             this.wallClockMillis = wallClockMillis;
6646         }
6647 
6648         public String toString() {
6649             StringBuilder sb = new StringBuilder();
6650             Calendar c = Calendar.getInstance();
6651             c.setTimeInMillis(wallClockMillis);
6652             if (wallClockMillis != 0) {
6653                 sb.append(String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c));
6654             } else {
6655                 sb.append("                  ");
6656             }
6657             sb.append(" ").append(staEventToString(staEvent));
6658             return sb.toString();
6659         }
6660     }
6661 
6662     private LinkedList<WifiIsUnusableWithTime> mWifiIsUnusableList =
6663             new LinkedList<WifiIsUnusableWithTime>();
6664     private long mTxScucessDelta = 0;
6665     private long mTxRetriesDelta = 0;
6666     private long mTxBadDelta = 0;
6667     private long mRxSuccessDelta = 0;
6668     private long mLlStatsUpdateTimeDelta = 0;
6669     private long mLlStatsLastUpdateTime = 0;
6670     private int mLastScoreNoReset = -1;
6671     private long mLastDataStallTime = Long.MIN_VALUE;
6672 
6673     private static class WifiIsUnusableWithTime {
6674         public WifiIsUnusableEvent event;
6675         public long wallClockMillis;
6676 
6677         WifiIsUnusableWithTime(WifiIsUnusableEvent event, long wallClockMillis) {
6678             this.event = event;
6679             this.wallClockMillis = wallClockMillis;
6680         }
6681 
6682         public String toString() {
6683             if (event == null) return "<NULL>";
6684             StringBuilder sb = new StringBuilder();
6685             if (wallClockMillis != 0) {
6686                 Calendar c = Calendar.getInstance();
6687                 c.setTimeInMillis(wallClockMillis);
6688                 sb.append(String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c));
6689             } else {
6690                 sb.append("                  ");
6691             }
6692             sb.append(" ");
6693 
6694             switch(event.type) {
6695                 case WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX:
6696                     sb.append("DATA_STALL_BAD_TX");
6697                     break;
6698                 case WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX:
6699                     sb.append("DATA_STALL_TX_WITHOUT_RX");
6700                     break;
6701                 case WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH:
6702                     sb.append("DATA_STALL_BOTH");
6703                     break;
6704                 case WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT:
6705                     sb.append("FIRMWARE_ALERT");
6706                     break;
6707                 case WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST:
6708                     sb.append("IP_REACHABILITY_LOST");
6709                     break;
6710                 default:
6711                     sb.append("UNKNOWN " + event.type);
6712                     break;
6713             }
6714 
6715             sb.append(" lastScore=").append(event.lastScore);
6716             sb.append(" txSuccessDelta=").append(event.txSuccessDelta);
6717             sb.append(" txRetriesDelta=").append(event.txRetriesDelta);
6718             sb.append(" txBadDelta=").append(event.txBadDelta);
6719             sb.append(" rxSuccessDelta=").append(event.rxSuccessDelta);
6720             sb.append(" packetUpdateTimeDelta=").append(event.packetUpdateTimeDelta)
6721                     .append("ms");
6722             if (event.firmwareAlertCode != -1) {
6723                 sb.append(" firmwareAlertCode=").append(event.firmwareAlertCode);
6724             }
6725             sb.append(" lastWifiUsabilityScore=").append(event.lastWifiUsabilityScore);
6726             sb.append(" lastPredictionHorizonSec=").append(event.lastPredictionHorizonSec);
6727             sb.append(" screenOn=").append(event.screenOn);
6728             sb.append(" mobileTxBytes=").append(event.mobileTxBytes);
6729             sb.append(" mobileRxBytes=").append(event.mobileRxBytes);
6730             sb.append(" totalTxBytes=").append(event.totalTxBytes);
6731             sb.append(" totalRxBytes=").append(event.totalRxBytes);
6732             return sb.toString();
6733         }
6734     }
6735 
6736     /**
6737      * Converts MeteredOverride enum to UserActionEvent type.
6738      * @param value
6739      */
6740     public static int convertMeteredOverrideEnumToUserActionEventType(@MeteredOverride int value) {
6741         int result = UserActionEvent.EVENT_UNKNOWN;
6742         switch(value) {
6743             case WifiConfiguration.METERED_OVERRIDE_NONE:
6744                 result = UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_AUTO;
6745                 break;
6746             case WifiConfiguration.METERED_OVERRIDE_METERED:
6747                 result = UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_METERED;
6748                 break;
6749             case WifiConfiguration.METERED_OVERRIDE_NOT_METERED:
6750                 result = UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_UNMETERED;
6751                 break;
6752         }
6753         return result;
6754     }
6755 
6756     /**
6757      * Converts Adaptive Connectivity state to UserActionEvent type.
6758      * @param value
6759      */
6760     public static int convertAdaptiveConnectivityStateToUserActionEventType(boolean value) {
6761         return value ? UserActionEvent.EVENT_CONFIGURE_ADAPTIVE_CONNECTIVITY_ON
6762                 : UserActionEvent.EVENT_CONFIGURE_ADAPTIVE_CONNECTIVITY_OFF;
6763     }
6764 
6765     static class MeteredNetworkStatsBuilder {
6766         // A map from network identifier to MeteredDetail
6767         Map<String, MeteredDetail> mNetworkMap = new ArrayMap<>();
6768 
6769         void put(WifiConfiguration config, boolean detectedAsMetered) {
6770             MeteredDetail meteredDetail = new MeteredDetail();
6771             boolean isMetered = detectedAsMetered;
6772             if (config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_METERED) {
6773                 isMetered = true;
6774             } else if (config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_NOT_METERED) {
6775                 isMetered = false;
6776             }
6777             meteredDetail.isMetered = isMetered;
6778             meteredDetail.isMeteredOverrideSet = config.meteredOverride
6779                     != WifiConfiguration.METERED_OVERRIDE_NONE;
6780             meteredDetail.isFromSuggestion = config.fromWifiNetworkSuggestion;
6781             mNetworkMap.put(config.getProfileKey(), meteredDetail);
6782         }
6783 
6784         void clear() {
6785             mNetworkMap.clear();
6786         }
6787 
6788         MeteredNetworkStats toProto(boolean isFromSuggestion) {
6789             MeteredNetworkStats result = new MeteredNetworkStats();
6790             for (MeteredDetail meteredDetail : mNetworkMap.values()) {
6791                 if (meteredDetail.isFromSuggestion != isFromSuggestion) {
6792                     continue;
6793                 }
6794                 if (meteredDetail.isMetered) {
6795                     result.numMetered++;
6796                 } else {
6797                     result.numUnmetered++;
6798                 }
6799                 if (meteredDetail.isMeteredOverrideSet) {
6800                     if (meteredDetail.isMetered) {
6801                         result.numOverrideMetered++;
6802                     } else {
6803                         result.numOverrideUnmetered++;
6804                     }
6805                 }
6806             }
6807             return result;
6808         }
6809 
6810         static class MeteredDetail {
6811             public boolean isMetered;
6812             public boolean isMeteredOverrideSet;
6813             public boolean isFromSuggestion;
6814         }
6815     }
6816 
6817     /**
6818      * Add metered information of this network.
6819      * @param config WifiConfiguration representing the netework.
6820      * @param detectedAsMetered is the network detected as metered.
6821      */
6822     public void addMeteredStat(WifiConfiguration config, boolean detectedAsMetered) {
6823         synchronized (mLock) {
6824             if (config == null) {
6825                 return;
6826             }
6827             mMeteredNetworkStatsBuilder.put(config, detectedAsMetered);
6828         }
6829     }
6830     /**
6831      * Logs a UserActionEvent without a target network.
6832      * @param eventType the type of user action (one of WifiMetricsProto.UserActionEvent.EventType)
6833      */
6834     public void logUserActionEvent(int eventType) {
6835         logUserActionEvent(eventType, -1);
6836     }
6837 
6838     /**
6839      * Logs a UserActionEvent which has a target network.
6840      * @param eventType the type of user action (one of WifiMetricsProto.UserActionEvent.EventType)
6841      * @param networkId networkId of the target network.
6842      */
6843     public void logUserActionEvent(int eventType, int networkId) {
6844         synchronized (mLock) {
6845             mUserActionEventList.add(new UserActionEventWithTime(eventType, networkId));
6846             if (mUserActionEventList.size() > MAX_USER_ACTION_EVENTS) {
6847                 mUserActionEventList.remove();
6848             }
6849         }
6850     }
6851 
6852     /**
6853      * Logs a UserActionEvent, directly specifying the target network's properties.
6854      * @param eventType the type of user action (one of WifiMetricsProto.UserActionEvent.EventType)
6855      * @param isEphemeral true if the target network is ephemeral.
6856      * @param isPasspoint true if the target network is passpoint.
6857      */
6858     public void logUserActionEvent(int eventType, boolean isEphemeral, boolean isPasspoint) {
6859         synchronized (mLock) {
6860             TargetNetworkInfo networkInfo = new TargetNetworkInfo();
6861             networkInfo.isEphemeral = isEphemeral;
6862             networkInfo.isPasspoint = isPasspoint;
6863             mUserActionEventList.add(new UserActionEventWithTime(eventType, networkInfo));
6864             if (mUserActionEventList.size() > MAX_USER_ACTION_EVENTS) {
6865                 mUserActionEventList.remove();
6866             }
6867         }
6868     }
6869 
6870     /**
6871      * Update the difference between the last two WifiLinkLayerStats for WifiIsUnusableEvent
6872      */
6873     public void updateWifiIsUnusableLinkLayerStats(long txSuccessDelta, long txRetriesDelta,
6874             long txBadDelta, long rxSuccessDelta, long updateTimeDelta) {
6875         mTxScucessDelta = txSuccessDelta;
6876         mTxRetriesDelta = txRetriesDelta;
6877         mTxBadDelta = txBadDelta;
6878         mRxSuccessDelta = rxSuccessDelta;
6879         mLlStatsUpdateTimeDelta = updateTimeDelta;
6880         mLlStatsLastUpdateTime = mClock.getElapsedSinceBootMillis();
6881     }
6882 
6883     /**
6884      * Clear the saved difference between the last two WifiLinkLayerStats
6885      */
6886     public void resetWifiIsUnusableLinkLayerStats() {
6887         mTxScucessDelta = 0;
6888         mTxRetriesDelta = 0;
6889         mTxBadDelta = 0;
6890         mRxSuccessDelta = 0;
6891         mLlStatsUpdateTimeDelta = 0;
6892         mLlStatsLastUpdateTime = 0;
6893         mLastDataStallTime = Long.MIN_VALUE;
6894     }
6895 
6896     /**
6897      * Log a WifiIsUnusableEvent
6898      * @param triggerType WifiIsUnusableEvent.type describing the event
6899      * @param ifaceName name of the interface.
6900      */
6901     public void logWifiIsUnusableEvent(String ifaceName, int triggerType) {
6902         logWifiIsUnusableEvent(ifaceName, triggerType, -1);
6903     }
6904 
6905     /**
6906      * Log a WifiIsUnusableEvent
6907      * @param triggerType WifiIsUnusableEvent.type describing the event
6908      * @param firmwareAlertCode WifiIsUnusableEvent.firmwareAlertCode for firmware alert code
6909      * @param ifaceName name of the interface.
6910      */
6911     public void logWifiIsUnusableEvent(String ifaceName, int triggerType, int firmwareAlertCode) {
6912         if (!isPrimary(ifaceName)) {
6913             return;
6914         }
6915         mScoreBreachLowTimeMillis = -1;
6916 
6917         long currentBootTime = mClock.getElapsedSinceBootMillis();
6918         switch (triggerType) {
6919             case WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX:
6920             case WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX:
6921             case WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH:
6922                 // Have a time-based throttle for generating WifiIsUnusableEvent from data stalls
6923                 if (currentBootTime < mLastDataStallTime + MIN_DATA_STALL_WAIT_MS) {
6924                     return;
6925                 }
6926                 mLastDataStallTime = currentBootTime;
6927                 break;
6928             case WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT:
6929                 break;
6930             case WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST:
6931                 break;
6932             default:
6933                 Log.e(TAG, "Unknown WifiIsUnusableEvent: " + triggerType);
6934                 return;
6935         }
6936 
6937         WifiIsUnusableEvent event = new WifiIsUnusableEvent();
6938         event.type = triggerType;
6939         if (triggerType == WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT) {
6940             event.firmwareAlertCode = firmwareAlertCode;
6941         }
6942         event.startTimeMillis = currentBootTime;
6943         event.lastScore = mLastScoreNoReset;
6944         event.lastWifiUsabilityScore = mLastWifiUsabilityScoreNoReset;
6945         event.lastPredictionHorizonSec = mLastPredictionHorizonSecNoReset;
6946         event.txSuccessDelta = mTxScucessDelta;
6947         event.txRetriesDelta = mTxRetriesDelta;
6948         event.txBadDelta = mTxBadDelta;
6949         event.rxSuccessDelta = mRxSuccessDelta;
6950         event.packetUpdateTimeDelta = mLlStatsUpdateTimeDelta;
6951         event.lastLinkLayerStatsUpdateTime = mLlStatsLastUpdateTime;
6952         event.screenOn = mScreenOn;
6953         event.mobileTxBytes = mFacade.getMobileTxBytes();
6954         event.mobileRxBytes = mFacade.getMobileRxBytes();
6955         event.totalTxBytes = mFacade.getTotalTxBytes();
6956         event.totalRxBytes = mFacade.getTotalRxBytes();
6957 
6958         mWifiIsUnusableList.add(new WifiIsUnusableWithTime(event, mClock.getWallClockMillis()));
6959         if (mWifiIsUnusableList.size() > MAX_UNUSABLE_EVENTS) {
6960             mWifiIsUnusableList.removeFirst();
6961         }
6962         WifiUsabilityState wifiUsabilityState = mWifiUsabilityStatePerIface.getOrDefault(
6963                 ifaceName, WifiUsabilityState.UNKNOWN);
6964 
6965         WifiStatsLog.write(WIFI_IS_UNUSABLE_REPORTED,
6966                 convertWifiUnUsableTypeToProto(triggerType),
6967                 mScorerUid, wifiUsabilityState == WifiUsabilityState.USABLE,
6968                 convertWifiUsabilityState(wifiUsabilityState));
6969     }
6970 
6971     private int convertWifiUsabilityState(WifiUsabilityState usabilityState) {
6972         if (usabilityState == WifiUsabilityState.USABLE) {
6973             return WifiStatsLog.WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE;
6974         } else if (usabilityState == WifiUsabilityState.UNUSABLE) {
6975             return WifiStatsLog.WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_UNUSABLE;
6976         } else {
6977             return WifiStatsLog.WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_UNKNOWN;
6978         }
6979     }
6980 
6981     private int convertWifiUnUsableTypeToProto(int triggerType) {
6982         switch (triggerType) {
6983             case WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX:
6984                 return WifiStatsLog.WIFI_IS_UNUSABLE_REPORTED__TYPE__TYPE_DATA_STALL_BAD_TX;
6985             case WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX:
6986                 return WifiStatsLog.WIFI_IS_UNUSABLE_REPORTED__TYPE__TYPE_DATA_STALL_TX_WITHOUT_RX;
6987             case WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH:
6988                 return WifiStatsLog.WIFI_IS_UNUSABLE_REPORTED__TYPE__TYPE_DATA_STALL_BOTH;
6989             case WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT:
6990                 return WifiStatsLog.WIFI_IS_UNUSABLE_REPORTED__TYPE__TYPE_FIRMWARE_ALERT;
6991             case WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST:
6992                 return WifiStatsLog.WIFI_IS_UNUSABLE_REPORTED__TYPE__TYPE_IP_REACHABILITY_LOST;
6993             default:
6994                 return WifiStatsLog.WIFI_IS_UNUSABLE_REPORTED__TYPE__TYPE_UNKNOWN;
6995         }
6996     }
6997 
6998     /**
6999      * Extract data from |info| and |stats| to build a WifiUsabilityStatsEntry and then adds it
7000      * into an internal ring buffer.
7001      * @param info
7002      * @param stats
7003      * @param ifaceName
7004      */
7005     public void updateWifiUsabilityStatsEntries(String ifaceName, WifiInfo info,
7006             WifiLinkLayerStats stats) {
7007         // This is only collected for primary STA currently because RSSI polling is disabled for
7008         // non-primary STAs.
7009         synchronized (mLock) {
7010             if (info == null) {
7011                 return;
7012             }
7013             if (stats == null) {
7014                 // For devices lacking vendor hal, fill in the parts that we can
7015                 stats = new WifiLinkLayerStats();
7016                 stats.timeStampInMs = mClock.getElapsedSinceBootMillis();
7017                 stats.txmpdu_be = info.txSuccess;
7018                 stats.retries_be = info.txRetries;
7019                 stats.lostmpdu_be = info.txBad;
7020                 stats.rxmpdu_be = info.rxSuccess;
7021             }
7022             WifiUsabilityStatsEntry wifiUsabilityStatsEntry =
7023                     mWifiUsabilityStatsEntriesList.size()
7024                     < MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE
7025                     ? new WifiUsabilityStatsEntry() : mWifiUsabilityStatsEntriesList.remove();
7026             wifiUsabilityStatsEntry.timeStampMs = stats.timeStampInMs;
7027             wifiUsabilityStatsEntry.totalTxSuccess = stats.txmpdu_be + stats.txmpdu_bk
7028                     + stats.txmpdu_vi + stats.txmpdu_vo;
7029             wifiUsabilityStatsEntry.totalTxRetries = stats.retries_be + stats.retries_bk
7030                     + stats.retries_vi + stats.retries_vo;
7031             wifiUsabilityStatsEntry.totalTxBad = stats.lostmpdu_be + stats.lostmpdu_bk
7032                     + stats.lostmpdu_vi + stats.lostmpdu_vo;
7033             wifiUsabilityStatsEntry.totalRxSuccess = stats.rxmpdu_be + stats.rxmpdu_bk
7034                     + stats.rxmpdu_vi + stats.rxmpdu_vo;
7035             /* Update per radio stats */
7036             if (stats.radioStats != null && stats.radioStats.length > 0) {
7037                 int numRadios = stats.radioStats.length;
7038                 wifiUsabilityStatsEntry.radioStats =
7039                         new RadioStats[numRadios];
7040                 for (int i = 0; i < numRadios; i++) {
7041                     RadioStats radioStats = new RadioStats();
7042                     WifiLinkLayerStats.RadioStat radio = stats.radioStats[i];
7043                     radioStats.radioId = radio.radio_id;
7044                     radioStats.totalRadioOnTimeMs = radio.on_time;
7045                     radioStats.totalRadioTxTimeMs = radio.tx_time;
7046                     radioStats.totalRadioRxTimeMs = radio.rx_time;
7047                     radioStats.totalScanTimeMs = radio.on_time_scan;
7048                     radioStats.totalNanScanTimeMs = radio.on_time_nan_scan;
7049                     radioStats.totalBackgroundScanTimeMs = radio.on_time_background_scan;
7050                     radioStats.totalRoamScanTimeMs = radio.on_time_roam_scan;
7051                     radioStats.totalPnoScanTimeMs = radio.on_time_pno_scan;
7052                     radioStats.totalHotspot2ScanTimeMs = radio.on_time_hs20_scan;
7053                     wifiUsabilityStatsEntry.radioStats[i] = radioStats;
7054                 }
7055             }
7056             wifiUsabilityStatsEntry.totalRadioOnTimeMs = stats.on_time;
7057             wifiUsabilityStatsEntry.totalRadioTxTimeMs = stats.tx_time;
7058             wifiUsabilityStatsEntry.totalRadioRxTimeMs = stats.rx_time;
7059             wifiUsabilityStatsEntry.totalScanTimeMs = stats.on_time_scan;
7060             wifiUsabilityStatsEntry.totalNanScanTimeMs = stats.on_time_nan_scan;
7061             wifiUsabilityStatsEntry.totalBackgroundScanTimeMs = stats.on_time_background_scan;
7062             wifiUsabilityStatsEntry.totalRoamScanTimeMs = stats.on_time_roam_scan;
7063             wifiUsabilityStatsEntry.totalPnoScanTimeMs = stats.on_time_pno_scan;
7064             wifiUsabilityStatsEntry.totalHotspot2ScanTimeMs = stats.on_time_hs20_scan;
7065             wifiUsabilityStatsEntry.rssi = info.getRssi();
7066             wifiUsabilityStatsEntry.linkSpeedMbps = info.getLinkSpeed();
7067             WifiLinkLayerStats.ChannelStats statsMap =
7068                     stats.channelStatsMap.get(info.getFrequency());
7069             if (statsMap != null) {
7070                 wifiUsabilityStatsEntry.totalRadioOnFreqTimeMs = statsMap.radioOnTimeMs;
7071                 wifiUsabilityStatsEntry.totalCcaBusyFreqTimeMs = statsMap.ccaBusyTimeMs;
7072             }
7073             wifiUsabilityStatsEntry.totalBeaconRx = stats.beacon_rx;
7074             mLastTotalBeaconRx = stats.beacon_rx;
7075             wifiUsabilityStatsEntry.timeSliceDutyCycleInPercent = stats.timeSliceDutyCycleInPercent;
7076 
7077             boolean isSameBssidAndFreq = mLastBssid == null || mLastFrequency == -1
7078                     || (mLastBssid.equals(info.getBSSID())
7079                     && mLastFrequency == info.getFrequency());
7080             mLastBssid = info.getBSSID();
7081             mLastFrequency = info.getFrequency();
7082             wifiUsabilityStatsEntry.wifiScore = mLastScoreNoReset;
7083             wifiUsabilityStatsEntry.wifiUsabilityScore = mLastWifiUsabilityScoreNoReset;
7084             wifiUsabilityStatsEntry.seqNumToFramework = mSeqNumToFramework;
7085             wifiUsabilityStatsEntry.predictionHorizonSec = mLastPredictionHorizonSecNoReset;
7086             switch (mProbeStatusSinceLastUpdate) {
7087                 case android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE:
7088                     wifiUsabilityStatsEntry.probeStatusSinceLastUpdate =
7089                             WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE;
7090                     break;
7091                 case android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS:
7092                     wifiUsabilityStatsEntry.probeStatusSinceLastUpdate =
7093                             WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS;
7094                     break;
7095                 case android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE:
7096                     wifiUsabilityStatsEntry.probeStatusSinceLastUpdate =
7097                             WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE;
7098                     break;
7099                 default:
7100                     wifiUsabilityStatsEntry.probeStatusSinceLastUpdate =
7101                             WifiUsabilityStatsEntry.PROBE_STATUS_UNKNOWN;
7102                     Log.e(TAG, "Unknown link probe status: " + mProbeStatusSinceLastUpdate);
7103             }
7104             wifiUsabilityStatsEntry.probeElapsedTimeSinceLastUpdateMs =
7105                     mProbeElapsedTimeSinceLastUpdateMs;
7106             wifiUsabilityStatsEntry.probeMcsRateSinceLastUpdate = mProbeMcsRateSinceLastUpdate;
7107             wifiUsabilityStatsEntry.rxLinkSpeedMbps = info.getRxLinkSpeedMbps();
7108             wifiUsabilityStatsEntry.isSameBssidAndFreq = isSameBssidAndFreq;
7109             wifiUsabilityStatsEntry.seqNumInsideFramework = mSeqNumInsideFramework;
7110             wifiUsabilityStatsEntry.deviceMobilityState = mCurrentDeviceMobilityState;
7111             wifiUsabilityStatsEntry.contentionTimeStats =
7112                     new ContentionTimeStats[NUM_WME_ACCESS_CATEGORIES];
7113             for (int ac = 0; ac < NUM_WME_ACCESS_CATEGORIES; ac++) {
7114                 ContentionTimeStats contentionTimeStats = new ContentionTimeStats();
7115                 switch (ac) {
7116                     case ContentionTimeStats.WME_ACCESS_CATEGORY_BE:
7117                         contentionTimeStats.accessCategory =
7118                                 ContentionTimeStats.WME_ACCESS_CATEGORY_BE;
7119                         contentionTimeStats.contentionTimeMinMicros =
7120                                 stats.contentionTimeMinBeInUsec;
7121                         contentionTimeStats.contentionTimeMaxMicros =
7122                                 stats.contentionTimeMaxBeInUsec;
7123                         contentionTimeStats.contentionTimeAvgMicros =
7124                                 stats.contentionTimeAvgBeInUsec;
7125                         contentionTimeStats.contentionNumSamples =
7126                                 stats.contentionNumSamplesBe;
7127                         break;
7128                     case ContentionTimeStats.WME_ACCESS_CATEGORY_BK:
7129                         contentionTimeStats.accessCategory =
7130                                 ContentionTimeStats.WME_ACCESS_CATEGORY_BK;
7131                         contentionTimeStats.contentionTimeMinMicros =
7132                                 stats.contentionTimeMinBkInUsec;
7133                         contentionTimeStats.contentionTimeMaxMicros =
7134                                 stats.contentionTimeMaxBkInUsec;
7135                         contentionTimeStats.contentionTimeAvgMicros =
7136                                 stats.contentionTimeAvgBkInUsec;
7137                         contentionTimeStats.contentionNumSamples =
7138                                 stats.contentionNumSamplesBk;
7139                         break;
7140                     case ContentionTimeStats.WME_ACCESS_CATEGORY_VI:
7141                         contentionTimeStats.accessCategory =
7142                                 ContentionTimeStats.WME_ACCESS_CATEGORY_VI;
7143                         contentionTimeStats.contentionTimeMinMicros =
7144                                 stats.contentionTimeMinViInUsec;
7145                         contentionTimeStats.contentionTimeMaxMicros =
7146                                 stats.contentionTimeMaxViInUsec;
7147                         contentionTimeStats.contentionTimeAvgMicros =
7148                                 stats.contentionTimeAvgViInUsec;
7149                         contentionTimeStats.contentionNumSamples =
7150                                 stats.contentionNumSamplesVi;
7151                         break;
7152                     case ContentionTimeStats.WME_ACCESS_CATEGORY_VO:
7153                         contentionTimeStats.accessCategory =
7154                                 ContentionTimeStats.WME_ACCESS_CATEGORY_VO;
7155                         contentionTimeStats.contentionTimeMinMicros =
7156                                 stats.contentionTimeMinVoInUsec;
7157                         contentionTimeStats.contentionTimeMaxMicros =
7158                                 stats.contentionTimeMaxVoInUsec;
7159                         contentionTimeStats.contentionTimeAvgMicros =
7160                                 stats.contentionTimeAvgVoInUsec;
7161                         contentionTimeStats.contentionNumSamples =
7162                                 stats.contentionNumSamplesVo;
7163                         break;
7164                     default:
7165                         Log.e(TAG, "Unknown WME Access Category: " + ac);
7166                 }
7167                 wifiUsabilityStatsEntry.contentionTimeStats[ac] = contentionTimeStats;
7168             }
7169             if (mWifiChannelUtilization != null) {
7170                 wifiUsabilityStatsEntry.channelUtilizationRatio =
7171                         mWifiChannelUtilization.getUtilizationRatio(mLastFrequency);
7172             }
7173             if (mWifiDataStall != null) {
7174                 wifiUsabilityStatsEntry.isThroughputSufficient =
7175                         mWifiDataStall.isThroughputSufficient();
7176                 wifiUsabilityStatsEntry.isCellularDataAvailable =
7177                         mWifiDataStall.isCellularDataAvailable();
7178             }
7179             if (mWifiSettingsStore != null) {
7180                 wifiUsabilityStatsEntry.isWifiScoringEnabled =
7181                         mWifiSettingsStore.isWifiScoringEnabled();
7182             }
7183             // Here it is assumed there is only one peer information from HAL and the peer is the
7184             // AP that STA is associated with.
7185             if (stats.peerInfo != null && stats.peerInfo.length > 0
7186                     && stats.peerInfo[0].rateStats != null) {
7187                 wifiUsabilityStatsEntry.staCount = stats.peerInfo[0].staCount;
7188                 wifiUsabilityStatsEntry.channelUtilization = stats.peerInfo[0].chanUtil;
7189                 int numRates = stats.peerInfo[0].rateStats != null
7190                         ? stats.peerInfo[0].rateStats.length : 0;
7191                 wifiUsabilityStatsEntry.rateStats = new RateStats[numRates];
7192                 for (int i = 0; i < numRates; i++) {
7193                     RateStats rate = new RateStats();
7194                     WifiLinkLayerStats.RateStat curRate = stats.peerInfo[0].rateStats[i];
7195                     rate.preamble = curRate.preamble;
7196                     rate.nss = curRate.nss;
7197                     rate.bw = curRate.bw;
7198                     rate.rateMcsIdx = curRate.rateMcsIdx;
7199                     rate.bitRateInKbps = curRate.bitRateInKbps;
7200                     rate.txMpdu = curRate.txMpdu;
7201                     rate.rxMpdu = curRate.rxMpdu;
7202                     rate.mpduLost = curRate.mpduLost;
7203                     rate.retries = curRate.retries;
7204                     wifiUsabilityStatsEntry.rateStats[i] = rate;
7205                 }
7206             }
7207 
7208             mWifiUsabilityStatsEntriesList.add(wifiUsabilityStatsEntry);
7209             mWifiUsabilityStatsCounter++;
7210             if (mWifiUsabilityStatsCounter >= NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD) {
7211                 addToWifiUsabilityStatsList(ifaceName, WifiUsabilityStats.LABEL_GOOD,
7212                         WifiUsabilityStats.TYPE_UNKNOWN, -1);
7213             }
7214             if (mScoreBreachLowTimeMillis != -1) {
7215                 long elapsedTime =  mClock.getElapsedSinceBootMillis() - mScoreBreachLowTimeMillis;
7216                 if (elapsedTime >= MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS) {
7217                     mScoreBreachLowTimeMillis = -1;
7218                     if (elapsedTime <= VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS) {
7219                         addToWifiUsabilityStatsList(ifaceName, WifiUsabilityStats.LABEL_GOOD,
7220                                 WifiUsabilityStats.TYPE_UNKNOWN, -1);
7221                     }
7222                 }
7223             }
7224 
7225             // Invoke Wifi usability stats listener.
7226             // TODO(b/179518316): Enable this for secondary transient STA also if external scorer
7227             // is in charge of MBB.
7228             if (isPrimary(ifaceName)) {
7229                 sendWifiUsabilityStats(mSeqNumInsideFramework, isSameBssidAndFreq,
7230                         createNewWifiUsabilityStatsEntryParcelable(wifiUsabilityStatsEntry, stats,
7231                                 info));
7232             }
7233 
7234             mSeqNumInsideFramework++;
7235             mProbeStatusSinceLastUpdate =
7236                     android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE;
7237             mProbeElapsedTimeSinceLastUpdateMs = -1;
7238             mProbeMcsRateSinceLastUpdate = -1;
7239         }
7240     }
7241 
7242     /**
7243      * Send Wifi usability stats.
7244      * @param seqNum
7245      * @param isSameBssidAndFreq
7246      * @param statsEntry
7247      */
7248     private void sendWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq,
7249             android.net.wifi.WifiUsabilityStatsEntry statsEntry) {
7250         int itemCount = mOnWifiUsabilityListeners.beginBroadcast();
7251         for (int i = 0; i < itemCount; i++) {
7252             try {
7253                 mOnWifiUsabilityListeners.getBroadcastItem(i).onWifiUsabilityStats(seqNum,
7254                         isSameBssidAndFreq, statsEntry);
7255             } catch (RemoteException e) {
7256                 Log.e(TAG, "Unable to invoke Wifi usability stats entry listener ", e);
7257             }
7258         }
7259         mOnWifiUsabilityListeners.finishBroadcast();
7260     }
7261 
7262     private android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats[]
7263             convertContentionTimeStats(WifiLinkLayerStats.LinkSpecificStats stats) {
7264         android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats[] contentionTimeStatsArray =
7265                 new android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats[
7266                         android.net.wifi.WifiUsabilityStatsEntry.NUM_WME_ACCESS_CATEGORIES];
7267         for (int ac = 0; ac < android.net.wifi.WifiUsabilityStatsEntry.NUM_WME_ACCESS_CATEGORIES;
7268                 ac++) {
7269             android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats contentionTimeStats = null;
7270             switch (ac) {
7271                 case android.net.wifi.WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE:
7272                     contentionTimeStats =
7273                             new android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats(
7274                                     stats.contentionTimeMinBeInUsec,
7275                                     stats.contentionTimeMaxBeInUsec,
7276                                     stats.contentionTimeAvgBeInUsec,
7277                                     stats.contentionNumSamplesBe
7278                             );
7279                     break;
7280                 case android.net.wifi.WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK:
7281                     contentionTimeStats =
7282                             new android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats(
7283                                     stats.contentionTimeMinBkInUsec,
7284                                     stats.contentionTimeMaxBkInUsec,
7285                                     stats.contentionTimeAvgBkInUsec,
7286                                     stats.contentionNumSamplesBk
7287                             );
7288                     break;
7289                 case android.net.wifi.WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO:
7290                     contentionTimeStats =
7291                             new android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats(
7292                                     stats.contentionTimeMinVoInUsec,
7293                                     stats.contentionTimeMaxVoInUsec,
7294                                     stats.contentionTimeAvgVoInUsec,
7295                                     stats.contentionNumSamplesVo
7296                             );
7297                     break;
7298                 case android.net.wifi.WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI:
7299                     contentionTimeStats =
7300                             new android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats(
7301                                     stats.contentionTimeMinViInUsec,
7302                                     stats.contentionTimeMaxViInUsec,
7303                                     stats.contentionTimeAvgViInUsec,
7304                                     stats.contentionNumSamplesVi
7305                             );
7306                     break;
7307                 default:
7308                     Log.d(TAG, "Unknown WME Access Category: " + ac);
7309                     contentionTimeStats = null;
7310             }
7311             contentionTimeStatsArray[ac] = contentionTimeStats;
7312         }
7313         return contentionTimeStatsArray;
7314     }
7315 
7316     private android.net.wifi.WifiUsabilityStatsEntry.RateStats[] convertRateStats(
7317             WifiLinkLayerStats.LinkSpecificStats stats) {
7318         android.net.wifi.WifiUsabilityStatsEntry.RateStats[] rateStats = null;
7319         if (stats.peerInfo != null && stats.peerInfo.length > 0
7320                 && stats.peerInfo[0].rateStats != null) {
7321             int numRates = stats.peerInfo[0].rateStats != null
7322                     ? stats.peerInfo[0].rateStats.length : 0;
7323             rateStats = new android.net.wifi.WifiUsabilityStatsEntry.RateStats[numRates];
7324             for (int i = 0; i < numRates; i++) {
7325                 WifiLinkLayerStats.RateStat curRate = stats.peerInfo[0].rateStats[i];
7326                 android.net.wifi.WifiUsabilityStatsEntry.RateStats rate =
7327                         new android.net.wifi.WifiUsabilityStatsEntry.RateStats(
7328                                 convertPreambleTypeEnumToUsabilityStatsType(curRate.preamble),
7329                                 convertSpatialStreamEnumToUsabilityStatsType(curRate.nss),
7330                                 convertBandwidthEnumToUsabilityStatsType(curRate.bw),
7331                                 curRate.rateMcsIdx, curRate.bitRateInKbps,
7332                                 curRate.txMpdu, curRate.rxMpdu, curRate.mpduLost, curRate.retries);
7333                 rateStats[i] = rate;
7334             }
7335         }
7336         return rateStats;
7337     }
7338 
7339     private SparseArray<android.net.wifi.WifiUsabilityStatsEntry.LinkStats> convertLinkStats(
7340             WifiLinkLayerStats stats, WifiInfo info) {
7341         SparseArray<android.net.wifi.WifiUsabilityStatsEntry.LinkStats> linkStats =
7342                 new SparseArray<>();
7343         if (stats == null || stats.links == null || stats.links.length == 0) return linkStats;
7344         // Create a link id to MLO link mapping
7345         SparseArray<MloLink> mloLinks = new SparseArray<>();
7346         for (MloLink link: info.getAffiliatedMloLinks()) {
7347             mloLinks.put(link.getLinkId(), link);
7348         }
7349         mLastLinkMetrics.clear();
7350         // Fill per link stats.
7351         for (WifiLinkLayerStats.LinkSpecificStats inStat : stats.links) {
7352             if (inStat == null) break;
7353             LinkMetrics linkMetrics = new LinkMetrics();
7354             linkMetrics.setTotalBeaconRx(inStat.beacon_rx);
7355             linkMetrics.setLinkUsageState(inStat.state);
7356             mLastLinkMetrics.put(inStat.link_id, linkMetrics);
7357             WifiLinkLayerStats.ChannelStats channelStatsMap = stats.channelStatsMap.get(
7358                     inStat.frequencyMhz);
7359             // Note: RSSI, Tx & Rx link speed are derived from signal poll stats which is updated in
7360             // Mlolink or WifiInfo (non-MLO case).
7361             android.net.wifi.WifiUsabilityStatsEntry.LinkStats outStat =
7362                     new android.net.wifi.WifiUsabilityStatsEntry.LinkStats(inStat.link_id,
7363                             inStat.state, inStat.radio_id,
7364                             (mloLinks.size() > 0) ? mloLinks.get(inStat.link_id,
7365                                     new MloLink()).getRssi() : info.getRssi(),
7366                             (mloLinks.size() > 0) ? mloLinks.get(inStat.link_id,
7367                                     new MloLink()).getTxLinkSpeedMbps() : info.getTxLinkSpeedMbps(),
7368                             (mloLinks.size() > 0) ? mloLinks.get(inStat.link_id,
7369                                     new MloLink()).getRxLinkSpeedMbps() : info.getRxLinkSpeedMbps(),
7370                             inStat.txmpdu_be + inStat.txmpdu_bk + inStat.txmpdu_vi
7371                                     + inStat.txmpdu_vo,
7372                             inStat.retries_be + inStat.retries_bk + inStat.retries_vi
7373                                     + inStat.retries_vo,
7374                             inStat.lostmpdu_be + inStat.lostmpdu_bk + inStat.lostmpdu_vo
7375                                     + inStat.lostmpdu_vi,
7376                             inStat.rxmpdu_be + inStat.rxmpdu_bk + inStat.rxmpdu_vo
7377                                     + inStat.rxmpdu_vi,
7378                             inStat.beacon_rx, inStat.timeSliceDutyCycleInPercent,
7379                             (channelStatsMap != null) ? channelStatsMap.ccaBusyTimeMs : 0 ,
7380                             (channelStatsMap != null) ? channelStatsMap.radioOnTimeMs : 0,
7381                             convertContentionTimeStats(inStat),
7382                             convertRateStats(inStat));
7383             linkStats.put(inStat.link_id, outStat);
7384         }
7385 
7386         return linkStats;
7387     }
7388 
7389     private android.net.wifi.WifiUsabilityStatsEntry createNewWifiUsabilityStatsEntryParcelable(
7390             WifiUsabilityStatsEntry s, WifiLinkLayerStats stats, WifiInfo info) {
7391         int probeStatus;
7392         switch (s.probeStatusSinceLastUpdate) {
7393             case WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE:
7394                 probeStatus = android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE;
7395                 break;
7396             case WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS:
7397                 probeStatus = android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS;
7398                 break;
7399             case WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE:
7400                 probeStatus = android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE;
7401                 break;
7402             default:
7403                 probeStatus = android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_UNKNOWN;
7404                 Log.e(TAG, "Unknown link probe status: " + s.probeStatusSinceLastUpdate);
7405         }
7406         android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats[] contentionTimeStats =
7407                 new android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats[
7408                         android.net.wifi.WifiUsabilityStatsEntry.NUM_WME_ACCESS_CATEGORIES];
7409         createNewContentionTimeStatsParcelable(contentionTimeStats, s.contentionTimeStats);
7410         int numRates = s.rateStats != null ? s.rateStats.length : 0;
7411         android.net.wifi.WifiUsabilityStatsEntry.RateStats[] rateStats =
7412                 new android.net.wifi.WifiUsabilityStatsEntry.RateStats[numRates];
7413         createNewRateStatsParcelable(rateStats, s.rateStats);
7414         int numRadios = s.radioStats != null ? s.radioStats.length : 0;
7415         android.net.wifi.WifiUsabilityStatsEntry.RadioStats[] radioStats =
7416                 new android.net.wifi.WifiUsabilityStatsEntry.RadioStats[numRadios];
7417         createNewRadioStatsParcelable(radioStats, s.radioStats);
7418         // TODO: remove the following hardcoded values once if they are removed from public API
7419         return new android.net.wifi.WifiUsabilityStatsEntry(s.timeStampMs, s.rssi,
7420                 s.linkSpeedMbps, s.totalTxSuccess, s.totalTxRetries,
7421                 s.totalTxBad, s.totalRxSuccess, s.totalRadioOnTimeMs,
7422                 s.totalRadioTxTimeMs, s.totalRadioRxTimeMs, s.totalScanTimeMs,
7423                 s.totalNanScanTimeMs, s.totalBackgroundScanTimeMs, s.totalRoamScanTimeMs,
7424                 s.totalPnoScanTimeMs, s.totalHotspot2ScanTimeMs, s.totalCcaBusyFreqTimeMs,
7425                 s.totalRadioOnFreqTimeMs, s.totalBeaconRx, probeStatus,
7426                 s.probeElapsedTimeSinceLastUpdateMs, s.probeMcsRateSinceLastUpdate,
7427                 s.rxLinkSpeedMbps, s.timeSliceDutyCycleInPercent, contentionTimeStats, rateStats,
7428                 radioStats, s.channelUtilizationRatio, s.isThroughputSufficient,
7429                 s.isWifiScoringEnabled, s.isCellularDataAvailable, 0, 0, 0, false,
7430                 convertLinkStats(stats, info)
7431         );
7432     }
7433 
7434     private void createNewContentionTimeStatsParcelable(
7435             android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats[] statsParcelable,
7436                     ContentionTimeStats[] stats) {
7437         if (statsParcelable.length != stats.length || stats.length != NUM_WME_ACCESS_CATEGORIES) {
7438             Log.e(TAG, "The two ContentionTimeStats do not match in length: "
7439                     + " in proto: " + stats.length
7440                     + " in system API: " + statsParcelable.length);
7441             return;
7442         }
7443         for (int ac = 0; ac < NUM_WME_ACCESS_CATEGORIES; ac++) {
7444             android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats stat =
7445                     new android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats(
7446                             stats[ac].contentionTimeMinMicros,
7447                             stats[ac].contentionTimeMaxMicros,
7448                             stats[ac].contentionTimeAvgMicros,
7449                             stats[ac].contentionNumSamples);
7450             switch (ac) {
7451                 case ContentionTimeStats.WME_ACCESS_CATEGORY_BE:
7452                     statsParcelable[
7453                             android.net.wifi.WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE] = stat;
7454                     break;
7455                 case ContentionTimeStats.WME_ACCESS_CATEGORY_BK:
7456                     statsParcelable[
7457                             android.net.wifi.WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK] = stat;
7458                     break;
7459                 case ContentionTimeStats.WME_ACCESS_CATEGORY_VI:
7460                     statsParcelable[
7461                             android.net.wifi.WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI] = stat;
7462                     break;
7463                 case ContentionTimeStats.WME_ACCESS_CATEGORY_VO:
7464                     statsParcelable[
7465                             android.net.wifi.WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO] = stat;
7466                     break;
7467                 default:
7468                     Log.e(TAG, "Unknown WME Access Category: " + ac);
7469             }
7470         }
7471     }
7472 
7473     private void createNewRateStatsParcelable(
7474             android.net.wifi.WifiUsabilityStatsEntry.RateStats[] statsParcelable,
7475                     RateStats[] stats) {
7476         if (stats == null) {
7477             return;
7478         }
7479         for (int i = 0; i < stats.length; i++) {
7480             statsParcelable[i] = new android.net.wifi.WifiUsabilityStatsEntry.RateStats(
7481                     convertPreambleTypeEnumToUsabilityStatsType(stats[i].preamble),
7482                     convertSpatialStreamEnumToUsabilityStatsType(stats[i].nss),
7483                     convertBandwidthEnumToUsabilityStatsType(stats[i].bw),
7484                     stats[i].rateMcsIdx, stats[i].bitRateInKbps, stats[i].txMpdu, stats[i].rxMpdu,
7485                     stats[i].mpduLost, stats[i].retries
7486             );
7487         }
7488     }
7489 
7490     /**
7491      * Converts bandwidth enum in proto to WifiUsabilityStatsEntry type.
7492      * @param value
7493      */
7494     @VisibleForTesting
7495     public static int convertBandwidthEnumToUsabilityStatsType(int value) {
7496         switch (value) {
7497             case RateStats.WIFI_BANDWIDTH_20_MHZ:
7498                 return android.net.wifi.WifiUsabilityStatsEntry.WIFI_BANDWIDTH_20_MHZ;
7499             case RateStats.WIFI_BANDWIDTH_40_MHZ:
7500                 return android.net.wifi.WifiUsabilityStatsEntry.WIFI_BANDWIDTH_40_MHZ;
7501             case RateStats.WIFI_BANDWIDTH_80_MHZ:
7502                 return android.net.wifi.WifiUsabilityStatsEntry.WIFI_BANDWIDTH_80_MHZ;
7503             case RateStats.WIFI_BANDWIDTH_160_MHZ:
7504                 return android.net.wifi.WifiUsabilityStatsEntry.WIFI_BANDWIDTH_160_MHZ;
7505             case RateStats.WIFI_BANDWIDTH_80P80_MHZ:
7506                 return android.net.wifi.WifiUsabilityStatsEntry.WIFI_BANDWIDTH_80P80_MHZ;
7507             case RateStats.WIFI_BANDWIDTH_5_MHZ:
7508                 return android.net.wifi.WifiUsabilityStatsEntry.WIFI_BANDWIDTH_5_MHZ;
7509             case RateStats.WIFI_BANDWIDTH_10_MHZ:
7510                 return android.net.wifi.WifiUsabilityStatsEntry.WIFI_BANDWIDTH_10_MHZ;
7511         }
7512         return android.net.wifi.WifiUsabilityStatsEntry.WIFI_BANDWIDTH_INVALID;
7513     }
7514 
7515     /**
7516      * Converts spatial streams enum in proto to WifiUsabilityStatsEntry type.
7517      * @param value
7518      */
7519     @VisibleForTesting
7520     public static int convertSpatialStreamEnumToUsabilityStatsType(int value) {
7521         switch (value) {
7522             case RateStats.WIFI_SPATIAL_STREAMS_ONE:
7523                 return android.net.wifi.WifiUsabilityStatsEntry.WIFI_SPATIAL_STREAMS_ONE;
7524             case RateStats.WIFI_SPATIAL_STREAMS_TWO:
7525                 return android.net.wifi.WifiUsabilityStatsEntry.WIFI_SPATIAL_STREAMS_TWO;
7526             case RateStats.WIFI_SPATIAL_STREAMS_THREE:
7527                 return android.net.wifi.WifiUsabilityStatsEntry.WIFI_SPATIAL_STREAMS_THREE;
7528             case RateStats.WIFI_SPATIAL_STREAMS_FOUR:
7529                 return android.net.wifi.WifiUsabilityStatsEntry.WIFI_SPATIAL_STREAMS_FOUR;
7530         }
7531         return android.net.wifi.WifiUsabilityStatsEntry.WIFI_SPATIAL_STREAMS_INVALID;
7532     }
7533 
7534     /**
7535      * Converts preamble type enum in proto to WifiUsabilityStatsEntry type.
7536      * @param value
7537      */
7538     @VisibleForTesting
7539     public static int convertPreambleTypeEnumToUsabilityStatsType(int value) {
7540         switch (value) {
7541             case RateStats.WIFI_PREAMBLE_OFDM:
7542                 return android.net.wifi.WifiUsabilityStatsEntry.WIFI_PREAMBLE_OFDM;
7543             case RateStats.WIFI_PREAMBLE_CCK:
7544                 return android.net.wifi.WifiUsabilityStatsEntry.WIFI_PREAMBLE_CCK;
7545             case RateStats.WIFI_PREAMBLE_HT:
7546                 return android.net.wifi.WifiUsabilityStatsEntry.WIFI_PREAMBLE_HT;
7547             case RateStats.WIFI_PREAMBLE_VHT:
7548                 return android.net.wifi.WifiUsabilityStatsEntry.WIFI_PREAMBLE_VHT;
7549             case RateStats.WIFI_PREAMBLE_HE:
7550                 return android.net.wifi.WifiUsabilityStatsEntry.WIFI_PREAMBLE_HE;
7551         }
7552         return android.net.wifi.WifiUsabilityStatsEntry.WIFI_PREAMBLE_INVALID;
7553     }
7554 
7555     private void createNewRadioStatsParcelable(
7556             android.net.wifi.WifiUsabilityStatsEntry.RadioStats[] statsParcelable,
7557             RadioStats[] stats) {
7558         if (stats == null) {
7559             return;
7560         }
7561         for (int i = 0; i < stats.length; i++) {
7562             statsParcelable[i] =
7563                     new android.net.wifi.WifiUsabilityStatsEntry.RadioStats(
7564                             stats[i].radioId,
7565                             stats[i].totalRadioOnTimeMs,
7566                             stats[i].totalRadioTxTimeMs,
7567                             stats[i].totalRadioRxTimeMs,
7568                             stats[i].totalScanTimeMs,
7569                             stats[i].totalNanScanTimeMs,
7570                             stats[i].totalBackgroundScanTimeMs,
7571                             stats[i].totalRoamScanTimeMs,
7572                             stats[i].totalPnoScanTimeMs,
7573                             stats[i].totalHotspot2ScanTimeMs);
7574         }
7575     }
7576 
7577     private WifiUsabilityStatsEntry createNewWifiUsabilityStatsEntry(WifiUsabilityStatsEntry s) {
7578         WifiUsabilityStatsEntry out = new WifiUsabilityStatsEntry();
7579         out.timeStampMs = s.timeStampMs;
7580         out.totalTxSuccess = s.totalTxSuccess;
7581         out.totalTxRetries = s.totalTxRetries;
7582         out.totalTxBad = s.totalTxBad;
7583         out.totalRxSuccess = s.totalRxSuccess;
7584         out.totalRadioOnTimeMs = s.totalRadioOnTimeMs;
7585         out.totalRadioTxTimeMs = s.totalRadioTxTimeMs;
7586         out.totalRadioRxTimeMs = s.totalRadioRxTimeMs;
7587         out.totalScanTimeMs = s.totalScanTimeMs;
7588         out.totalNanScanTimeMs = s.totalNanScanTimeMs;
7589         out.totalBackgroundScanTimeMs = s.totalBackgroundScanTimeMs;
7590         out.totalRoamScanTimeMs = s.totalRoamScanTimeMs;
7591         out.totalPnoScanTimeMs = s.totalPnoScanTimeMs;
7592         out.totalHotspot2ScanTimeMs = s.totalHotspot2ScanTimeMs;
7593         out.rssi = s.rssi;
7594         out.linkSpeedMbps = s.linkSpeedMbps;
7595         out.totalCcaBusyFreqTimeMs = s.totalCcaBusyFreqTimeMs;
7596         out.totalRadioOnFreqTimeMs = s.totalRadioOnFreqTimeMs;
7597         out.totalBeaconRx = s.totalBeaconRx;
7598         out.wifiScore = s.wifiScore;
7599         out.wifiUsabilityScore = s.wifiUsabilityScore;
7600         out.seqNumToFramework = s.seqNumToFramework;
7601         out.predictionHorizonSec = s.predictionHorizonSec;
7602         out.probeStatusSinceLastUpdate = s.probeStatusSinceLastUpdate;
7603         out.probeElapsedTimeSinceLastUpdateMs = s.probeElapsedTimeSinceLastUpdateMs;
7604         out.probeMcsRateSinceLastUpdate = s.probeMcsRateSinceLastUpdate;
7605         out.rxLinkSpeedMbps = s.rxLinkSpeedMbps;
7606         out.isSameBssidAndFreq = s.isSameBssidAndFreq;
7607         out.seqNumInsideFramework = s.seqNumInsideFramework;
7608         out.deviceMobilityState = s.deviceMobilityState;
7609         out.timeSliceDutyCycleInPercent = s.timeSliceDutyCycleInPercent;
7610         out.contentionTimeStats = s.contentionTimeStats;
7611         out.channelUtilizationRatio = s.channelUtilizationRatio;
7612         out.isThroughputSufficient = s.isThroughputSufficient;
7613         out.isWifiScoringEnabled = s.isWifiScoringEnabled;
7614         out.isCellularDataAvailable = s.isCellularDataAvailable;
7615         out.rateStats = s.rateStats;
7616         out.staCount = s.staCount;
7617         out.channelUtilization = s.channelUtilization;
7618         out.radioStats = s.radioStats;
7619         return out;
7620     }
7621 
7622     private WifiUsabilityStats createWifiUsabilityStatsWithLabel(int label, int triggerType,
7623             int firmwareAlertCode) {
7624         WifiUsabilityStats wifiUsabilityStats = new WifiUsabilityStats();
7625         wifiUsabilityStats.label = label;
7626         wifiUsabilityStats.triggerType = triggerType;
7627         wifiUsabilityStats.firmwareAlertCode = firmwareAlertCode;
7628         wifiUsabilityStats.timeStampMs = mClock.getElapsedSinceBootMillis();
7629         wifiUsabilityStats.stats =
7630                 new WifiUsabilityStatsEntry[mWifiUsabilityStatsEntriesList.size()];
7631         for (int i = 0; i < mWifiUsabilityStatsEntriesList.size(); i++) {
7632             wifiUsabilityStats.stats[i] =
7633                     createNewWifiUsabilityStatsEntry(mWifiUsabilityStatsEntriesList.get(i));
7634         }
7635         return wifiUsabilityStats;
7636     }
7637 
7638     /**
7639      * Label the current snapshot of WifiUsabilityStatsEntrys and save the labeled data in memory.
7640      * @param label WifiUsabilityStats.LABEL_GOOD or WifiUsabilityStats.LABEL_BAD
7641      * @param triggerType what event triggers WifiUsabilityStats
7642      * @param firmwareAlertCode the firmware alert code when the stats was triggered by a
7643      *        firmware alert
7644      */
7645     public void addToWifiUsabilityStatsList(String ifaceName, int label, int triggerType,
7646             int firmwareAlertCode) {
7647         synchronized (mLock) {
7648             if (!isPrimary(ifaceName)) {
7649                 return;
7650             }
7651             if (mWifiUsabilityStatsEntriesList.isEmpty() || !mScreenOn) {
7652                 return;
7653             }
7654             if (label == WifiUsabilityStats.LABEL_GOOD) {
7655                 // Only add a good event if at least |MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS|
7656                 // has passed.
7657                 if (mWifiUsabilityStatsListGood.isEmpty()
7658                         || mWifiUsabilityStatsListGood.getLast().stats[mWifiUsabilityStatsListGood
7659                         .getLast().stats.length - 1].timeStampMs
7660                         + MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS
7661                         < mWifiUsabilityStatsEntriesList.getLast().timeStampMs) {
7662                     while (mWifiUsabilityStatsListGood.size()
7663                             >= MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE) {
7664                         mWifiUsabilityStatsListGood.remove(
7665                                 mRand.nextInt(mWifiUsabilityStatsListGood.size()));
7666                     }
7667                     mWifiUsabilityStatsListGood.add(
7668                             createWifiUsabilityStatsWithLabel(label, triggerType,
7669                                     firmwareAlertCode));
7670                 }
7671             } else {
7672                 // Only add a bad event if at least |MIN_DATA_STALL_WAIT_MS|
7673                 // has passed.
7674                 mScoreBreachLowTimeMillis = -1;
7675                 if (mWifiUsabilityStatsListBad.isEmpty()
7676                         || (mWifiUsabilityStatsListBad.getLast().stats[mWifiUsabilityStatsListBad
7677                         .getLast().stats.length - 1].timeStampMs
7678                         + MIN_DATA_STALL_WAIT_MS
7679                         < mWifiUsabilityStatsEntriesList.getLast().timeStampMs)) {
7680                     while (mWifiUsabilityStatsListBad.size()
7681                             >= MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE) {
7682                         mWifiUsabilityStatsListBad.remove(
7683                                 mRand.nextInt(mWifiUsabilityStatsListBad.size()));
7684                     }
7685                     mWifiUsabilityStatsListBad.add(
7686                             createWifiUsabilityStatsWithLabel(label, triggerType,
7687                                     firmwareAlertCode));
7688                 }
7689             }
7690             mWifiUsabilityStatsCounter = 0;
7691             mWifiUsabilityStatsEntriesList.clear();
7692         }
7693     }
7694 
7695     private DeviceMobilityStatePnoScanStats getOrCreateDeviceMobilityStatePnoScanStats(
7696             @DeviceMobilityState int deviceMobilityState) {
7697         DeviceMobilityStatePnoScanStats stats = mMobilityStatePnoStatsMap.get(deviceMobilityState);
7698         if (stats == null) {
7699             stats = new DeviceMobilityStatePnoScanStats();
7700             stats.deviceMobilityState = deviceMobilityState;
7701             stats.numTimesEnteredState = 0;
7702             stats.totalDurationMs = 0;
7703             stats.pnoDurationMs = 0;
7704             mMobilityStatePnoStatsMap.put(deviceMobilityState, stats);
7705         }
7706         return stats;
7707     }
7708 
7709     /**
7710      * Updates the current device mobility state's total duration. This method should be called
7711      * before entering a new device mobility state.
7712      */
7713     private void updateCurrentMobilityStateTotalDuration(long now) {
7714         DeviceMobilityStatePnoScanStats stats =
7715                 getOrCreateDeviceMobilityStatePnoScanStats(mCurrentDeviceMobilityState);
7716         stats.totalDurationMs += now - mCurrentDeviceMobilityStateStartMs;
7717         mCurrentDeviceMobilityStateStartMs = now;
7718     }
7719 
7720     /**
7721      * Convert the IntCounter of passpoint profile types and counts to proto's
7722      * repeated IntKeyVal array.
7723      *
7724      * @param passpointProfileTypes passpoint profile types and counts.
7725      */
7726     private PasspointProfileTypeCount[] convertPasspointProfilesToProto(
7727                 IntCounter passpointProfileTypes) {
7728         return passpointProfileTypes.toProto(PasspointProfileTypeCount.class, (key, count) -> {
7729             PasspointProfileTypeCount entry = new PasspointProfileTypeCount();
7730             entry.eapMethodType = key;
7731             entry.count = count;
7732             return entry;
7733         });
7734     }
7735 
7736     /**
7737      * Reports that the device entered a new mobility state.
7738      *
7739      * @param newState the new device mobility state.
7740      */
7741     public void enterDeviceMobilityState(@DeviceMobilityState int newState) {
7742         synchronized (mLock) {
7743             long now = mClock.getElapsedSinceBootMillis();
7744             updateCurrentMobilityStateTotalDuration(now);
7745 
7746             if (newState == mCurrentDeviceMobilityState) return;
7747 
7748             mCurrentDeviceMobilityState = newState;
7749             DeviceMobilityStatePnoScanStats stats =
7750                     getOrCreateDeviceMobilityStatePnoScanStats(mCurrentDeviceMobilityState);
7751             stats.numTimesEnteredState++;
7752         }
7753     }
7754 
7755     /**
7756      * Logs the start of a PNO scan.
7757      */
7758     public void logPnoScanStart() {
7759         synchronized (mLock) {
7760             long now = mClock.getElapsedSinceBootMillis();
7761             mCurrentDeviceMobilityStatePnoScanStartMs = now;
7762             updateCurrentMobilityStateTotalDuration(now);
7763         }
7764     }
7765 
7766     /**
7767      * Logs the end of a PNO scan. This is attributed to the current device mobility state, as
7768      * logged by {@link #enterDeviceMobilityState(int)}. Thus, if the mobility state changes during
7769      * a PNO scan, one should call {@link #logPnoScanStop()}, {@link #enterDeviceMobilityState(int)}
7770      * , then {@link #logPnoScanStart()} so that the portion of PNO scan before the mobility state
7771      * change can be correctly attributed to the previous mobility state.
7772      */
7773     public void logPnoScanStop() {
7774         synchronized (mLock) {
7775             if (mCurrentDeviceMobilityStatePnoScanStartMs < 0) {
7776                 Log.e(TAG, "Called WifiMetrics#logPNoScanStop() without calling "
7777                         + "WifiMetrics#logPnoScanStart() first!");
7778                 return;
7779             }
7780             DeviceMobilityStatePnoScanStats stats =
7781                     getOrCreateDeviceMobilityStatePnoScanStats(mCurrentDeviceMobilityState);
7782             long now = mClock.getElapsedSinceBootMillis();
7783             stats.pnoDurationMs += now - mCurrentDeviceMobilityStatePnoScanStartMs;
7784             mCurrentDeviceMobilityStatePnoScanStartMs = -1;
7785             updateCurrentMobilityStateTotalDuration(now);
7786         }
7787     }
7788 
7789     /**
7790      * Logs that wifi bug report is taken
7791      */
7792     public void logBugReport() {
7793         synchronized (mLock) {
7794             for (ConnectionEvent connectionEvent : mCurrentConnectionEventPerIface.values()) {
7795                 if (connectionEvent != null) {
7796                     connectionEvent.mConnectionEvent.automaticBugReportTaken = true;
7797                 }
7798             }
7799         }
7800     }
7801 
7802     /**
7803      * Add a new listener for Wi-Fi usability stats handling.
7804      */
7805     public void addOnWifiUsabilityListener(@NonNull IOnWifiUsabilityStatsListener listener) {
7806         if (!mOnWifiUsabilityListeners.register(listener)) {
7807             Log.e(TAG, "Failed to add listener");
7808             return;
7809         }
7810         if (DBG) {
7811             Log.v(TAG, "Adding listener. Num listeners: "
7812                     + mOnWifiUsabilityListeners.getRegisteredCallbackCount());
7813         }
7814     }
7815 
7816     /**
7817      * Remove an existing listener for Wi-Fi usability stats handling.
7818      */
7819     public void removeOnWifiUsabilityListener(@NonNull IOnWifiUsabilityStatsListener listener) {
7820         mOnWifiUsabilityListeners.unregister(listener);
7821         if (DBG) {
7822             Log.v(TAG, "Removing listener. Num listeners: "
7823                     + mOnWifiUsabilityListeners.getRegisteredCallbackCount());
7824         }
7825     }
7826 
7827     /**
7828      * Updates the Wi-Fi usability score and increments occurence of a particular Wifi usability
7829      * score passed in from outside framework. Scores are bounded within
7830      * [MIN_WIFI_USABILITY_SCORE, MAX_WIFI_USABILITY_SCORE].
7831      *
7832      * Also records events when the Wifi usability score breaches significant thresholds.
7833      *
7834      * @param seqNum Sequence number of the Wi-Fi usability score.
7835      * @param score The Wi-Fi usability score.
7836      * @param predictionHorizonSec Prediction horizon of the Wi-Fi usability score.
7837      */
7838     public void incrementWifiUsabilityScoreCount(String ifaceName, int seqNum, int score,
7839             int predictionHorizonSec) {
7840         if (score < MIN_WIFI_USABILITY_SCORE || score > MAX_WIFI_USABILITY_SCORE) {
7841             return;
7842         }
7843         synchronized (mLock) {
7844             mSeqNumToFramework = seqNum;
7845             mLastWifiUsabilityScore = score;
7846             mLastWifiUsabilityScoreNoReset = score;
7847             mWifiUsabilityScoreCounts.put(score, mWifiUsabilityScoreCounts.get(score) + 1);
7848             mLastPredictionHorizonSec = predictionHorizonSec;
7849             mLastPredictionHorizonSecNoReset = predictionHorizonSec;
7850 
7851             boolean wifiWins = mWifiWinsUsabilityScore;
7852             if (score > LOW_WIFI_USABILITY_SCORE) {
7853                 wifiWins = true;
7854             } else if (score < LOW_WIFI_USABILITY_SCORE) {
7855                 wifiWins = false;
7856             }
7857 
7858             if (wifiWins != mWifiWinsUsabilityScore) {
7859                 mWifiWinsUsabilityScore = wifiWins;
7860                 StaEvent event = new StaEvent();
7861                 event.type = StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH;
7862                 addStaEvent(ifaceName, event);
7863                 // Only record the first score breach by checking whether mScoreBreachLowTimeMillis
7864                 // has been set to -1
7865                 if (!wifiWins && mScoreBreachLowTimeMillis == -1) {
7866                     mScoreBreachLowTimeMillis = mClock.getElapsedSinceBootMillis();
7867                 }
7868             }
7869         }
7870     }
7871 
7872     /**
7873      * Reports stats for a successful link probe.
7874      *
7875      * @param timeSinceLastTxSuccessMs At {@code startTimestampMs}, the number of milliseconds since
7876      *                                 the last Tx success (according to
7877      *                                 {@link WifiInfo#txSuccess}).
7878      * @param rssi The Rx RSSI at {@code startTimestampMs}.
7879      * @param linkSpeed The Tx link speed in Mbps at {@code startTimestampMs}.
7880      * @param elapsedTimeMs The number of milliseconds between when the command to transmit the
7881      *                      probe was sent to the driver and when the driver responded that the
7882      *                      probe was ACKed. Note: this number should be correlated with the number
7883      *                      of retries that the driver attempted before the probe was ACKed.
7884      */
7885     public void logLinkProbeSuccess(String ifaceName, long timeSinceLastTxSuccessMs,
7886             int rssi, int linkSpeed, int elapsedTimeMs) {
7887         synchronized (mLock) {
7888             mProbeStatusSinceLastUpdate =
7889                     android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS;
7890             mProbeElapsedTimeSinceLastUpdateMs = elapsedTimeMs;
7891 
7892             mLinkProbeSuccessSecondsSinceLastTxSuccessHistogram.increment(
7893                     (int) (timeSinceLastTxSuccessMs / 1000));
7894             mLinkProbeSuccessRssiCounts.increment(rssi);
7895             mLinkProbeSuccessLinkSpeedCounts.increment(linkSpeed);
7896             mLinkProbeSuccessElapsedTimeMsHistogram.increment(elapsedTimeMs);
7897 
7898             if (mLinkProbeStaEventCount < MAX_LINK_PROBE_STA_EVENTS) {
7899                 StaEvent event = new StaEvent();
7900                 event.type = StaEvent.TYPE_LINK_PROBE;
7901                 event.linkProbeWasSuccess = true;
7902                 event.linkProbeSuccessElapsedTimeMs = elapsedTimeMs;
7903                 addStaEvent(ifaceName, event);
7904             }
7905             mLinkProbeStaEventCount++;
7906         }
7907     }
7908 
7909     /**
7910      * Reports stats for an unsuccessful link probe.
7911      *
7912      * @param timeSinceLastTxSuccessMs At {@code startTimestampMs}, the number of milliseconds since
7913      *                                 the last Tx success (according to
7914      *                                 {@link WifiInfo#txSuccess}).
7915      * @param rssi The Rx RSSI at {@code startTimestampMs}.
7916      * @param linkSpeed The Tx link speed in Mbps at {@code startTimestampMs}.
7917      * @param reason The error code for the failure. See
7918      * {@link WifiNl80211Manager.SendMgmtFrameError}.
7919      */
7920     public void logLinkProbeFailure(String ifaceName, long timeSinceLastTxSuccessMs,
7921             int rssi, int linkSpeed, int reason) {
7922         synchronized (mLock) {
7923             mProbeStatusSinceLastUpdate =
7924                     android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE;
7925             mProbeElapsedTimeSinceLastUpdateMs = Integer.MAX_VALUE;
7926 
7927             mLinkProbeFailureSecondsSinceLastTxSuccessHistogram.increment(
7928                     (int) (timeSinceLastTxSuccessMs / 1000));
7929             mLinkProbeFailureRssiCounts.increment(rssi);
7930             mLinkProbeFailureLinkSpeedCounts.increment(linkSpeed);
7931             mLinkProbeFailureReasonCounts.increment(reason);
7932 
7933             if (mLinkProbeStaEventCount < MAX_LINK_PROBE_STA_EVENTS) {
7934                 StaEvent event = new StaEvent();
7935                 event.type = StaEvent.TYPE_LINK_PROBE;
7936                 event.linkProbeWasSuccess = false;
7937                 event.linkProbeFailureReason = linkProbeFailureReasonToProto(reason);
7938                 addStaEvent(ifaceName, event);
7939             }
7940             mLinkProbeStaEventCount++;
7941         }
7942     }
7943 
7944     /**
7945      * Increments the number of probes triggered by the experiment `experimentId`.
7946      */
7947     public void incrementLinkProbeExperimentProbeCount(String experimentId) {
7948         synchronized (mLock) {
7949             mLinkProbeExperimentProbeCounts.increment(experimentId);
7950         }
7951     }
7952 
7953     /**
7954      * Update wifi config store read duration.
7955      *
7956      * @param timeMs Time it took to complete the operation, in milliseconds
7957      */
7958     public void noteWifiConfigStoreReadDuration(int timeMs) {
7959         synchronized (mLock) {
7960             MetricsUtils.addValueToLinearHistogram(timeMs, mWifiConfigStoreReadDurationHistogram,
7961                     WIFI_CONFIG_STORE_IO_DURATION_BUCKET_RANGES_MS);
7962         }
7963     }
7964 
7965     /**
7966      * Update wifi config store write duration.
7967      *
7968      * @param timeMs Time it took to complete the operation, in milliseconds
7969      */
7970     public void noteWifiConfigStoreWriteDuration(int timeMs) {
7971         synchronized (mLock) {
7972             MetricsUtils.addValueToLinearHistogram(timeMs, mWifiConfigStoreWriteDurationHistogram,
7973                     WIFI_CONFIG_STORE_IO_DURATION_BUCKET_RANGES_MS);
7974         }
7975     }
7976 
7977     /**
7978      * Logs the decision of a network selection algorithm when compared against another network
7979      * selection algorithm.
7980      *
7981      * @param experiment1Id ID of one experiment
7982      * @param experiment2Id ID of the other experiment
7983      * @param isSameDecision did the 2 experiments make the same decision?
7984      * @param numNetworkChoices the number of non-null network choices there were, where the null
7985      *                          choice is not selecting any network
7986      */
7987     public void logNetworkSelectionDecision(int experiment1Id, int experiment2Id,
7988             boolean isSameDecision, int numNetworkChoices) {
7989         if (numNetworkChoices < 0) {
7990             Log.e(TAG, "numNetworkChoices cannot be negative!");
7991             return;
7992         }
7993         if (experiment1Id == experiment2Id) {
7994             Log.e(TAG, "comparing the same experiment id: " + experiment1Id);
7995             return;
7996         }
7997 
7998         Pair<Integer, Integer> key = new Pair<>(experiment1Id, experiment2Id);
7999         synchronized (mLock) {
8000             NetworkSelectionExperimentResults results =
8001                     mNetworkSelectionExperimentPairNumChoicesCounts
8002                             .computeIfAbsent(key, k -> new NetworkSelectionExperimentResults());
8003 
8004             IntCounter counter = isSameDecision
8005                     ? results.sameSelectionNumChoicesCounter
8006                     : results.differentSelectionNumChoicesCounter;
8007 
8008             counter.increment(numNetworkChoices);
8009         }
8010     }
8011 
8012     /** Increment number of network request API usage stats */
8013     public void incrementNetworkRequestApiNumRequest() {
8014         synchronized (mLock) {
8015             mWifiNetworkRequestApiLog.numRequest++;
8016         }
8017     }
8018 
8019     /** Add to the network request API match size histogram */
8020     public void incrementNetworkRequestApiMatchSizeHistogram(int matchSize) {
8021         synchronized (mLock) {
8022             mWifiNetworkRequestApiMatchSizeHistogram.increment(matchSize);
8023         }
8024     }
8025 
8026     /** Increment number of connection success on primary iface via network request API */
8027     public void incrementNetworkRequestApiNumConnectSuccessOnPrimaryIface() {
8028         synchronized (mLock) {
8029             mWifiNetworkRequestApiLog.numConnectSuccessOnPrimaryIface++;
8030         }
8031     }
8032 
8033     /** Increment number of requests that bypassed user approval via network request API */
8034     public void incrementNetworkRequestApiNumUserApprovalBypass() {
8035         synchronized (mLock) {
8036             mWifiNetworkRequestApiLog.numUserApprovalBypass++;
8037         }
8038     }
8039 
8040     /** Increment number of requests that user rejected via network request API */
8041     public void incrementNetworkRequestApiNumUserReject() {
8042         synchronized (mLock) {
8043             mWifiNetworkRequestApiLog.numUserReject++;
8044         }
8045     }
8046 
8047     /** Increment number of requests from unique apps via network request API */
8048     public void incrementNetworkRequestApiNumApps() {
8049         synchronized (mLock) {
8050             mWifiNetworkRequestApiLog.numApps++;
8051         }
8052     }
8053 
8054     /** Add to the network request API connection duration histogram */
8055     public void incrementNetworkRequestApiConnectionDurationSecOnPrimaryIfaceHistogram(
8056             int durationSec) {
8057         synchronized (mLock) {
8058             mWifiNetworkRequestApiConnectionDurationSecOnPrimaryIfaceHistogram.increment(
8059                     durationSec);
8060         }
8061     }
8062 
8063     /** Add to the network request API connection duration on secondary iface histogram */
8064     public void incrementNetworkRequestApiConnectionDurationSecOnSecondaryIfaceHistogram(
8065             int durationSec) {
8066         synchronized (mLock) {
8067             mWifiNetworkRequestApiConnectionDurationSecOnSecondaryIfaceHistogram.increment(
8068                     durationSec);
8069         }
8070     }
8071 
8072     /** Increment number of connection on primary iface via network request API */
8073     public void incrementNetworkRequestApiNumConnectOnPrimaryIface() {
8074         synchronized (mLock) {
8075             mWifiNetworkRequestApiLog.numConnectOnPrimaryIface++;
8076         }
8077     }
8078 
8079     /** Increment number of connection on secondary iface via network request API */
8080     public void incrementNetworkRequestApiNumConnectOnSecondaryIface() {
8081         synchronized (mLock) {
8082             mWifiNetworkRequestApiLog.numConnectOnSecondaryIface++;
8083         }
8084     }
8085 
8086     /** Increment number of connection success on secondary iface via network request API */
8087     public void incrementNetworkRequestApiNumConnectSuccessOnSecondaryIface() {
8088         synchronized (mLock) {
8089             mWifiNetworkRequestApiLog.numConnectSuccessOnSecondaryIface++;
8090         }
8091     }
8092 
8093     /** Increment number of concurrent connection via network request API */
8094     public void incrementNetworkRequestApiNumConcurrentConnection() {
8095         synchronized (mLock) {
8096             mWifiNetworkRequestApiLog.numConcurrentConnection++;
8097         }
8098     }
8099 
8100     /** Add to the network request API concurrent connection duration histogram */
8101     public void incrementNetworkRequestApiConcurrentConnectionDurationSecHistogram(
8102             int durationSec) {
8103         synchronized (mLock) {
8104             mWifiNetworkRequestApiConcurrentConnectionDurationSecHistogram.increment(
8105                     durationSec);
8106         }
8107     }
8108 
8109     /** Increment number of network suggestion API modification by app stats */
8110     public void incrementNetworkSuggestionApiNumModification() {
8111         synchronized (mLock) {
8112             mWifiNetworkSuggestionApiLog.numModification++;
8113         }
8114     }
8115 
8116     /** Increment number of connection success via network suggestion API */
8117     public void incrementNetworkSuggestionApiNumConnectSuccess() {
8118         synchronized (mLock) {
8119             mWifiNetworkSuggestionApiLog.numConnectSuccess++;
8120         }
8121     }
8122 
8123     /** Increment number of connection failure via network suggestion API */
8124     public void incrementNetworkSuggestionApiNumConnectFailure() {
8125         synchronized (mLock) {
8126             mWifiNetworkSuggestionApiLog.numConnectFailure++;
8127         }
8128     }
8129 
8130     /** Increment number of user revoke suggestion permission. Including from settings or
8131      * disallowed from UI.
8132      */
8133     public void incrementNetworkSuggestionUserRevokePermission() {
8134         synchronized (mLock) {
8135             mWifiNetworkSuggestionApiLog.userRevokeAppSuggestionPermission++;
8136         }
8137     }
8138 
8139     /**
8140      * Increment number of times a ScanResult matches more than one WifiNetworkSuggestion.
8141      */
8142     public void incrementNetworkSuggestionMoreThanOneSuggestionForSingleScanResult() {
8143         synchronized (mLock) {
8144             mWifiNetworkSuggestionApiLog.numMultipleSuggestions++;
8145         }
8146     }
8147 
8148     /**
8149      * Add a saved network which has at least has one suggestion for same network on the device.
8150      */
8151     public void addSuggestionExistsForSavedNetwork(String key) {
8152         synchronized (mLock) {
8153             mWifiNetworkSuggestionCoexistSavedNetworks.add(key);
8154         }
8155     }
8156 
8157     /**
8158      * Add a priority group which is using on the device.(Except default priority group).
8159      */
8160     public void addNetworkSuggestionPriorityGroup(int priorityGroup) {
8161         synchronized (mLock) {
8162             // Ignore the default group
8163             if (priorityGroup == 0) {
8164                 return;
8165             }
8166             mWifiNetworkSuggestionPriorityGroups.put(priorityGroup, true);
8167         }
8168 
8169     }
8170 
8171     /** Clear and set the latest network suggestion API max list size histogram */
8172     public void noteNetworkSuggestionApiListSizeHistogram(List<Integer> listSizes) {
8173         synchronized (mLock) {
8174             mWifiNetworkSuggestionApiListSizeHistogram.clear();
8175             for (Integer listSize : listSizes) {
8176                 mWifiNetworkSuggestionApiListSizeHistogram.increment(listSize);
8177             }
8178         }
8179     }
8180 
8181     /** Increment number of app add suggestion with different privilege */
8182     public void incrementNetworkSuggestionApiUsageNumOfAppInType(int appType) {
8183         int typeCode;
8184         synchronized (mLock) {
8185             switch (appType) {
8186                 case WifiNetworkSuggestionsManager.APP_TYPE_CARRIER_PRIVILEGED:
8187                     typeCode = WifiNetworkSuggestionApiLog.TYPE_CARRIER_PRIVILEGED;
8188                     break;
8189                 case WifiNetworkSuggestionsManager.APP_TYPE_NETWORK_PROVISIONING:
8190                     typeCode = WifiNetworkSuggestionApiLog.TYPE_NETWORK_PROVISIONING;
8191                     break;
8192                 case WifiNetworkSuggestionsManager.APP_TYPE_NON_PRIVILEGED:
8193                     typeCode = WifiNetworkSuggestionApiLog.TYPE_NON_PRIVILEGED;
8194                     break;
8195                 default:
8196                     typeCode = WifiNetworkSuggestionApiLog.TYPE_UNKNOWN;
8197             }
8198             mWifiNetworkSuggestionApiAppTypeCounter.increment(typeCode);
8199         }
8200     }
8201 
8202     /** Add user action to the approval suggestion app UI */
8203     public void addUserApprovalSuggestionAppUiReaction(@WifiNetworkSuggestionsManager.UserActionCode
8204             int actionType, boolean isDialog) {
8205         int actionCode;
8206         switch (actionType) {
8207             case WifiNetworkSuggestionsManager.ACTION_USER_ALLOWED_APP:
8208                 actionCode = UserReactionToApprovalUiEvent.ACTION_ALLOWED;
8209                 break;
8210             case WifiNetworkSuggestionsManager.ACTION_USER_DISALLOWED_APP:
8211                 actionCode = UserReactionToApprovalUiEvent.ACTION_DISALLOWED;
8212                 break;
8213             case WifiNetworkSuggestionsManager.ACTION_USER_DISMISS:
8214                 actionCode = UserReactionToApprovalUiEvent.ACTION_DISMISS;
8215                 break;
8216             default:
8217                 actionCode = UserReactionToApprovalUiEvent.ACTION_UNKNOWN;
8218         }
8219         UserReaction event = new UserReaction();
8220         event.userAction = actionCode;
8221         event.isDialog = isDialog;
8222         synchronized (mLock) {
8223             mUserApprovalSuggestionAppUiReactionList.add(event);
8224         }
8225     }
8226 
8227     /** Add user action to the approval Carrier Imsi protection exemption UI */
8228     public void addUserApprovalCarrierUiReaction(@WifiCarrierInfoManager.UserActionCode
8229             int actionType, boolean isDialog) {
8230         int actionCode;
8231         switch (actionType) {
8232             case WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER:
8233                 actionCode = UserReactionToApprovalUiEvent.ACTION_ALLOWED;
8234                 break;
8235             case WifiCarrierInfoManager.ACTION_USER_DISALLOWED_CARRIER:
8236                 actionCode = UserReactionToApprovalUiEvent.ACTION_DISALLOWED;
8237                 break;
8238             case WifiCarrierInfoManager.ACTION_USER_DISMISS:
8239                 actionCode = UserReactionToApprovalUiEvent.ACTION_DISMISS;
8240                 break;
8241             default:
8242                 actionCode = UserReactionToApprovalUiEvent.ACTION_UNKNOWN;
8243         }
8244         UserReaction event = new UserReaction();
8245         event.userAction = actionCode;
8246         event.isDialog = isDialog;
8247 
8248         synchronized (mLock) {
8249             mUserApprovalCarrierUiReactionList.add(event);
8250         }
8251     }
8252 
8253     /**
8254      * Sets the nominator for a network (i.e. which entity made the suggestion to connect)
8255      * @param networkId the ID of the network, from its {@link WifiConfiguration}
8256      * @param nominatorId the entity that made the suggestion to connect to this network,
8257      *                    from {@link WifiMetricsProto.ConnectionEvent.ConnectionNominator}
8258      */
8259     public void setNominatorForNetwork(int networkId, int nominatorId) {
8260         synchronized (mLock) {
8261             if (networkId == WifiConfiguration.INVALID_NETWORK_ID) return;
8262             mNetworkIdToNominatorId.put(networkId, nominatorId);
8263 
8264             // user connect choice is preventing switching off from the connected network
8265             if (nominatorId
8266                     == WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED_USER_CONNECT_CHOICE
8267                     && mWifiStatusBuilder.getNetworkId() == networkId) {
8268                 mWifiStatusBuilder.setUserChoice(true);
8269             }
8270         }
8271     }
8272 
8273     /**
8274      * Sets the numeric CandidateScorer id.
8275      */
8276     public void setNetworkSelectorExperimentId(int expId) {
8277         synchronized (mLock) {
8278             mNetworkSelectorExperimentId = expId;
8279         }
8280     }
8281 
8282     /** Add a WifiLock acquisition session */
8283     public void addWifiLockAcqSession(int lockType, int[] attrUids, String[] attrTags,
8284             int callerType, long duration, boolean isPowersaveDisableAllowed,
8285             boolean isAppExemptedFromScreenOn, boolean isAppExemptedFromForeground) {
8286         int lockMode;
8287         switch (lockType) {
8288             case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
8289                 mWifiLockHighPerfAcqDurationSecHistogram.increment((int) (duration / 1000));
8290                 lockMode = WifiStatsLog.WIFI_LOCK_RELEASED__MODE__WIFI_MODE_FULL_HIGH_PERF;
8291                 break;
8292 
8293             case WifiManager.WIFI_MODE_FULL_LOW_LATENCY:
8294                 mWifiLockLowLatencyAcqDurationSecHistogram.increment((int) (duration / 1000));
8295                 lockMode = WifiStatsLog.WIFI_LOCK_RELEASED__MODE__WIFI_MODE_FULL_LOW_LATENCY;
8296                 break;
8297             default:
8298                 Log.e(TAG, "addWifiLockAcqSession: Invalid lock type: " + lockType);
8299                 return;
8300         }
8301         WifiStatsLog.write(WifiStatsLog.WIFI_LOCK_RELEASED,
8302                 attrUids,
8303                 attrTags,
8304                 callerType,
8305                 lockMode,
8306                 duration,
8307                 isPowersaveDisableAllowed,
8308                 isAppExemptedFromScreenOn,
8309                 isAppExemptedFromForeground);
8310     }
8311 
8312     /** Add a WifiLock active session */
8313     public void addWifiLockActiveSession(int lockType, int[] attrUids, String[] attrTags,
8314             long duration, boolean isPowersaveDisableAllowed,
8315             boolean isAppExemptedFromScreenOn, boolean isAppExemptedFromForeground) {
8316         int lockMode;
8317         switch (lockType) {
8318             case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
8319                 lockMode = WifiStatsLog.WIFI_LOCK_DEACTIVATED__MODE__WIFI_MODE_FULL_HIGH_PERF;
8320                 mWifiLockStats.highPerfActiveTimeMs += duration;
8321                 mWifiLockHighPerfActiveSessionDurationSecHistogram.increment(
8322                         (int) (duration / 1000));
8323                 break;
8324 
8325             case WifiManager.WIFI_MODE_FULL_LOW_LATENCY:
8326                 lockMode = WifiStatsLog.WIFI_LOCK_DEACTIVATED__MODE__WIFI_MODE_FULL_LOW_LATENCY;
8327                 mWifiLockStats.lowLatencyActiveTimeMs += duration;
8328                 mWifiLockLowLatencyActiveSessionDurationSecHistogram.increment(
8329                         (int) (duration / 1000));
8330                 break;
8331 
8332             default:
8333                 Log.e(TAG, "addWifiLockActiveSession: Invalid lock type: " + lockType);
8334                 return;
8335         }
8336         WifiStatsLog.write(WifiStatsLog.WIFI_LOCK_DEACTIVATED,
8337                 attrUids,
8338                 attrTags,
8339                 lockMode,
8340                 duration,
8341                 isPowersaveDisableAllowed,
8342                 isAppExemptedFromScreenOn,
8343                 isAppExemptedFromForeground);
8344     }
8345 
8346     /** Increments metrics counting number of addOrUpdateNetwork calls. **/
8347     public void incrementNumAddOrUpdateNetworkCalls() {
8348         synchronized (mLock) {
8349             mWifiLogProto.numAddOrUpdateNetworkCalls++;
8350         }
8351     }
8352 
8353     /** Increments metrics counting number of enableNetwork calls. **/
8354     public void incrementNumEnableNetworkCalls() {
8355         synchronized (mLock) {
8356             mWifiLogProto.numEnableNetworkCalls++;
8357         }
8358     }
8359 
8360     /** Add to WifiToggleStats **/
8361     public void incrementNumWifiToggles(boolean isPrivileged, boolean enable) {
8362         synchronized (mLock) {
8363             if (isPrivileged && enable) {
8364                 mWifiToggleStats.numToggleOnPrivileged++;
8365             } else if (isPrivileged && !enable) {
8366                 mWifiToggleStats.numToggleOffPrivileged++;
8367             } else if (!isPrivileged && enable) {
8368                 mWifiToggleStats.numToggleOnNormal++;
8369             } else {
8370                 mWifiToggleStats.numToggleOffNormal++;
8371             }
8372         }
8373     }
8374 
8375     /**
8376      * Increment number of passpoint provision failure
8377      * @param failureCode indicates error condition
8378      */
8379     public void incrementPasspointProvisionFailure(@OsuFailure int failureCode) {
8380         int provisionFailureCode;
8381         synchronized (mLock) {
8382             switch (failureCode) {
8383                 case ProvisioningCallback.OSU_FAILURE_AP_CONNECTION:
8384                     provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_AP_CONNECTION;
8385                     break;
8386                 case ProvisioningCallback.OSU_FAILURE_SERVER_URL_INVALID:
8387                     provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_SERVER_URL_INVALID;
8388                     break;
8389                 case ProvisioningCallback.OSU_FAILURE_SERVER_CONNECTION:
8390                     provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_SERVER_CONNECTION;
8391                     break;
8392                 case ProvisioningCallback.OSU_FAILURE_SERVER_VALIDATION:
8393                     provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_SERVER_VALIDATION;
8394                     break;
8395                 case ProvisioningCallback.OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION:
8396                     provisionFailureCode = PasspointProvisionStats
8397                             .OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION;
8398                     break;
8399                 case ProvisioningCallback.OSU_FAILURE_PROVISIONING_ABORTED:
8400                     provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_PROVISIONING_ABORTED;
8401                     break;
8402                 case ProvisioningCallback.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE:
8403                     provisionFailureCode = PasspointProvisionStats
8404                             .OSU_FAILURE_PROVISIONING_NOT_AVAILABLE;
8405                     break;
8406                 case ProvisioningCallback.OSU_FAILURE_INVALID_URL_FORMAT_FOR_OSU:
8407                     provisionFailureCode = PasspointProvisionStats
8408                             .OSU_FAILURE_INVALID_URL_FORMAT_FOR_OSU;
8409                     break;
8410                 case ProvisioningCallback.OSU_FAILURE_UNEXPECTED_COMMAND_TYPE:
8411                     provisionFailureCode = PasspointProvisionStats
8412                             .OSU_FAILURE_UNEXPECTED_COMMAND_TYPE;
8413                     break;
8414                 case ProvisioningCallback.OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE:
8415                     provisionFailureCode = PasspointProvisionStats
8416                             .OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE;
8417                     break;
8418                 case ProvisioningCallback.OSU_FAILURE_SOAP_MESSAGE_EXCHANGE:
8419                     provisionFailureCode = PasspointProvisionStats
8420                             .OSU_FAILURE_SOAP_MESSAGE_EXCHANGE;
8421                     break;
8422                 case ProvisioningCallback.OSU_FAILURE_START_REDIRECT_LISTENER:
8423                     provisionFailureCode = PasspointProvisionStats
8424                             .OSU_FAILURE_START_REDIRECT_LISTENER;
8425                     break;
8426                 case ProvisioningCallback.OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER:
8427                     provisionFailureCode = PasspointProvisionStats
8428                             .OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER;
8429                     break;
8430                 case ProvisioningCallback.OSU_FAILURE_NO_OSU_ACTIVITY_FOUND:
8431                     provisionFailureCode = PasspointProvisionStats
8432                             .OSU_FAILURE_NO_OSU_ACTIVITY_FOUND;
8433                     break;
8434                 case ProvisioningCallback.OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS:
8435                     provisionFailureCode = PasspointProvisionStats
8436                             .OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS;
8437                     break;
8438                 case ProvisioningCallback.OSU_FAILURE_NO_PPS_MO:
8439                     provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_NO_PPS_MO;
8440                     break;
8441                 case ProvisioningCallback.OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE:
8442                     provisionFailureCode = PasspointProvisionStats
8443                             .OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE;
8444                     break;
8445                 case ProvisioningCallback.OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE:
8446                     provisionFailureCode = PasspointProvisionStats
8447                             .OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE;
8448                     break;
8449                 case ProvisioningCallback.OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE:
8450                     provisionFailureCode = PasspointProvisionStats
8451                             .OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE;
8452                     break;
8453                 case ProvisioningCallback.OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES:
8454                     provisionFailureCode = PasspointProvisionStats
8455                             .OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES;
8456                     break;
8457                 case ProvisioningCallback.OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE:
8458                     provisionFailureCode = PasspointProvisionStats
8459                             .OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE;
8460                     break;
8461                 case ProvisioningCallback.OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION:
8462                     provisionFailureCode = PasspointProvisionStats
8463                             .OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION;
8464                     break;
8465                 case ProvisioningCallback.OSU_FAILURE_OSU_PROVIDER_NOT_FOUND:
8466                     provisionFailureCode = PasspointProvisionStats
8467                             .OSU_FAILURE_OSU_PROVIDER_NOT_FOUND;
8468                     break;
8469                 default:
8470                     provisionFailureCode = PasspointProvisionStats.OSU_FAILURE_UNKNOWN;
8471             }
8472             mPasspointProvisionFailureCounts.increment(provisionFailureCode);
8473         }
8474     }
8475 
8476     /**
8477      * Add to the histogram of number of BSSIDs filtered out from network selection.
8478      */
8479     public void incrementNetworkSelectionFilteredBssidCount(int numBssid) {
8480         mBssidBlocklistStats.networkSelectionFilteredBssidCount.increment(numBssid);
8481     }
8482 
8483     /**
8484      * Increment the number of network connections skipped due to the high movement feature.
8485      */
8486     public void incrementNumHighMovementConnectionSkipped() {
8487         mBssidBlocklistStats.numHighMovementConnectionSkipped++;
8488     }
8489 
8490     /**
8491      * Increment the number of network connections initiated while under the high movement
8492      * feature.
8493      */
8494     public void incrementNumHighMovementConnectionStarted() {
8495         mBssidBlocklistStats.numHighMovementConnectionStarted++;
8496     }
8497 
8498     /**
8499      * Increment the number of times BSSIDs are blocked per reason.
8500      * @param blockReason one of {@link WifiBlocklistMonitor.FailureReason}
8501      */
8502     public void incrementBssidBlocklistCount(int blockReason) {
8503         mBssidBlocklistStats.incrementBssidBlocklistCount(blockReason);
8504     }
8505 
8506     /**
8507      * Increment the number of times WifiConfigurations are blocked per reason.
8508      * @param blockReason one of {@Link NetworkSelectionStatus.NetworkSelectionDisableReason}
8509      */
8510     public void incrementWificonfigurationBlocklistCount(int blockReason) {
8511         mBssidBlocklistStats.incrementWificonfigurationBlocklistCount(blockReason);
8512     }
8513 
8514     /**
8515      * Increment number of passpoint provision success
8516      */
8517     public void incrementPasspointProvisionSuccess() {
8518         synchronized (mLock) {
8519             mNumProvisionSuccess++;
8520         }
8521     }
8522 
8523     /**
8524      * Increment number of IP renewal failures.
8525      */
8526     public void incrementIpRenewalFailure() {
8527         synchronized (mLock) {
8528             mWifiLogProto.numIpRenewalFailure++;
8529         }
8530     }
8531 
8532     /**
8533      * Sets the duration for evaluating Wifi condition to trigger a data stall
8534      */
8535     public void setDataStallDurationMs(int duration) {
8536         synchronized (mLock) {
8537             mExperimentValues.dataStallDurationMs = duration;
8538         }
8539     }
8540 
8541     /**
8542      * Sets the threshold of Tx throughput below which to trigger a data stall
8543      */
8544     public void setDataStallTxTputThrKbps(int txTputThr) {
8545         synchronized (mLock) {
8546             mExperimentValues.dataStallTxTputThrKbps = txTputThr;
8547         }
8548     }
8549 
8550     /**
8551      * Sets the threshold of Rx throughput below which to trigger a data stall
8552      */
8553     public void setDataStallRxTputThrKbps(int rxTputThr) {
8554         synchronized (mLock) {
8555             mExperimentValues.dataStallRxTputThrKbps = rxTputThr;
8556         }
8557     }
8558 
8559     /**
8560      * Sets the threshold of Tx packet error rate above which to trigger a data stall
8561      */
8562     public void setDataStallTxPerThr(int txPerThr) {
8563         synchronized (mLock) {
8564             mExperimentValues.dataStallTxPerThr = txPerThr;
8565         }
8566     }
8567 
8568     /**
8569      * Sets the threshold of CCA level above which to trigger a data stall
8570      */
8571     public void setDataStallCcaLevelThr(int ccaLevel) {
8572         synchronized (mLock) {
8573             mExperimentValues.dataStallCcaLevelThr = ccaLevel;
8574         }
8575     }
8576 
8577     /**
8578      * Sets health monitor RSSI poll valid time in ms
8579      */
8580     public void setHealthMonitorRssiPollValidTimeMs(int rssiPollValidTimeMs) {
8581         synchronized (mLock) {
8582             mExperimentValues.healthMonitorRssiPollValidTimeMs = rssiPollValidTimeMs;
8583         }
8584     }
8585 
8586     /**
8587      * Increment connection duration while link layer stats report are on
8588      */
8589     public void incrementConnectionDuration(String ifaceName, int timeDeltaLastTwoPollsMs,
8590             boolean isThroughputSufficient, boolean isCellularDataAvailable, int rssi, int txKbps,
8591             int rxKbps) {
8592         synchronized (mLock) {
8593             if (!isPrimary(ifaceName)) {
8594                 return;
8595             }
8596             mConnectionDurationStats.incrementDurationCount(timeDeltaLastTwoPollsMs,
8597                     isThroughputSufficient, isCellularDataAvailable, mWifiWins);
8598             WifiUsabilityState wifiUsabilityState = mWifiUsabilityStatePerIface.getOrDefault(
8599                     ifaceName, WifiUsabilityState.UNKNOWN);
8600             int band = KnownBandsChannelHelper.getBand(mLastPollFreq);
8601             WifiStatsLog.write(WifiStatsLog.WIFI_HEALTH_STAT_REPORTED, timeDeltaLastTwoPollsMs,
8602                     isThroughputSufficient || !mWifiWins, isCellularDataAvailable, band, rssi,
8603                     txKbps, rxKbps, mScorerUid, (wifiUsabilityState == WifiUsabilityState.USABLE),
8604                     convertWifiUsabilityState(wifiUsabilityState));
8605         }
8606     }
8607 
8608     /**
8609      * Sets the status to indicate whether external WiFi connected network scorer is present or not.
8610      */
8611     public void setIsExternalWifiScorerOn(boolean value, int callerUid) {
8612         synchronized (mLock) {
8613             mWifiLogProto.isExternalWifiScorerOn = value;
8614             mScorerUid = callerUid;
8615         }
8616     }
8617 
8618     /**
8619      * Note Wi-Fi off metrics
8620      */
8621     public void noteWifiOff(boolean isDeferred, boolean isTimeout, int duration) {
8622         synchronized (mLock) {
8623             mWifiOffMetrics.numWifiOff++;
8624             if (isDeferred) {
8625                 mWifiOffMetrics.numWifiOffDeferring++;
8626                 if (isTimeout) {
8627                     mWifiOffMetrics.numWifiOffDeferringTimeout++;
8628                 }
8629                 mWifiOffMetrics.wifiOffDeferringTimeHistogram.increment(duration);
8630             }
8631         }
8632     }
8633 
8634     /**
8635      * Increment number of BSSIDs filtered out from network selection due to MBO Association
8636      * disallowed indication.
8637      */
8638     public void incrementNetworkSelectionFilteredBssidCountDueToMboAssocDisallowInd() {
8639         synchronized (mLock) {
8640             mWifiLogProto.numBssidFilteredDueToMboAssocDisallowInd++;
8641         }
8642     }
8643 
8644     /**
8645      * Increment number of times BSS transition management request frame is received from the AP.
8646      */
8647     public void incrementSteeringRequestCount() {
8648         synchronized (mLock) {
8649             mWifiLogProto.numSteeringRequest++;
8650         }
8651     }
8652 
8653     /**
8654      * Increment number of times force scan is triggered due to a
8655      * BSS transition management request frame from AP.
8656      */
8657     public void incrementForceScanCountDueToSteeringRequest() {
8658         synchronized (mLock) {
8659             mWifiLogProto.numForceScanDueToSteeringRequest++;
8660         }
8661     }
8662 
8663     /**
8664      * Increment number of times STA received cellular switch
8665      * request from MBO supported AP.
8666      */
8667     public void incrementMboCellularSwitchRequestCount() {
8668         synchronized (mLock) {
8669             mWifiLogProto.numMboCellularSwitchRequest++;
8670         }
8671     }
8672 
8673     /**
8674      * Increment number of times STA received steering request
8675      * including MBO association retry delay.
8676      */
8677     public void incrementSteeringRequestCountIncludingMboAssocRetryDelay() {
8678         synchronized (mLock) {
8679             mWifiLogProto.numSteeringRequestIncludingMboAssocRetryDelay++;
8680         }
8681     }
8682 
8683     /**
8684      * Increment number of connect request to AP adding FILS AKM.
8685      */
8686     public void incrementConnectRequestWithFilsAkmCount() {
8687         synchronized (mLock) {
8688             mWifiLogProto.numConnectRequestWithFilsAkm++;
8689         }
8690     }
8691 
8692     /**
8693      * Increment number of times STA connected through FILS
8694      * authentication.
8695      */
8696     public void incrementL2ConnectionThroughFilsAuthCount() {
8697         synchronized (mLock) {
8698             mWifiLogProto.numL2ConnectionThroughFilsAuthentication++;
8699         }
8700     }
8701 
8702     /**
8703      * Note SoftapConfig Reset Metrics
8704      */
8705     public void noteSoftApConfigReset(SoftApConfiguration originalConfig,
8706             SoftApConfiguration newConfig) {
8707         synchronized (mLock) {
8708             if (originalConfig.getSecurityType() != newConfig.getSecurityType()) {
8709                 mSoftApConfigLimitationMetrics.numSecurityTypeResetToDefault++;
8710             }
8711             if (originalConfig.getMaxNumberOfClients() != newConfig.getMaxNumberOfClients()) {
8712                 mSoftApConfigLimitationMetrics.numMaxClientSettingResetToDefault++;
8713             }
8714             if (originalConfig.isClientControlByUserEnabled()
8715                     != newConfig.isClientControlByUserEnabled()) {
8716                 mSoftApConfigLimitationMetrics.numClientControlByUserResetToDefault++;
8717             }
8718         }
8719     }
8720 
8721     /**
8722      * Note Softap client blocked due to max client limitation
8723      */
8724     public void noteSoftApClientBlocked(int maxClient) {
8725         mSoftApConfigLimitationMetrics.maxClientSettingWhenReachHistogram.increment(maxClient);
8726     }
8727 
8728     /**
8729      * Increment number of connection with different BSSID between framework and firmware selection.
8730      */
8731     public void incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware() {
8732         synchronized (mLock) {
8733             mWifiLogProto.numBssidDifferentSelectionBetweenFrameworkAndFirmware++;
8734         }
8735     }
8736 
8737     /**
8738      * Note the carrier wifi network connected successfully.
8739      */
8740     public void incrementNumOfCarrierWifiConnectionSuccess() {
8741         synchronized (mLock) {
8742             mCarrierWifiMetrics.numConnectionSuccess++;
8743         }
8744     }
8745 
8746     /**
8747      * Note the carrier wifi network connection authentication failure.
8748      */
8749     public void incrementNumOfCarrierWifiConnectionAuthFailure() {
8750         synchronized (mLock) {
8751             mCarrierWifiMetrics.numConnectionAuthFailure++;
8752         }
8753     }
8754 
8755     /**
8756      * Note the carrier wifi network connection non-authentication failure.
8757      */
8758     public void incrementNumOfCarrierWifiConnectionNonAuthFailure() {
8759         synchronized (mLock) {
8760             mCarrierWifiMetrics.numConnectionNonAuthFailure++;
8761         }
8762     }
8763 
8764     /**
8765      *  Set Adaptive Connectivity state (On/Off)
8766      */
8767     public void setAdaptiveConnectivityState(boolean adaptiveConnectivityEnabled) {
8768         synchronized (mLock) {
8769             mAdaptiveConnectivityEnabled = adaptiveConnectivityEnabled;
8770         }
8771     }
8772 
8773     /**
8774      * Get total beacon receive count
8775      */
8776     public long getTotalBeaconRxCount() {
8777         return mLastTotalBeaconRx;
8778     }
8779 
8780     /** Get total beacon receive count for the link */
8781     public long getTotalBeaconRxCount(int linkId) {
8782         if (!mLastLinkMetrics.contains(linkId)) return 0;
8783         return mLastLinkMetrics.get(linkId).getTotalBeaconRx();
8784     }
8785 
8786     /** Get link usage state */
8787     public @android.net.wifi.WifiUsabilityStatsEntry.LinkState int getLinkUsageState(int linkId) {
8788         if (!mLastLinkMetrics.contains(linkId)) {
8789             return android.net.wifi.WifiUsabilityStatsEntry.LINK_STATE_UNKNOWN;
8790         }
8791         return mLastLinkMetrics.get(linkId).getLinkUsageState();
8792     }
8793 
8794     /** Note whether Wifi was enabled at boot time. */
8795     public void noteWifiEnabledDuringBoot(boolean isWifiEnabled) {
8796         synchronized (mLock) {
8797             if (mIsFirstConnectionAttemptComplete
8798                     || mFirstConnectAfterBootStats == null
8799                     || mFirstConnectAfterBootStats.wifiEnabledAtBoot != null) {
8800                 return;
8801             }
8802             Attempt wifiEnabledAtBoot = new Attempt();
8803             wifiEnabledAtBoot.isSuccess = isWifiEnabled;
8804             wifiEnabledAtBoot.timestampSinceBootMillis = mClock.getElapsedSinceBootMillis();
8805             mFirstConnectAfterBootStats.wifiEnabledAtBoot = wifiEnabledAtBoot;
8806             if (!isWifiEnabled) {
8807                 mIsFirstConnectionAttemptComplete = true;
8808             }
8809         }
8810     }
8811 
8812     /** Note the first network selection after boot. */
8813     public void noteFirstNetworkSelectionAfterBoot(boolean wasAnyCandidatesFound) {
8814         synchronized (mLock) {
8815             if (mIsFirstConnectionAttemptComplete
8816                     || mFirstConnectAfterBootStats == null
8817                     || mFirstConnectAfterBootStats.firstNetworkSelection != null) {
8818                 return;
8819             }
8820             Attempt firstNetworkSelection = new Attempt();
8821             firstNetworkSelection.isSuccess = wasAnyCandidatesFound;
8822             firstNetworkSelection.timestampSinceBootMillis = mClock.getElapsedSinceBootMillis();
8823             mFirstConnectAfterBootStats.firstNetworkSelection = firstNetworkSelection;
8824             if (!wasAnyCandidatesFound) {
8825                 mIsFirstConnectionAttemptComplete = true;
8826             }
8827         }
8828     }
8829 
8830     /** Note the first L2 connection after boot. */
8831     public void noteFirstL2ConnectionAfterBoot(boolean wasConnectionSuccessful) {
8832         synchronized (mLock) {
8833             if (mIsFirstConnectionAttemptComplete
8834                     || mFirstConnectAfterBootStats == null
8835                     || mFirstConnectAfterBootStats.firstL2Connection != null) {
8836                 return;
8837             }
8838             Attempt firstL2Connection = new Attempt();
8839             firstL2Connection.isSuccess = wasConnectionSuccessful;
8840             firstL2Connection.timestampSinceBootMillis = mClock.getElapsedSinceBootMillis();
8841             mFirstConnectAfterBootStats.firstL2Connection = firstL2Connection;
8842             if (!wasConnectionSuccessful) {
8843                 mIsFirstConnectionAttemptComplete = true;
8844             }
8845         }
8846     }
8847 
8848     /** Note the first L3 connection after boot. */
8849     public void noteFirstL3ConnectionAfterBoot(boolean wasConnectionSuccessful) {
8850         synchronized (mLock) {
8851             if (mIsFirstConnectionAttemptComplete
8852                     || mFirstConnectAfterBootStats == null
8853                     || mFirstConnectAfterBootStats.firstL3Connection != null) {
8854                 return;
8855             }
8856             Attempt firstL3Connection = new Attempt();
8857             firstL3Connection.isSuccess = wasConnectionSuccessful;
8858             firstL3Connection.timestampSinceBootMillis = mClock.getElapsedSinceBootMillis();
8859             mFirstConnectAfterBootStats.firstL3Connection = firstL3Connection;
8860             if (!wasConnectionSuccessful) {
8861                 mIsFirstConnectionAttemptComplete = true;
8862             }
8863         }
8864     }
8865 
8866     private static String attemptToString(@Nullable Attempt attempt) {
8867         if (attempt == null) return "Attempt=null";
8868         return "Attempt{"
8869                 + "timestampSinceBootMillis=" + attempt.timestampSinceBootMillis
8870                 + ",isSuccess=" + attempt.isSuccess
8871                 + "}";
8872     }
8873 
8874     private static String firstConnectAfterBootStatsToString(
8875             @Nullable FirstConnectAfterBootStats stats) {
8876         if (stats == null) return "FirstConnectAfterBootStats=null";
8877         return "FirstConnectAfterBootStats{"
8878                 + "wifiEnabledAtBoot=" + attemptToString(stats.wifiEnabledAtBoot)
8879                 + ",firstNetworkSelection" + attemptToString(stats.firstNetworkSelection)
8880                 + ",firstL2Connection" + attemptToString(stats.firstL2Connection)
8881                 + ",firstL3Connection" + attemptToString(stats.firstL3Connection)
8882                 + "}";
8883     }
8884 
8885     public ScanMetrics getScanMetrics() {
8886         return mScanMetrics;
8887     }
8888 
8889     public enum ScanType { SINGLE, BACKGROUND }
8890 
8891     public enum PnoScanState { STARTED, FAILED_TO_START, COMPLETED_NETWORK_FOUND, FAILED }
8892 
8893     /**
8894      * This class reports Scan metrics to statsd and holds intermediate scan request state.
8895      */
8896     public static class ScanMetrics {
8897         private static final String TAG_SCANS = "ScanMetrics";
8898         private static final String GMS_PACKAGE = "com.google.android.gms";
8899 
8900         // Scan types.
8901         public static final int SCAN_TYPE_SINGLE = 0;
8902         public static final int SCAN_TYPE_BACKGROUND = 1;
8903         public static final int SCAN_TYPE_MAX_VALUE = SCAN_TYPE_BACKGROUND;
8904         @IntDef(prefix = { "SCAN_TYPE_" }, value = {
8905                 SCAN_TYPE_SINGLE,
8906                 SCAN_TYPE_BACKGROUND,
8907         })
8908         public @interface ScanType {}
8909 
8910         // PNO scan states.
8911         public static final int PNO_SCAN_STATE_STARTED = 1;
8912         public static final int PNO_SCAN_STATE_FAILED_TO_START = 2;
8913         public static final int PNO_SCAN_STATE_COMPLETED_NETWORK_FOUND = 3;
8914         public static final int PNO_SCAN_STATE_FAILED = 4;
8915         @IntDef(prefix = { "PNO_SCAN_STATE_" }, value = {
8916                 PNO_SCAN_STATE_STARTED,
8917                 PNO_SCAN_STATE_FAILED_TO_START,
8918                 PNO_SCAN_STATE_COMPLETED_NETWORK_FOUND,
8919                 PNO_SCAN_STATE_FAILED
8920         })
8921         public @interface PnoScanState {}
8922 
8923         private final Object mLock = new Object();
8924         private Clock mClock;
8925 
8926         private List<String> mSettingsPackages = new ArrayList<>();
8927         private int mGmsUid = -1;
8928 
8929         // mNextScanState collects metadata about the next scan that's about to happen.
8930         // It is mutated by external callers via setX methods before the call to logScanStarted.
8931         private State mNextScanState = new State();
8932         // mActiveScanState is an immutable copy of mNextScanState during the scan process,
8933         // i.e. between logScanStarted and logScanSucceeded/Failed. Since the state is pushed to
8934         // statsd only when a scan ends, it's important to keep the immutable copy
8935         // for the duration of the scan.
8936         private State[] mActiveScanStates = new State[SCAN_TYPE_MAX_VALUE + 1];
8937 
8938         ScanMetrics(Context context, Clock clock) {
8939             mClock = clock;
8940 
8941             PackageManager pm = context.getPackageManager();
8942             if (pm != null) {
8943                 Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS);
8944                 List<ResolveInfo> packages = pm.queryIntentActivities(settingsIntent, 0);
8945                 for (ResolveInfo res : packages) {
8946                     String packageName = res.activityInfo.packageName;
8947                     Log.d(TAG_SCANS, "Settings package: " + packageName);
8948                     mSettingsPackages.add(packageName);
8949                 }
8950             }
8951 
8952             try {
8953                 mGmsUid = context.getPackageManager().getApplicationInfo(GMS_PACKAGE, 0).uid;
8954                 Log.d(TAG_SCANS, "GMS uid: " + mGmsUid);
8955             } catch (Exception e) {
8956                 Log.e(TAG_SCANS, "Can't get GMS uid");
8957             }
8958         }
8959 
8960         /**
8961          * Set WorkSource for the upcoming scan request.
8962          *
8963          * @param workSource
8964          */
8965         public void setWorkSource(WorkSource workSource) {
8966             synchronized (mLock) {
8967                 if (mNextScanState.mWorkSource == null) {
8968                     mNextScanState.mWorkSource = workSource;
8969                     if (DBG) Log.d(TAG_SCANS, "setWorkSource: workSource = " + workSource);
8970                 }
8971             }
8972         }
8973 
8974         /**
8975          * Set ClientUid for the upcoming scan request.
8976          *
8977          * @param uid
8978          */
8979         public void setClientUid(int uid) {
8980             synchronized (mLock) {
8981                 mNextScanState.mClientUid = uid;
8982 
8983                 if (DBG) Log.d(TAG_SCANS, "setClientUid: uid = " + uid);
8984             }
8985         }
8986 
8987         /**
8988          * Set Importance for the upcoming scan request.
8989          *
8990          * @param packageImportance See {@link ActivityManager.RunningAppProcessInfo.Importance}
8991          */
8992         public void setImportance(int packageImportance) {
8993             synchronized (mLock) {
8994                 mNextScanState.mPackageImportance = packageImportance;
8995 
8996                 if (DBG) {
8997                     Log.d(TAG_SCANS,
8998                             "setRequestFromBackground: packageImportance = " + packageImportance);
8999                 }
9000             }
9001         }
9002 
9003         /**
9004          * Indicate that a scan started.
9005          * @param scanType See {@link ScanMetrics.ScanType}
9006          */
9007         public void logScanStarted(@ScanType int scanType) {
9008             synchronized (mLock) {
9009                 if (DBG) Log.d(TAG_SCANS, "logScanStarted");
9010 
9011                 mNextScanState.mTimeStartMillis = mClock.getElapsedSinceBootMillis();
9012                 mActiveScanStates[scanType] = mNextScanState;
9013                 mNextScanState = new State();
9014             }
9015         }
9016 
9017         /**
9018          * Indicate that a scan failed to start.
9019          * @param scanType See {@link ScanMetrics.ScanType}
9020          */
9021         public void logScanFailedToStart(@ScanType int scanType) {
9022             synchronized (mLock) {
9023                 Log.d(TAG_SCANS, "logScanFailedToStart");
9024 
9025                 mNextScanState.mTimeStartMillis = mClock.getElapsedSinceBootMillis();
9026                 mActiveScanStates[scanType] = mNextScanState;
9027                 mNextScanState = new State();
9028 
9029                 log(scanType, WifiStatsLog.WIFI_SCAN_REPORTED__RESULT__RESULT_FAILED_TO_START, 0);
9030                 mActiveScanStates[scanType] = null;
9031             }
9032         }
9033 
9034         /**
9035          * Indicate that a scan finished successfully.
9036          * @param scanType See {@link ScanMetrics.ScanType}
9037          * @param countOfNetworksFound How many networks were found.
9038          */
9039         public void logScanSucceeded(@ScanType int scanType, int countOfNetworksFound) {
9040             synchronized (mLock) {
9041                 if (DBG) Log.d(TAG_SCANS, "logScanSucceeded: found = " + countOfNetworksFound);
9042 
9043                 log(scanType, WifiStatsLog.WIFI_SCAN_REPORTED__RESULT__RESULT_SUCCESS,
9044                         countOfNetworksFound);
9045                 mActiveScanStates[scanType] = null;
9046             }
9047         }
9048 
9049         /**
9050          * Log a PNO scan event: start/finish/fail.
9051          * @param pnoScanState See {@link PnoScanState}
9052          */
9053         public void logPnoScanEvent(@PnoScanState int pnoScanState) {
9054             synchronized (mLock) {
9055                 int state = 0;
9056 
9057                 switch (pnoScanState) {
9058                     case PNO_SCAN_STATE_STARTED:
9059                         state = WifiStatsLog.WIFI_PNO_SCAN_REPORTED__STATE__STARTED;
9060                         break;
9061                     case PNO_SCAN_STATE_FAILED_TO_START:
9062                         state = WifiStatsLog.WIFI_PNO_SCAN_REPORTED__STATE__FAILED_TO_START;
9063                         break;
9064                     case PNO_SCAN_STATE_COMPLETED_NETWORK_FOUND:
9065                         state = WifiStatsLog.WIFI_PNO_SCAN_REPORTED__STATE__FINISHED_NETWORKS_FOUND;
9066                         break;
9067                     case PNO_SCAN_STATE_FAILED:
9068                         state = WifiStatsLog.WIFI_PNO_SCAN_REPORTED__STATE__FAILED;
9069                         break;
9070                 }
9071 
9072                 WifiStatsLog.write(WifiStatsLog.WIFI_PNO_SCAN_REPORTED, state);
9073 
9074                 if (DBG) Log.d(TAG_SCANS, "logPnoScanEvent: pnoScanState = " + pnoScanState);
9075             }
9076         }
9077 
9078         /**
9079          * Indicate that a scan failed.
9080          */
9081         public void logScanFailed(@ScanType int scanType) {
9082             synchronized (mLock) {
9083                 if (DBG) Log.d(TAG_SCANS, "logScanFailed");
9084 
9085                 log(scanType, WifiStatsLog.WIFI_SCAN_REPORTED__RESULT__RESULT_FAILED_TO_SCAN, 0);
9086                 mActiveScanStates[scanType] = null;
9087             }
9088         }
9089 
9090         private void log(@ScanType int scanType, int result, int countNetworks) {
9091             State state = mActiveScanStates[scanType];
9092 
9093             if (state == null) {
9094                 if (DBG) Log.e(TAG_SCANS, "Wifi scan result log called with no prior start calls!");
9095                 return;
9096             }
9097 
9098             int type = WifiStatsLog.WIFI_SCAN_REPORTED__TYPE__TYPE_UNKNOWN;
9099             if (scanType == SCAN_TYPE_SINGLE) {
9100                 type = WifiStatsLog.WIFI_SCAN_REPORTED__TYPE__TYPE_SINGLE;
9101             } else if (scanType == SCAN_TYPE_BACKGROUND) {
9102                 type = WifiStatsLog.WIFI_SCAN_REPORTED__TYPE__TYPE_BACKGROUND;
9103             }
9104 
9105             long duration = mClock.getElapsedSinceBootMillis() - state.mTimeStartMillis;
9106 
9107             int source = WifiStatsLog.WIFI_SCAN_REPORTED__SOURCE__SOURCE_NO_WORK_SOURCE;
9108             if (state.mClientUid != -1 && state.mClientUid == mGmsUid) {
9109                 source = WifiStatsLog.WIFI_SCAN_REPORTED__SOURCE__SOURCE_GMS;
9110             } else if (state.mWorkSource != null) {
9111                 if (state.mWorkSource.equals(ClientModeImpl.WIFI_WORK_SOURCE)) {
9112                     source = WifiStatsLog.WIFI_SCAN_REPORTED__SOURCE__SOURCE_WIFI_STACK;
9113                 } else {
9114                     source = WifiStatsLog.WIFI_SCAN_REPORTED__SOURCE__SOURCE_OTHER_APP;
9115 
9116                     for (int i = 0; i < state.mWorkSource.size(); i++) {
9117                         if (mSettingsPackages.contains(
9118                                 state.mWorkSource.getPackageName(i))) {
9119                             source = WifiStatsLog.WIFI_SCAN_REPORTED__SOURCE__SOURCE_SETTINGS_APP;
9120                             break;
9121                         }
9122                     }
9123                 }
9124             }
9125 
9126             int importance = WifiStatsLog.WIFI_SCAN_REPORTED__IMPORTANCE__IMPORTANCE_UNKNOWN;
9127             if (state.mPackageImportance != -1) {
9128                 if (state.mPackageImportance
9129                         <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
9130                     importance = WifiStatsLog.WIFI_SCAN_REPORTED__IMPORTANCE__IMPORTANCE_FOREGROUND;
9131                 } else if (state.mPackageImportance
9132                         <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE) {
9133                     importance =
9134                             WifiStatsLog.WIFI_SCAN_REPORTED__IMPORTANCE__IMPORTANCE_FOREGROUND_SERVICE;
9135                 } else {
9136                     importance = WifiStatsLog.WIFI_SCAN_REPORTED__IMPORTANCE__IMPORTANCE_BACKGROUND;
9137                 }
9138             }
9139 
9140             WifiStatsLog.write(WifiStatsLog.WIFI_SCAN_REPORTED,
9141                     type,
9142                     result,
9143                     source,
9144                     importance,
9145                     (int) duration,
9146                     countNetworks);
9147 
9148             if (DBG) {
9149                 Log.d(TAG_SCANS,
9150                         "WifiScanReported: type = " + type
9151                                 + ", result = " + result
9152                                 + ", source = " + source
9153                                 + ", importance = " + importance
9154                                 + ", networks = " + countNetworks);
9155             }
9156         }
9157 
9158         static class State {
9159             WorkSource mWorkSource = null;
9160             int mClientUid = -1;
9161             // see @ActivityManager.RunningAppProcessInfo.Importance
9162             int mPackageImportance = -1;
9163 
9164             long mTimeStartMillis;
9165         }
9166     }
9167 
9168     /** Set whether Make Before Break is supported by the hardware and enabled. */
9169     public void setIsMakeBeforeBreakSupported(boolean supported) {
9170         synchronized (mLock) {
9171             mWifiToWifiSwitchStats.isMakeBeforeBreakSupported = supported;
9172         }
9173     }
9174 
9175     /**
9176      * Increment the number of times Wifi to Wifi switch was triggered. This includes Make Before
9177      * Break and Break Before Make.
9178      */
9179     public void incrementWifiToWifiSwitchTriggerCount() {
9180         synchronized (mLock) {
9181             mWifiToWifiSwitchStats.wifiToWifiSwitchTriggerCount++;
9182         }
9183     }
9184 
9185     /**
9186      * Increment the Number of times Wifi to Wifi switch was triggered using Make Before Break
9187      * (MBB). Note that MBB may not always be used for various reasons e.g. no additional iface
9188      * available due to ongoing SoftAP, both old and new network have MAC randomization disabled,
9189      * etc.
9190      */
9191     public void incrementMakeBeforeBreakTriggerCount() {
9192         synchronized (mLock) {
9193             mWifiToWifiSwitchStats.makeBeforeBreakTriggerCount++;
9194         }
9195     }
9196 
9197     /**
9198      * Increment the number of times Make Before Break was aborted due to the new network not having
9199      * internet.
9200      */
9201     public void incrementMakeBeforeBreakNoInternetCount() {
9202         synchronized (mLock) {
9203             mWifiToWifiSwitchStats.makeBeforeBreakNoInternetCount++;
9204         }
9205     }
9206 
9207     /**
9208      * Increment the number of times where, for some reason, Make Before Break resulted in the
9209      * loss of the primary ClientModeManager, and we needed to recover by making one of the
9210      * SECONDARY_TRANSIENT ClientModeManagers primary.
9211      */
9212     public void incrementMakeBeforeBreakRecoverPrimaryCount() {
9213         synchronized (mLock) {
9214             mWifiToWifiSwitchStats.makeBeforeBreakRecoverPrimaryCount++;
9215         }
9216     }
9217 
9218     /**
9219      * Increment the number of times the new network in Make Before Break had its internet
9220      * connection validated.
9221      */
9222     public void incrementMakeBeforeBreakInternetValidatedCount() {
9223         synchronized (mLock) {
9224             mWifiToWifiSwitchStats.makeBeforeBreakInternetValidatedCount++;
9225         }
9226     }
9227 
9228     /**
9229      * Increment the number of times the old network in Make Before Break was successfully
9230      * transitioned from PRIMARY to SECONDARY_TRANSIENT role.
9231      */
9232     public void incrementMakeBeforeBreakSuccessCount() {
9233         synchronized (mLock) {
9234             mWifiToWifiSwitchStats.makeBeforeBreakSuccessCount++;
9235         }
9236     }
9237 
9238     /**
9239      * Increment the number of times the old network in Make Before Break completed lingering and
9240      * was disconnected.
9241      * @param duration the lingering duration in ms
9242      */
9243     public void incrementMakeBeforeBreakLingerCompletedCount(long duration) {
9244         synchronized (mLock) {
9245             mWifiToWifiSwitchStats.makeBeforeBreakLingerCompletedCount++;
9246             int lingeringDurationSeconds = Math.min(MBB_LINGERING_DURATION_MAX_SECONDS,
9247                     (int) duration / 1000);
9248             mMakeBeforeBreakLingeringDurationSeconds.increment(lingeringDurationSeconds);
9249         }
9250     }
9251 
9252     private String wifiToWifiSwitchStatsToString(WifiToWifiSwitchStats stats) {
9253         return "WifiToWifiSwitchStats{"
9254                 + "isMakeBeforeBreakSupported=" + stats.isMakeBeforeBreakSupported
9255                 + ",wifiToWifiSwitchTriggerCount=" + stats.wifiToWifiSwitchTriggerCount
9256                 + ",makeBeforeBreakTriggerCount=" + stats.makeBeforeBreakTriggerCount
9257                 + ",makeBeforeBreakNoInternetCount=" + stats.makeBeforeBreakNoInternetCount
9258                 + ",makeBeforeBreakRecoverPrimaryCount=" + stats.makeBeforeBreakRecoverPrimaryCount
9259                 + ",makeBeforeBreakInternetValidatedCount="
9260                 + stats.makeBeforeBreakInternetValidatedCount
9261                 + ",makeBeforeBreakSuccessCount=" + stats.makeBeforeBreakSuccessCount
9262                 + ",makeBeforeBreakLingerCompletedCount="
9263                 + stats.makeBeforeBreakLingerCompletedCount
9264                 + ",makeBeforeBreakLingeringDurationSeconds="
9265                 + mMakeBeforeBreakLingeringDurationSeconds
9266                 + "}";
9267     }
9268 
9269     /**
9270      * Increment number of number of Passpoint connections with a venue URL
9271      */
9272     public void incrementTotalNumberOfPasspointConnectionsWithVenueUrl() {
9273         synchronized (mLock) {
9274             mWifiLogProto.totalNumberOfPasspointConnectionsWithVenueUrl++;
9275         }
9276     }
9277 
9278     /**
9279      * Increment number of number of Passpoint connections with a T&C URL
9280      */
9281     public void incrementTotalNumberOfPasspointConnectionsWithTermsAndConditionsUrl() {
9282         synchronized (mLock) {
9283             mWifiLogProto.totalNumberOfPasspointConnectionsWithTermsAndConditionsUrl++;
9284         }
9285     }
9286 
9287     /**
9288      * Increment number of successful acceptance of Passpoint T&C
9289      */
9290     public void incrementTotalNumberOfPasspointAcceptanceOfTermsAndConditions() {
9291         synchronized (mLock) {
9292             mWifiLogProto.totalNumberOfPasspointAcceptanceOfTermsAndConditions++;
9293         }
9294     }
9295 
9296     /**
9297      * Increment number of Passpoint profiles with decorated identity prefix
9298      */
9299     public void incrementTotalNumberOfPasspointProfilesWithDecoratedIdentity() {
9300         synchronized (mLock) {
9301             mWifiLogProto.totalNumberOfPasspointProfilesWithDecoratedIdentity++;
9302         }
9303     }
9304 
9305     /**
9306      * Increment number of Passpoint Deauth-Imminent notification scope
9307      */
9308     public void incrementPasspointDeauthImminentScope(boolean isEss) {
9309         synchronized (mLock) {
9310             mPasspointDeauthImminentScope.increment(isEss ? PASSPOINT_DEAUTH_IMMINENT_SCOPE_ESS
9311                     : PASSPOINT_DEAUTH_IMMINENT_SCOPE_BSS);
9312         }
9313     }
9314 
9315     /**
9316      * Increment number of times connection failure status reported per
9317      * WifiConfiguration.RecentFailureReason
9318      */
9319     public void incrementRecentFailureAssociationStatusCount(
9320             @WifiConfiguration.RecentFailureReason int reason) {
9321         synchronized (mLock) {
9322             mRecentFailureAssociationStatus.increment(reason);
9323         }
9324     }
9325 
9326     /**
9327      * Logging the time it takes for save config to the storage.
9328      * @param time the time it take to write to the storage
9329      */
9330     public void wifiConfigStored(int time) {
9331         WifiStatsLog.write(WIFI_CONFIG_SAVED, time);
9332     }
9333 
9334     /**
9335      * Set Wi-Fi usability state per interface as predicted by the scorer
9336      */
9337     public void setScorerPredictedWifiUsabilityState(String ifaceName,
9338             WifiUsabilityState usabilityState) {
9339         mWifiUsabilityStatePerIface.put(ifaceName, usabilityState);
9340     }
9341 
9342     private static int getSoftApStartedStartResult(@SoftApManager.StartResult int startResult) {
9343         switch (startResult) {
9344             case SoftApManager.START_RESULT_UNKNOWN:
9345                 return WifiStatsLog.SOFT_AP_STARTED__RESULT__START_RESULT_UNKNOWN;
9346             case SoftApManager.START_RESULT_SUCCESS:
9347                 return WifiStatsLog.SOFT_AP_STARTED__RESULT__START_RESULT_SUCCESS;
9348             case SoftApManager.START_RESULT_FAILURE_GENERAL:
9349                 return WifiStatsLog.SOFT_AP_STARTED__RESULT__START_RESULT_FAILURE_GENERAL;
9350 
9351             case SoftApManager.START_RESULT_FAILURE_NO_CHANNEL:
9352                 return WifiStatsLog.SOFT_AP_STARTED__RESULT__START_RESULT_FAILURE_NO_CHANNEL;
9353             case SoftApManager.START_RESULT_FAILURE_UNSUPPORTED_CONFIG:
9354                 return WifiStatsLog.SOFT_AP_STARTED__RESULT__START_RESULT_FAILURE_UNSUPPORTED_CONFIG;
9355             case SoftApManager.START_RESULT_FAILURE_START_HAL:
9356                 return WifiStatsLog.SOFT_AP_STARTED__RESULT__START_RESULT_FAILURE_START_HAL;
9357             case SoftApManager.START_RESULT_FAILURE_START_HOSTAPD:
9358                 return WifiStatsLog.SOFT_AP_STARTED__RESULT__START_RESULT_FAILURE_START_HOSTAPD;
9359             case SoftApManager.START_RESULT_FAILURE_INTERFACE_CONFLICT_USER_REJECTED:
9360                 return WifiStatsLog.SOFT_AP_STARTED__RESULT__START_RESULT_FAILURE_INTERFACE_CONFLICT_USER_REJECTED;
9361             case SoftApManager.START_RESULT_FAILURE_INTERFACE_CONFLICT:
9362                 return WifiStatsLog.SOFT_AP_STARTED__RESULT__START_RESULT_FAILURE_INTERFACE_CONFLICT;
9363             case SoftApManager.START_RESULT_FAILURE_CREATE_INTERFACE:
9364                 return WifiStatsLog.SOFT_AP_STARTED__RESULT__START_RESULT_FAILURE_CREATE_INTERFACE;
9365             case SoftApManager.START_RESULT_FAILURE_SET_COUNTRY_CODE:
9366                 return WifiStatsLog.SOFT_AP_STARTED__RESULT__START_RESULT_FAILURE_SET_COUNTRY_CODE;
9367             case SoftApManager.START_RESULT_FAILURE_SET_MAC_ADDRESS:
9368                 return WifiStatsLog.SOFT_AP_STARTED__RESULT__START_RESULT_FAILURE_SET_MAC_ADDRESS;
9369             case SoftApManager.START_RESULT_FAILURE_REGISTER_AP_CALLBACK_HOSTAPD:
9370                 return WifiStatsLog.SOFT_AP_STARTED__RESULT__START_RESULT_FAILURE_REGISTER_AP_CALLBACK_HOSTAPD;
9371             case SoftApManager.START_RESULT_FAILURE_REGISTER_AP_CALLBACK_WIFICOND:
9372                 return WifiStatsLog.SOFT_AP_STARTED__RESULT__START_RESULT_FAILURE_REGISTER_AP_CALLBACK_WIFICOND;
9373             case SoftApManager.START_RESULT_FAILURE_ADD_AP_HOSTAPD:
9374                 return WifiStatsLog.SOFT_AP_STARTED__RESULT__START_RESULT_FAILURE_ADD_AP_HOSTAPD;
9375             default:
9376                 Log.wtf(TAG, "getSoftApStartedStartResult: unknown StartResult" + startResult);
9377                 return WifiStatsLog.SOFT_AP_STARTED__RESULT__START_RESULT_UNKNOWN;
9378         }
9379     }
9380 
9381     private static int getSoftApStartedRole(ActiveModeManager.SoftApRole role) {
9382         if (ActiveModeManager.ROLE_SOFTAP_LOCAL_ONLY.equals(role)) {
9383             return WifiStatsLog.SOFT_AP_STARTED__ROLE__ROLE_LOCAL_ONLY;
9384         } else if (ActiveModeManager.ROLE_SOFTAP_TETHERED.equals(role)) {
9385             return WifiStatsLog.SOFT_AP_STARTED__ROLE__ROLE_TETHERING;
9386         }
9387         Log.wtf(TAG, "getSoftApStartedRole: unknown role " + role);
9388         return WifiStatsLog.SOFT_AP_STARTED__ROLE__ROLE_UNKNOWN;
9389     }
9390 
9391     private static int getSoftApStartedStaApConcurrency(
9392             boolean isStaApSupported, boolean isStaDbsSupported) {
9393         if (isStaDbsSupported) {
9394             return WifiStatsLog.SOFT_AP_STARTED__STA_AP_CONCURRENCY__STA_AP_CONCURRENCY_DBS;
9395         }
9396         if (isStaApSupported) {
9397             return WifiStatsLog.SOFT_AP_STARTED__STA_AP_CONCURRENCY__STA_AP_CONCURRENCY_SINGLE;
9398         }
9399         return WifiStatsLog.SOFT_AP_STARTED__STA_AP_CONCURRENCY__STA_AP_CONCURRENCY_UNSUPPORTED;
9400     }
9401 
9402     private static int getSoftApStartedStaStatus(int staFreqMhz) {
9403         if (staFreqMhz == WifiInfo.UNKNOWN_FREQUENCY) {
9404             return WifiStatsLog.SOFT_AP_STARTED__STA_STATUS__STA_STATUS_DISCONNECTED;
9405         }
9406         if (ScanResult.is24GHz(staFreqMhz)) {
9407             return WifiStatsLog.SOFT_AP_STARTED__STA_STATUS__STA_STATUS_CONNECTED_2_GHZ;
9408         }
9409         if (ScanResult.is5GHz(staFreqMhz)) {
9410             return WifiStatsLog.SOFT_AP_STARTED__STA_STATUS__STA_STATUS_CONNECTED_5_GHZ;
9411         }
9412         if (ScanResult.is6GHz(staFreqMhz)) {
9413             return WifiStatsLog.SOFT_AP_STARTED__STA_STATUS__STA_STATUS_CONNECTED_6_GHZ;
9414         }
9415         Log.wtf(TAG, "getSoftApStartedStaStatus: unknown band for freq " + staFreqMhz);
9416         return WifiStatsLog.SOFT_AP_STARTED__STA_STATUS__STA_STATUS_UNKNOWN;
9417     }
9418 
9419     private static int getSoftApStartedAuthType(
9420             @SoftApConfiguration.SecurityType int securityType) {
9421         switch (securityType) {
9422             case SoftApConfiguration.SECURITY_TYPE_OPEN:
9423                 return WifiStatsLog.SOFT_AP_STARTED__AUTH_TYPE__AUTH_TYPE_NONE;
9424             case SoftApConfiguration.SECURITY_TYPE_WPA2_PSK:
9425                 return WifiStatsLog.SOFT_AP_STARTED__AUTH_TYPE__AUTH_TYPE_WPA2_PSK;
9426             case SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION:
9427                 return WifiStatsLog.SOFT_AP_STARTED__AUTH_TYPE__AUTH_TYPE_SAE_TRANSITION;
9428             case SoftApConfiguration.SECURITY_TYPE_WPA3_SAE:
9429                 return WifiStatsLog.SOFT_AP_STARTED__AUTH_TYPE__AUTH_TYPE_SAE;
9430             case SoftApConfiguration.SECURITY_TYPE_WPA3_OWE_TRANSITION:
9431                 return WifiStatsLog.SOFT_AP_STARTED__AUTH_TYPE__AUTH_TYPE_OWE_TRANSITION;
9432             case SoftApConfiguration.SECURITY_TYPE_WPA3_OWE:
9433                 return WifiStatsLog.SOFT_AP_STARTED__AUTH_TYPE__AUTH_TYPE_OWE;
9434             default:
9435                 Log.wtf(TAG, "getSoftApStartedAuthType: unknown type " + securityType);
9436                 return WifiStatsLog.SOFT_AP_STARTED__STA_STATUS__STA_STATUS_UNKNOWN;
9437         }
9438     }
9439 
9440     /**
9441      * Writes the SoftApStarted event to WifiStatsLog.
9442      */
9443     public void writeSoftApStartedEvent(@SoftApManager.StartResult int startResult,
9444             @NonNull ActiveModeManager.SoftApRole role,
9445             @WifiScanner.WifiBand int band1,
9446             @WifiScanner.WifiBand int band2,
9447             boolean isDbsSupported,
9448             boolean isStaApSupported,
9449             boolean isStaDbsSupported,
9450             int staFreqMhz,
9451             @SoftApConfiguration.SecurityType int securityType) {
9452         WifiStatsLog.write(WifiStatsLog.SOFT_AP_STARTED,
9453                 getSoftApStartedStartResult(startResult),
9454                 getSoftApStartedRole(role),
9455                 band1,
9456                 band2,
9457                 isDbsSupported,
9458                 getSoftApStartedStaApConcurrency(isStaApSupported, isStaDbsSupported),
9459                 getSoftApStartedStaStatus(staFreqMhz),
9460                 getSoftApStartedAuthType(securityType));
9461         if (startResult == SoftApManager.START_RESULT_SUCCESS) {
9462             WifiStatsLog.write(WifiStatsLog.SOFT_AP_STATE_CHANGED,
9463                     WifiStatsLog.SOFT_AP_STATE_CHANGED__HOTSPOT_ON__STATE_ON);
9464         }
9465     }
9466 
9467     private static int getSoftApStoppedStopEvent(@SoftApManager.StopEvent int stopEvent) {
9468         switch (stopEvent) {
9469             case SoftApManager.STOP_EVENT_UNKNOWN:
9470                 return WifiStatsLog.SOFT_AP_STOPPED__STOP_EVENT__STOP_EVENT_UNKNOWN;
9471             case SoftApManager.STOP_EVENT_STOPPED:
9472                 return WifiStatsLog.SOFT_AP_STOPPED__STOP_EVENT__STOP_EVENT_STOPPED;
9473             case SoftApManager.STOP_EVENT_INTERFACE_DOWN:
9474                 return WifiStatsLog.SOFT_AP_STOPPED__STOP_EVENT__STOP_EVENT_INTERFACE_DOWN;
9475             case SoftApManager.STOP_EVENT_INTERFACE_DESTROYED:
9476                 return WifiStatsLog.SOFT_AP_STOPPED__STOP_EVENT__STOP_EVENT_INTERFACE_DESTROYED;
9477             case SoftApManager.STOP_EVENT_HOSTAPD_FAILURE:
9478                 return WifiStatsLog.SOFT_AP_STOPPED__STOP_EVENT__STOP_EVENT_HOSTAPD_FAILURE;
9479             case SoftApManager.STOP_EVENT_NO_USAGE_TIMEOUT:
9480                 return WifiStatsLog.SOFT_AP_STOPPED__STOP_EVENT__STOP_EVENT_NO_USAGE_TIMEOUT;
9481             default:
9482                 Log.wtf(TAG, "getSoftApStoppedStopEvent: unknown StopEvent " + stopEvent);
9483                 return WifiStatsLog.SOFT_AP_STOPPED__STOP_EVENT__STOP_EVENT_UNKNOWN;
9484         }
9485     }
9486 
9487     private static int getSoftApStoppedRole(ActiveModeManager.SoftApRole role) {
9488         if (ActiveModeManager.ROLE_SOFTAP_LOCAL_ONLY.equals(role)) {
9489             return WifiStatsLog.SOFT_AP_STOPPED__ROLE__ROLE_LOCAL_ONLY;
9490         } else if (ActiveModeManager.ROLE_SOFTAP_TETHERED.equals(role)) {
9491             return WifiStatsLog.SOFT_AP_STOPPED__ROLE__ROLE_TETHERING;
9492         }
9493         Log.wtf(TAG, "getSoftApStoppedRole: unknown role " + role);
9494         return WifiStatsLog.SOFT_AP_STOPPED__ROLE__ROLE_UNKNOWN;
9495     }
9496 
9497     private static int getSoftApStoppedStaApConcurrency(
9498             boolean isStaApSupported, boolean isStaDbsSupported) {
9499         if (isStaDbsSupported) {
9500             return WifiStatsLog.SOFT_AP_STOPPED__STA_AP_CONCURRENCY__STA_AP_CONCURRENCY_DBS;
9501         }
9502         if (isStaApSupported) {
9503             return WifiStatsLog.SOFT_AP_STOPPED__STA_AP_CONCURRENCY__STA_AP_CONCURRENCY_SINGLE;
9504         }
9505         return WifiStatsLog.SOFT_AP_STOPPED__STA_AP_CONCURRENCY__STA_AP_CONCURRENCY_UNSUPPORTED;
9506     }
9507     private static int getSoftApStoppedStaStatus(int staFreqMhz) {
9508         if (staFreqMhz == WifiInfo.UNKNOWN_FREQUENCY) {
9509             return WifiStatsLog.SOFT_AP_STOPPED__STA_STATUS__STA_STATUS_DISCONNECTED;
9510         }
9511         if (ScanResult.is24GHz(staFreqMhz)) {
9512             return WifiStatsLog.SOFT_AP_STOPPED__STA_STATUS__STA_STATUS_CONNECTED_2_GHZ;
9513         }
9514         if (ScanResult.is5GHz(staFreqMhz)) {
9515             return WifiStatsLog.SOFT_AP_STOPPED__STA_STATUS__STA_STATUS_CONNECTED_5_GHZ;
9516         }
9517         if (ScanResult.is6GHz(staFreqMhz)) {
9518             return WifiStatsLog.SOFT_AP_STOPPED__STA_STATUS__STA_STATUS_CONNECTED_6_GHZ;
9519         }
9520         Log.wtf(TAG, "getSoftApStoppedStaStatus: unknown band for freq " + staFreqMhz);
9521         return WifiStatsLog.SOFT_AP_STOPPED__STA_STATUS__STA_STATUS_UNKNOWN;
9522     }
9523 
9524     private static int getSoftApStoppedAuthType(
9525             @SoftApConfiguration.SecurityType int securityType) {
9526         switch (securityType) {
9527             case SoftApConfiguration.SECURITY_TYPE_OPEN:
9528                 return WifiStatsLog.SOFT_AP_STOPPED__AUTH_TYPE__AUTH_TYPE_NONE;
9529             case SoftApConfiguration.SECURITY_TYPE_WPA2_PSK:
9530                 return WifiStatsLog.SOFT_AP_STOPPED__AUTH_TYPE__AUTH_TYPE_WPA2_PSK;
9531             case SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION:
9532                 return WifiStatsLog.SOFT_AP_STOPPED__AUTH_TYPE__AUTH_TYPE_SAE_TRANSITION;
9533             case SoftApConfiguration.SECURITY_TYPE_WPA3_SAE:
9534                 return WifiStatsLog.SOFT_AP_STOPPED__AUTH_TYPE__AUTH_TYPE_SAE;
9535             case SoftApConfiguration.SECURITY_TYPE_WPA3_OWE_TRANSITION:
9536                 return WifiStatsLog.SOFT_AP_STOPPED__AUTH_TYPE__AUTH_TYPE_OWE_TRANSITION;
9537             case SoftApConfiguration.SECURITY_TYPE_WPA3_OWE:
9538                 return WifiStatsLog.SOFT_AP_STOPPED__AUTH_TYPE__AUTH_TYPE_OWE;
9539             default:
9540                 Log.wtf(TAG, "getSoftApStoppedAuthType: unknown type " + securityType);
9541                 return WifiStatsLog.SOFT_AP_STOPPED__STA_STATUS__STA_STATUS_UNKNOWN;
9542         }
9543     }
9544 
9545     private static int getSoftApStoppedStandard(@WifiAnnotations.WifiStandard int standard) {
9546         switch (standard) {
9547             case ScanResult.WIFI_STANDARD_UNKNOWN:
9548                 return WifiStatsLog.SOFT_AP_STOPPED__STANDARD__WIFI_STANDARD_UNKNOWN;
9549             case ScanResult.WIFI_STANDARD_LEGACY:
9550                 return WifiStatsLog.SOFT_AP_STOPPED__STANDARD__WIFI_STANDARD_LEGACY;
9551             case ScanResult.WIFI_STANDARD_11N:
9552                 return WifiStatsLog.SOFT_AP_STOPPED__STANDARD__WIFI_STANDARD_11N;
9553             case ScanResult.WIFI_STANDARD_11AC:
9554                 return WifiStatsLog.SOFT_AP_STOPPED__STANDARD__WIFI_STANDARD_11AC;
9555             case ScanResult.WIFI_STANDARD_11AX:
9556                 return WifiStatsLog.SOFT_AP_STOPPED__STANDARD__WIFI_STANDARD_11AX;
9557             case ScanResult.WIFI_STANDARD_11AD:
9558                 return WifiStatsLog.SOFT_AP_STOPPED__STANDARD__WIFI_STANDARD_11AD;
9559             case ScanResult.WIFI_STANDARD_11BE:
9560                 return WifiStatsLog.SOFT_AP_STOPPED__STANDARD__WIFI_STANDARD_11BE;
9561             default:
9562                 Log.wtf(TAG, "getSoftApStoppedStandard: unknown standard " + standard);
9563                 return WifiStatsLog.SOFT_AP_STOPPED__STANDARD__WIFI_STANDARD_UNKNOWN;
9564         }
9565     }
9566 
9567     private static int getSoftApStoppedUpstreamType(@Nullable NetworkCapabilities caps) {
9568         if (caps == null) {
9569             return WifiStatsLog.SOFT_AP_STOPPED__UPSTREAM_TRANSPORT__TT_UNKNOWN;
9570         }
9571         if (caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
9572             if (caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
9573                 if (caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
9574                     return WifiStatsLog.SOFT_AP_STOPPED__UPSTREAM_TRANSPORT__TT_WIFI_CELLULAR_VPN;
9575                 }
9576                 return WifiStatsLog.SOFT_AP_STOPPED__UPSTREAM_TRANSPORT__TT_WIFI_VPN;
9577             }
9578             if (caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
9579                 return WifiStatsLog.SOFT_AP_STOPPED__UPSTREAM_TRANSPORT__TT_CELLULAR_VPN;
9580             }
9581             if (caps.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH)) {
9582                 return WifiStatsLog.SOFT_AP_STOPPED__UPSTREAM_TRANSPORT__TT_BLUETOOTH_VPN;
9583             }
9584             if (caps.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
9585                 return WifiStatsLog.SOFT_AP_STOPPED__UPSTREAM_TRANSPORT__TT_ETHERNET_VPN;
9586             }
9587         }
9588         if (caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
9589             return WifiStatsLog.SOFT_AP_STOPPED__UPSTREAM_TRANSPORT__TT_WIFI;
9590         }
9591         if (caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
9592             return WifiStatsLog.SOFT_AP_STOPPED__UPSTREAM_TRANSPORT__TT_CELLULAR;
9593         }
9594         if (caps.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH)) {
9595             return WifiStatsLog.SOFT_AP_STOPPED__UPSTREAM_TRANSPORT__TT_BLUETOOTH;
9596         }
9597         if (caps.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
9598             return WifiStatsLog.SOFT_AP_STOPPED__UPSTREAM_TRANSPORT__TT_ETHERNET;
9599         }
9600         if (caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE)) {
9601             return WifiStatsLog.SOFT_AP_STOPPED__UPSTREAM_TRANSPORT__TT_WIFI_AWARE;
9602         }
9603         if (caps.hasTransport(NetworkCapabilities.TRANSPORT_LOWPAN)) {
9604             return WifiStatsLog.SOFT_AP_STOPPED__UPSTREAM_TRANSPORT__TT_LOWPAN;
9605         }
9606         if (caps.hasTransport(NetworkCapabilities.TRANSPORT_TEST)) {
9607             return WifiStatsLog.SOFT_AP_STOPPED__UPSTREAM_TRANSPORT__TT_TEST;
9608         }
9609         Log.wtf(TAG, "getSoftApStoppedStandard: unknown transport types for caps "
9610                 + Arrays.toString(caps.getTransportTypes()));
9611         return WifiStatsLog.SOFT_AP_STOPPED__UPSTREAM_TRANSPORT__TT_UNKNOWN;
9612     }
9613 
9614     /**
9615      * Writes the SoftApStoppedEvent to WifiStatsLog.
9616      */
9617     public void writeSoftApStoppedEvent(@SoftApManager.StopEvent int stopEvent,
9618             @NonNull ActiveModeManager.SoftApRole role,
9619             @WifiScanner.WifiBand int band,
9620             boolean isDbs,
9621             boolean isStaApSupported,
9622             boolean isStaBridgedApSupported,
9623             int staFreqMhz,
9624             boolean isTimeoutEnabled,
9625             int sessionDurationSeconds,
9626             @SoftApConfiguration.SecurityType int securityType,
9627             @WifiAnnotations.WifiStandard int standard,
9628             int maxClients,
9629             boolean isDbsTimeoutEnabled,
9630             int dbsFailureBand,
9631             int dbsTimeoutBand,
9632             @Nullable NetworkCapabilities upstreamCaps) {
9633         WifiStatsLog.write(WifiStatsLog.SOFT_AP_STOPPED,
9634                 getSoftApStoppedStopEvent(stopEvent),
9635                 getSoftApStoppedRole(role),
9636                 band,
9637                 isDbs,
9638                 getSoftApStoppedStaApConcurrency(isStaApSupported, isStaBridgedApSupported),
9639                 getSoftApStoppedStaStatus(staFreqMhz),
9640                 isTimeoutEnabled,
9641                 sessionDurationSeconds,
9642                 getSoftApStoppedAuthType(securityType),
9643                 getSoftApStoppedStandard(standard),
9644                 maxClients,
9645                 isDbsTimeoutEnabled,
9646                 dbsFailureBand,
9647                 dbsTimeoutBand,
9648                 getSoftApStoppedUpstreamType(upstreamCaps));
9649         WifiStatsLog.write(WifiStatsLog.SOFT_AP_STATE_CHANGED,
9650                 WifiStatsLog.SOFT_AP_STATE_CHANGED__HOTSPOT_ON__STATE_OFF);
9651     }
9652 }
9653