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