• 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 package com.android.server.wifi;
17 
18 import static android.content.Intent.ACTION_SCREEN_OFF;
19 import static android.content.Intent.ACTION_SCREEN_ON;
20 import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT;
21 import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_LOW_MVMT;
22 import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_STATIONARY;
23 import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_UNKNOWN;
24 
25 import static com.android.server.wifi.WifiMetricsTestUtil.assertDeviceMobilityStatePnoScanStatsEqual;
26 import static com.android.server.wifi.WifiMetricsTestUtil.assertExperimentProbeCountsEqual;
27 import static com.android.server.wifi.WifiMetricsTestUtil.assertHistogramBucketsEqual;
28 import static com.android.server.wifi.WifiMetricsTestUtil.assertKeyCountsEqual;
29 import static com.android.server.wifi.WifiMetricsTestUtil.assertLinkProbeFailureReasonCountsEqual;
30 import static com.android.server.wifi.WifiMetricsTestUtil.assertLinkProbeStaEventsEqual;
31 import static com.android.server.wifi.WifiMetricsTestUtil.buildDeviceMobilityStatePnoScanStats;
32 import static com.android.server.wifi.WifiMetricsTestUtil.buildExperimentProbeCounts;
33 import static com.android.server.wifi.WifiMetricsTestUtil.buildHistogramBucketInt32;
34 import static com.android.server.wifi.WifiMetricsTestUtil.buildInt32Count;
35 import static com.android.server.wifi.WifiMetricsTestUtil.buildLinkProbeFailureReasonCount;
36 import static com.android.server.wifi.WifiMetricsTestUtil.buildLinkProbeFailureStaEvent;
37 import static com.android.server.wifi.WifiMetricsTestUtil.buildLinkProbeSuccessStaEvent;
38 import static com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent.TYPE_LINK_PROBE;
39 
40 import static org.junit.Assert.assertEquals;
41 import static org.junit.Assert.assertFalse;
42 import static org.junit.Assert.assertNotNull;
43 import static org.junit.Assert.assertNull;
44 import static org.junit.Assert.assertTrue;
45 import static org.junit.Assert.fail;
46 import static org.mockito.Mockito.any;
47 import static org.mockito.Mockito.anyBoolean;
48 import static org.mockito.Mockito.anyInt;
49 import static org.mockito.Mockito.anyString;
50 import static org.mockito.Mockito.atLeastOnce;
51 import static org.mockito.Mockito.doThrow;
52 import static org.mockito.Mockito.eq;
53 import static org.mockito.Mockito.mock;
54 import static org.mockito.Mockito.never;
55 import static org.mockito.Mockito.times;
56 import static org.mockito.Mockito.verify;
57 import static org.mockito.Mockito.when;
58 
59 import static java.lang.StrictMath.toIntExact;
60 
61 import android.app.ActivityManager;
62 import android.content.BroadcastReceiver;
63 import android.content.Context;
64 import android.content.Intent;
65 import android.net.MacAddress;
66 import android.net.wifi.EAPConstants;
67 import android.net.wifi.IOnWifiUsabilityStatsListener;
68 import android.net.wifi.ScanResult;
69 import android.net.wifi.SoftApCapability;
70 import android.net.wifi.SoftApConfiguration;
71 import android.net.wifi.SoftApInfo;
72 import android.net.wifi.SupplicantState;
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.WifiSsid;
79 import android.net.wifi.hotspot2.PasspointConfiguration;
80 import android.net.wifi.hotspot2.ProvisioningCallback;
81 import android.net.wifi.hotspot2.pps.Credential;
82 import android.net.wifi.nl80211.WifiNl80211Manager;
83 import android.os.Handler;
84 import android.os.IBinder;
85 import android.os.Message;
86 import android.os.PowerManager;
87 import android.os.RemoteException;
88 import android.os.test.TestLooper;
89 import android.telephony.TelephonyManager;
90 import android.util.Base64;
91 import android.util.Pair;
92 import android.util.SparseIntArray;
93 
94 import androidx.test.filters.MediumTest;
95 import androidx.test.filters.SmallTest;
96 
97 import com.android.dx.mockito.inline.extended.ExtendedMockito;
98 import com.android.server.wifi.WifiLinkLayerStats.PeerInfo;
99 import com.android.server.wifi.WifiLinkLayerStats.RadioStat;
100 import com.android.server.wifi.WifiLinkLayerStats.RateStat;
101 import com.android.server.wifi.aware.WifiAwareMetrics;
102 import com.android.server.wifi.hotspot2.NetworkDetail;
103 import com.android.server.wifi.hotspot2.PasspointManager;
104 import com.android.server.wifi.hotspot2.PasspointMatch;
105 import com.android.server.wifi.hotspot2.PasspointProvider;
106 import com.android.server.wifi.p2p.WifiP2pMetrics;
107 import com.android.server.wifi.proto.WifiStatsLog;
108 import com.android.server.wifi.proto.nano.WifiMetricsProto;
109 import com.android.server.wifi.proto.nano.WifiMetricsProto.ConnectToNetworkNotificationAndActionCount;
110 import com.android.server.wifi.proto.nano.WifiMetricsProto.DeviceMobilityStatePnoScanStats;
111 import com.android.server.wifi.proto.nano.WifiMetricsProto.HealthMonitorFailureStats;
112 import com.android.server.wifi.proto.nano.WifiMetricsProto.HealthMonitorMetrics;
113 import com.android.server.wifi.proto.nano.WifiMetricsProto.HistogramBucketInt32;
114 import com.android.server.wifi.proto.nano.WifiMetricsProto.Int32Count;
115 import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats;
116 import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.ExperimentProbeCounts;
117 import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.LinkProbeFailureReasonCount;
118 import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkDisableReason;
119 import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkSelectionExperimentDecisions;
120 import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProfileTypeCount;
121 import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProvisionStats;
122 import com.android.server.wifi.proto.nano.WifiMetricsProto.PnoScanMetrics;
123 import com.android.server.wifi.proto.nano.WifiMetricsProto.RadioStats;
124 import com.android.server.wifi.proto.nano.WifiMetricsProto.RateStats;
125 import com.android.server.wifi.proto.nano.WifiMetricsProto.SoftApConnectedClientsEvent;
126 import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent;
127 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent;
128 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiRadioUsage;
129 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats;
130 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStatsEntry;
131 import com.android.server.wifi.rtt.RttMetrics;
132 import com.android.server.wifi.util.InformationElementUtil;
133 import com.android.wifi.resources.R;
134 
135 import org.junit.After;
136 import org.junit.Before;
137 import org.junit.Test;
138 import org.mockito.ArgumentCaptor;
139 import org.mockito.Captor;
140 import org.mockito.Mock;
141 import org.mockito.MockitoAnnotations;
142 import org.mockito.MockitoSession;
143 import org.mockito.quality.Strictness;
144 
145 import java.io.ByteArrayOutputStream;
146 import java.io.FileDescriptor;
147 import java.io.PrintWriter;
148 import java.io.StringWriter;
149 import java.time.Duration;
150 import java.util.ArrayList;
151 import java.util.Arrays;
152 import java.util.BitSet;
153 import java.util.HashMap;
154 import java.util.HashSet;
155 import java.util.List;
156 import java.util.Map;
157 import java.util.Random;
158 import java.util.Set;
159 import java.util.regex.Matcher;
160 import java.util.regex.Pattern;
161 
162 /**
163  * Unit tests for {@link com.android.server.wifi.WifiMetrics}.
164  */
165 @SmallTest
166 public class WifiMetricsTest extends WifiBaseTest {
167 
168     WifiMetrics mWifiMetrics;
169     WifiMetricsProto.WifiLog mDecodedProto;
170     TestLooper mTestLooper;
171     Random mRandom = new Random();
172     private static final int TEST_NETWORK_ID = 42;
173     public static final String TEST_IFACE_NAME = "wlan0";
174     public static final String TEST_IFACE_NAME2 = "wlan1";
175     private MockitoSession mSession;
176     @Mock Context mContext;
177     MockResources mResources;
178     @Mock FrameworkFacade mFacade;
179     @Mock Clock mClock;
180     @Mock ScoringParams mScoringParams;
181     @Mock WifiConfigManager mWcm;
182     @Mock WifiBlocklistMonitor mWifiBlocklistMonitor;
183     @Mock PasspointManager mPpm;
184     @Mock WifiNetworkSelector mWns;
185     @Mock WifiPowerMetrics mWifiPowerMetrics;
186     @Mock WifiDataStall mWifiDataStall;
187     @Mock WifiChannelUtilization mWifiChannelUtilization;
188     @Mock WifiSettingsStore mWifiSettingsStore;
189     @Mock WifiHealthMonitor mWifiHealthMonitor;
190     @Mock IBinder mAppBinder;
191     @Mock IOnWifiUsabilityStatsListener mOnWifiUsabilityStatsListener;
192     @Mock WifiP2pMetrics mWifiP2pMetrics;
193     @Mock DppMetrics mDppMetrics;
194     @Mock WifiScoreCard mWifiScoreCard;
195     @Mock WifiScoreCard.PerNetwork mPerNetwork;
196     @Mock WifiScoreCard.NetworkConnectionStats mNetworkConnectionStats;
197     @Mock PowerManager mPowerManager;
198     @Mock WifiMonitor mWifiMonitor;
199     @Mock ActiveModeWarden mActiveModeWarden;
200     @Mock TelephonyManager mTelephonyManager;
201 
202     @Captor ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor;
203     @Captor ArgumentCaptor<ActiveModeWarden.ModeChangeCallback> mModeChangeCallbackArgumentCaptor;
204     @Captor ArgumentCaptor<Handler> mHandlerCaptor;
205 
206     @Before
setUp()207     public void setUp() throws Exception {
208         MockitoAnnotations.initMocks(this);
209         mDecodedProto = null;
210         when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 0);
211         mTestLooper = new TestLooper();
212         mResources = new MockResources();
213         when(mContext.getResources()).thenReturn(mResources);
214         when(mContext.getSystemService(PowerManager.class)).thenReturn(mPowerManager);
215         when(mPowerManager.isInteractive()).thenReturn(true);
216         when(mTelephonyManager.getNetworkCountryIso()).thenReturn("US");
217         when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
218         mWifiMetrics = new WifiMetrics(mContext, mFacade, mClock, mTestLooper.getLooper(),
219                 new WifiAwareMetrics(mClock), new RttMetrics(mClock), mWifiPowerMetrics,
220                 mWifiP2pMetrics, mDppMetrics, mWifiMonitor);
221         mWifiMetrics.setWifiConfigManager(mWcm);
222         mWifiMetrics.setWifiBlocklistMonitor(mWifiBlocklistMonitor);
223         mWifiMetrics.setPasspointManager(mPpm);
224         mWifiMetrics.setScoringParams(mScoringParams);
225         mWifiMetrics.setWifiNetworkSelector(mWns);
226         mWifiMetrics.setWifiDataStall(mWifiDataStall);
227         mWifiMetrics.setWifiChannelUtilization(mWifiChannelUtilization);
228         mWifiMetrics.setWifiSettingsStore(mWifiSettingsStore);
229         mWifiMetrics.setWifiHealthMonitor(mWifiHealthMonitor);
230         mWifiMetrics.setWifiScoreCard(mWifiScoreCard);
231         when(mOnWifiUsabilityStatsListener.asBinder()).thenReturn(mAppBinder);
232         when(mWifiScoreCard.lookupNetwork(anyString())).thenReturn(mPerNetwork);
233         when(mPerNetwork.getRecentStats()).thenReturn(mNetworkConnectionStats);
234         verify(mContext, atLeastOnce()).registerReceiver(
235                 mBroadcastReceiverCaptor.capture(), any(), any(), any());
236 
237         mWifiMetrics.registerForWifiMonitorEvents("wlan0");
238         verify(mWifiMonitor, atLeastOnce())
239                 .registerHandler(eq("wlan0"), anyInt(), mHandlerCaptor.capture());
240 
241         mWifiMetrics.setActiveModeWarden(mActiveModeWarden);
242         verify(mActiveModeWarden).registerModeChangeCallback(
243                 mModeChangeCallbackArgumentCaptor.capture());
244         ActiveModeWarden.ModeChangeCallback modeChangeCallback =
245                         mModeChangeCallbackArgumentCaptor.getValue();
246         ConcreteClientModeManager concreteClientModeManager = mock(ConcreteClientModeManager.class);
247         when(concreteClientModeManager.getInterfaceName()).thenReturn(TEST_IFACE_NAME);
248         when(concreteClientModeManager.getRole()).thenReturn(ActiveModeManager.ROLE_CLIENT_PRIMARY);
249         modeChangeCallback.onActiveModeManagerAdded(concreteClientModeManager);
250 
251         mSession = ExtendedMockito.mockitoSession()
252                 .strictness(Strictness.LENIENT)
253                 .mockStatic(WifiStatsLog.class)
254                 .startMocking();
255     }
256 
257     @After
tearDown()258     public void tearDown() {
259         mSession.finishMocking();
260     }
261 
262     /**
263      * Test that startConnectionEvent and endConnectionEvent can be called repeatedly and out of
264      * order. Only tests no exception occurs. Creates 3 ConnectionEvents.
265      */
266     @Test
startAndEndConnectionEventSucceeds()267     public void startAndEndConnectionEventSucceeds() throws Exception {
268         //Start and end Connection event
269         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, null,
270                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
271         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
272                 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
273                 WifiMetricsProto.ConnectionEvent.HLF_DHCP,
274                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
275         //end Connection event without starting one
276         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
277                 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
278                 WifiMetricsProto.ConnectionEvent.HLF_DHCP,
279                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
280         //start two ConnectionEvents in a row
281         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, null,
282                 "BLUE", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
283         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, null,
284                 "GREEN", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
285     }
286 
287     private static final long TEST_RECORD_DURATION_SEC = 12 * 60 * 60;
288     private static final long TEST_RECORD_DURATION_MILLIS = TEST_RECORD_DURATION_SEC * 1000;
289     /**
290      * Simulate how dumpsys gets the proto from mWifiMetrics, filter the proto bytes out and
291      * deserialize them into mDecodedProto
292      */
dumpProtoAndDeserialize()293     private void dumpProtoAndDeserialize() throws Exception {
294         ByteArrayOutputStream stream = new ByteArrayOutputStream();
295         PrintWriter writer = new PrintWriter(stream);
296 
297         when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_RECORD_DURATION_MILLIS);
298         //Test proto dump, by passing in proto arg option
299         String[] args = {WifiMetrics.PROTO_DUMP_ARG};
300         mWifiMetrics.dump(null, writer, args);
301         writer.flush();
302         Pattern pattern = Pattern.compile(
303                 "(?<=WifiMetrics:\\n)([\\s\\S]*)(?=EndWifiMetrics)");
304         Matcher matcher = pattern.matcher(stream.toString());
305         assertTrue("Proto Byte string found in WifiMetrics.dump():\n" + stream.toString(),
306                 matcher.find());
307         String protoByteString = matcher.group(1);
308         byte[] protoBytes = Base64.decode(protoByteString, Base64.DEFAULT);
309         mDecodedProto = WifiMetricsProto.WifiLog.parseFrom(protoBytes);
310     }
311 
312     /*, LOCAL_GEN, DEAUTH_REASON*
313      * Gets the 'clean dump' proto bytes from mWifiMetrics & deserializes it into
314      * mDecodedProto
315      */
cleanDumpProtoAndDeserialize()316     public void cleanDumpProtoAndDeserialize() throws Exception {
317         ByteArrayOutputStream stream = new ByteArrayOutputStream();
318         PrintWriter writer = new PrintWriter(stream);
319 
320         when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_RECORD_DURATION_MILLIS);
321         //Test proto dump, by passing in proto arg option
322         String[] args = {WifiMetrics.PROTO_DUMP_ARG, WifiMetrics.CLEAN_DUMP_ARG};
323         mWifiMetrics.dump(null, writer, args);
324         writer.flush();
325         String protoByteString = stream.toString();
326         byte[] protoBytes = Base64.decode(protoByteString, Base64.DEFAULT);
327         mDecodedProto = WifiMetricsProto.WifiLog.parseFrom(protoBytes);
328     }
329 
330     /** Verifies that dump() includes the expected header */
331     @Test
stateDumpIncludesHeader()332     public void stateDumpIncludesHeader() throws Exception {
333         assertStringContains(getStateDump(), "WifiMetrics");
334     }
335 
336     /** Verifies that dump() includes correct alert count when there are no alerts. */
337     @Test
stateDumpAlertCountIsCorrectWithNoAlerts()338     public void stateDumpAlertCountIsCorrectWithNoAlerts() throws Exception {
339         assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=()");
340     }
341 
342     /** Verifies that dump() includes correct alert count when there is one alert. */
343     @Test
stateDumpAlertCountIsCorrectWithOneAlert()344     public void stateDumpAlertCountIsCorrectWithOneAlert() throws Exception {
345         mWifiMetrics.logFirmwareAlert(TEST_IFACE_NAME, 1);
346         assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=(1,1)");
347     }
348 
349     /** Verifies that dump() includes correct alert count when there are multiple alerts. */
350     @Test
stateDumpAlertCountIsCorrectWithMultipleAlerts()351     public void stateDumpAlertCountIsCorrectWithMultipleAlerts() throws Exception {
352         mWifiMetrics.logFirmwareAlert(TEST_IFACE_NAME, 1);
353         mWifiMetrics.logFirmwareAlert(TEST_IFACE_NAME, 1);
354         mWifiMetrics.logFirmwareAlert(TEST_IFACE_NAME, 16);
355         assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=(1,2),(16,1)");
356     }
357 
358     @Test
testDumpProtoAndDeserialize()359     public void testDumpProtoAndDeserialize() throws Exception {
360         setAndIncrementMetrics();
361         dumpProtoAndDeserialize();
362         verify(mWifiP2pMetrics).consolidateProto();
363         assertDeserializedMetricsCorrect();
364     }
365 
366     private static final int NUM_OPEN_NETWORKS = 2;
367     private static final int NUM_LEGACY_PERSONAL_NETWORKS = 3;
368     private static final int NUM_LEGACY_ENTERPRISE_NETWORKS = 5;
369     private static final int NUM_ENHANCED_OPEN_NETWORKS = 1;
370     private static final int NUM_WPA3_PERSONAL_NETWORKS = 4;
371     private static final int NUM_WPA3_ENTERPRISE_NETWORKS = 6;
372     private static final int NUM_WAPI_PERSONAL_NETWORKS = 4;
373     private static final int NUM_WAPI_ENTERPRISE_NETWORKS = 6;
374     private static final int NUM_SAVED_NETWORKS = NUM_OPEN_NETWORKS + NUM_LEGACY_PERSONAL_NETWORKS
375             + NUM_LEGACY_ENTERPRISE_NETWORKS + NUM_ENHANCED_OPEN_NETWORKS
376             + NUM_WPA3_PERSONAL_NETWORKS + NUM_WPA3_ENTERPRISE_NETWORKS
377             + NUM_WAPI_PERSONAL_NETWORKS + NUM_WAPI_ENTERPRISE_NETWORKS;
378     private static final int NUM_HIDDEN_NETWORKS = NUM_OPEN_NETWORKS;
379     private static final int NUM_PASSPOINT_NETWORKS = NUM_LEGACY_ENTERPRISE_NETWORKS;
380     private static final int NUM_NETWORKS_ADDED_BY_USER = 0;
381     private static final int NUM_NETWORKS_ADDED_BY_APPS = NUM_SAVED_NETWORKS
382             - NUM_NETWORKS_ADDED_BY_USER;
383     private static final boolean TEST_VAL_IS_LOCATION_ENABLED = true;
384     private static final boolean IS_SCANNING_ALWAYS_ENABLED = true;
385     private static final boolean IS_VERBOSE_LOGGING_ENABLED = true;
386     private static final boolean IS_NON_PERSISTENT_MAC_RANDOMIZATION_FORCE_ENABLED = true;
387     private static final boolean IS_WIFI_WAKE_ENABLED = true;
388     private static final int NUM_EMPTY_SCAN_RESULTS = 19;
389     private static final int NUM_NON_EMPTY_SCAN_RESULTS = 23;
390     private static final int NUM_SCAN_UNKNOWN = 1;
391     private static final int NUM_SCAN_SUCCESS = 2;
392     private static final int NUM_SCAN_FAILURE_INTERRUPTED = 3;
393     private static final int NUM_SCAN_FAILURE_INVALID_CONFIGURATION = 5;
394     private static final int NUM_WIFI_UNKNOWN_SCREEN_OFF = 3;
395     private static final int NUM_WIFI_UNKNOWN_SCREEN_ON = 5;
396     private static final int NUM_WIFI_ASSOCIATED_SCREEN_OFF = 7;
397     private static final int NUM_WIFI_ASSOCIATED_SCREEN_ON = 11;
398     private static final int NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD = 11;
399     private static final int NUM_CONNECTIVITY_WATCHDOG_PNO_BAD = 12;
400     private static final int NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD = 13;
401     private static final int NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD = 14;
402     private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS = 1;
403     private static final int NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL = 2;
404     private static final int NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL = 3;
405     private static final int NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL = 4;
406     private static final int NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL = 5;
407     private static final int NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL = 6;
408     private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION = 7;
409     private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION = 8;
410     private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP = 9;
411     private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER = 10;
412     private static final int NUM_LAST_RESORT_WATCHDOG_SUCCESSES = 5;
413     private static final int WATCHDOG_TOTAL_CONNECTION_FAILURE_COUNT_AFTER_TRIGGER = 6;
414     private static final int RSSI_POLL_FREQUENCY = 5150;
415     private static final int NUM_RSSI_LEVELS_TO_INCREMENT = 20;
416     private static final int NUM_OPEN_NETWORK_SCAN_RESULTS = 1;
417     private static final int NUM_LEGACY_PERSONAL_NETWORK_SCAN_RESULTS = 4;
418     private static final int NUM_ENHANCED_OPEN_NETWORK_SCAN_RESULTS = 1;
419     private static final int NUM_WPA3_PERSONAL_NETWORK_SCAN_RESULTS = 2;
420     private static final int NUM_WPA3_ENTERPRISE_NETWORK_SCAN_RESULTS = 3;
421     private static final int NUM_WAPI_PERSONAL_NETWORK_SCAN_RESULTS = 1;
422     private static final int NUM_WAPI_ENTERPRISE_NETWORK_SCAN_RESULTS = 2;
423     private static final int NUM_HIDDEN_NETWORK_SCAN_RESULTS = 1;
424     private static final int NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS = 1;
425     private static final int NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS = 2;
426     private static final int NUM_HOTSPOT2_R3_NETWORK_SCAN_RESULTS = 2;
427     private static final int NUM_LEGACY_ENTERPRISE_NETWORK_SCAN_RESULTS =
428             NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS + NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS
429             + NUM_HOTSPOT2_R3_NETWORK_SCAN_RESULTS;
430     private static final int NUM_SCANS = 5;
431     private static final int NUM_CONNECTIVITY_ONESHOT_SCAN_EVENT = 4;
432     private static final int NUM_EXTERNAL_APP_ONESHOT_SCAN_REQUESTS = 15;
433     private static final int NUM_EXTERNAL_FOREGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED = 10;
434     private static final int NUM_EXTERNAL_BACKGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED = 16;
435     // Look at buildMockScanDetailList, this number needs to match the mocked results
436     private static final int NUM_TOTAL_SCAN_RESULTS = NUM_OPEN_NETWORK_SCAN_RESULTS
437             + NUM_LEGACY_PERSONAL_NETWORK_SCAN_RESULTS + NUM_LEGACY_ENTERPRISE_NETWORK_SCAN_RESULTS
438             + NUM_ENHANCED_OPEN_NETWORK_SCAN_RESULTS + NUM_WPA3_PERSONAL_NETWORK_SCAN_RESULTS
439             + NUM_WPA3_ENTERPRISE_NETWORK_SCAN_RESULTS + NUM_WAPI_PERSONAL_NETWORK_SCAN_RESULTS
440             + NUM_WAPI_ENTERPRISE_NETWORK_SCAN_RESULTS;
441     private static final int MIN_RSSI_LEVEL = -127;
442     private static final int MAX_RSSI_LEVEL = 0;
443     private static final int WIFI_SCORE_RANGE_MIN = 0;
444     private static final int NUM_WIFI_SCORES_TO_INCREMENT = 20;
445     private static final int WIFI_SCORE_RANGE_MAX = 60;
446     private static final int NUM_OUT_OF_BOUND_ENTRIES = 10;
447     private static final int MAX_NUM_SOFTAP_RETURN_CODES = 3;
448     private static final int NUM_SOFTAP_START_SUCCESS = 3;
449     private static final int NUM_SOFTAP_FAILED_GENERAL_ERROR = 2;
450     private static final int NUM_SOFTAP_FAILED_NO_CHANNEL = 1;
451     private static final int NUM_HAL_CRASHES = 11;
452     private static final int NUM_WIFICOND_CRASHES = 12;
453     private static final int NUM_SUPPLICANT_CRASHES = 23;
454     private static final int NUM_HOSTAPD_CRASHES = 7;
455     private static final int NUM_WIFI_ON_FAILURE_DUE_TO_HAL = 13;
456     private static final int NUM_WIFI_ON_FAILURE_DUE_TO_WIFICOND = 14;
457     private static final int NUM_WIFI_ON_FAILURE_DUE_TO_SUPPLICANT = 20;
458     private static final int NUM_SOFTAP_ON_FAILURE_DUE_TO_HAL = 23;
459     private static final int NUM_SOFTAP_ON_FAILURE_DUE_TO_WIFICOND = 19;
460     private static final int NUM_SOFTAP_ON_FAILURE_DUE_TO_HOSTAPD = 31;
461     private static final int NUM_SOFTAP_INTERFACE_DOWN = 65;
462     private static final int NUM_CLIENT_INTERFACE_DOWN = 12;
463     private static final int NUM_PASSPOINT_PROVIDERS = 7;
464     private static final int NUM_PASSPOINT_PROVIDER_INSTALLATION = 5;
465     private static final int NUM_PASSPOINT_PROVIDER_INSTALL_SUCCESS = 4;
466     private static final int NUM_PASSPOINT_PROVIDER_UNINSTALLATION = 3;
467     private static final int NUM_PASSPOINT_PROVIDER_UNINSTALL_SUCCESS = 2;
468     private static final int NUM_PASSPOINT_PROVIDERS_SUCCESSFULLY_CONNECTED = 1;
469     private static final int NUM_PASSPOINT_PROVIDERS_WITH_NO_ROOT_CA = 2;
470     private static final int NUM_PASSPOINT_PROVIDERS_WITH_SELF_SIGNED_ROOT_CA = 3;
471     private static final int NUM_PASSPOINT_PROVIDERS_WITH_EXPIRATION_DATE = 4;
472     private static final int NUM_EAP_SIM_TYPE = 1;
473     private static final int NUM_EAP_TTLS_TYPE = 2;
474     private static final int NUM_EAP_TLS_TYPE = 3;
475     private static final int NUM_EAP_AKA_TYPE = 4;
476     private static final int NUM_EAP_AKA_PRIME_TYPE = 5;
477     private static final SparseIntArray SAVED_PASSPOINT_PROVIDERS_TYPE = new SparseIntArray();
478     static {
SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_SIM, NUM_EAP_SIM_TYPE)479         SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_SIM, NUM_EAP_SIM_TYPE);
SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_TTLS, NUM_EAP_TTLS_TYPE)480         SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_TTLS, NUM_EAP_TTLS_TYPE);
SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_TLS, NUM_EAP_TLS_TYPE)481         SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_TLS, NUM_EAP_TLS_TYPE);
SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_AKA, NUM_EAP_AKA_TYPE)482         SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_AKA, NUM_EAP_AKA_TYPE);
SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_AKA_PRIME, NUM_EAP_AKA_PRIME_TYPE)483         SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_AKA_PRIME, NUM_EAP_AKA_PRIME_TYPE);
484     }
485 
486     private static final int NUM_PARTIAL_SCAN_RESULTS = 73;
487     private static final int NUM_PNO_SCAN_ATTEMPTS = 20;
488     private static final int NUM_PNO_SCAN_FAILED = 5;
489     private static final int NUM_PNO_FOUND_NETWORK_EVENTS = 10;
490     private static final int NUM_RADIO_MODE_CHANGE_TO_MCC = 4;
491     private static final int NUM_RADIO_MODE_CHANGE_TO_SCC = 13;
492     private static final int NUM_RADIO_MODE_CHANGE_TO_SBS = 19;
493     private static final int NUM_RADIO_MODE_CHANGE_TO_DBS = 34;
494     private static final int NUM_SOFTAP_USER_BAND_PREFERENCE_UNSATISFIED = 14;
495     private static final long NUM_WATCHDOG_SUCCESS_DURATION_MS = 65;
496     private static final long WIFI_POWER_METRICS_LOGGING_DURATION = 280;
497     private static final long WIFI_POWER_METRICS_SCAN_TIME = 33;
498     private static final boolean WIFI_IS_UNUSABLE_EVENT_LOGGING_SETTING = true;
499     private static final boolean LINK_SPEED_COUNTS_LOGGING_SETTING = true;
500     private static final int DATA_STALL_MIN_TX_BAD_SETTING = 5;
501     private static final int DATA_STALL_MIN_TX_SUCCESS_WITHOUT_RX_SETTING = 75;
502     private static final int NUM_ONESHOT_SCAN_REQUESTS_WITH_DFS_CHANNELS = 4;
503     private static final int NUM_ADD_OR_UPDATE_NETWORK_CALLS = 5;
504     private static final int NUM_ENABLE_NETWORK_CALLS = 6;
505     private static final long NUM_IP_RENEWAL_FAILURE = 7;
506     private static final int NUM_NETWORK_ABNORMAL_ASSOC_REJECTION = 2;
507     private static final int NUM_NETWORK_ABNORMAL_CONNECTION_FAILURE_DISCONNECTION = 5;
508     private static final int NUM_NETWORK_SUFFICIENT_RECENT_STATS_ONLY = 4;
509     private static final int NUM_NETWORK_SUFFICIENT_RECENT_PREV_STATS = 5;
510     private static final int NUM_BSSID_SELECTION_DIFFERENT_BETWEEN_FRAMEWORK_FIRMWARE = 3;
511     private static final long WIFI_MAINLINE_MODULE_VERSION = 123456L;
512 
513     /** Number of notifications per "Connect to Network" notification type. */
514     private static final int[] NUM_CONNECT_TO_NETWORK_NOTIFICATIONS = {0, 10, 20, 30, 40};
515     /** Number of notifications per "Connect to Network notification type and action type. */
516     private static final int[][] NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS = {
517             {0, 1, 2, 3, 4},
518             {10, 11, 12, 13, 14},
519             {20, 21, 22, 23, 24},
520             {30, 31, 32, 33, 34},
521             {40, 41, 42, 43, 44}};
522     private static final int SIZE_OPEN_NETWORK_RECOMMENDER_BLOCKLIST = 10;
523     private static final boolean IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = true;
524     private static final int NUM_OPEN_NETWORK_CONNECT_MESSAGE_FAILED_TO_SEND = 5;
525     private static final int NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES = 8;
526     private static final String OPEN_NET_NOTIFIER_TAG = OpenNetworkNotifier.TAG;
527 
528     private static final int NUM_SOFT_AP_EVENT_ENTRIES = 3;
529     private static final int NUM_SOFT_AP_EVENT_ENTRIES_FOR_BRIDGED_AP = 4;
530     private static final int NUM_SOFT_AP_ASSOCIATED_STATIONS = 3;
531     private static final int SOFT_AP_CHANNEL_FREQUENCY_2G = 2437;
532     private static final int SOFT_AP_CHANNEL_BANDWIDTH_2G =
533             SoftApConnectedClientsEvent.BANDWIDTH_20;
534     private static final int SOFT_AP_GENERATION_2G = ScanResult.WIFI_STANDARD_11N;
535     private static final int SOFT_AP_CHANNEL_FREQUENCY_5G = 5180;
536     private static final int SOFT_AP_CHANNEL_BANDWIDTH_5G =
537             SoftApConnectedClientsEvent.BANDWIDTH_80;
538     private static final int SOFT_AP_GENERATION_5G = ScanResult.WIFI_STANDARD_11AC;
539     private static final int SOFT_AP_MAX_CLIENT_SETTING = 10;
540     private static final int SOFT_AP_MAX_CLIENT_CAPABILITY = 16;
541     private static final long SOFT_AP_SHUTDOWN_TIMEOUT_SETTING = 10_000;
542     private static final long SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING = 600_000;
543     private static final boolean SOFT_AP_CLIENT_CONTROL_ENABLE = true;
544     private static final boolean IS_MAC_RANDOMIZATION_ON = true;
545     private static final int NUM_LINK_SPEED_LEVELS_TO_INCREMENT = 30;
546     private static final int TEST_RSSI_LEVEL = -80;
547     private static final int MAX_SUPPORTED_TX_LINK_SPEED_MBPS = 144;
548     private static final int MAX_SUPPORTED_RX_LINK_SPEED_MBPS = 190;
549 
550     private static final long NUM_MBO_SUPPORTED_NETWORKS_SCAN_RESULTS = 4;
551     private static final long NUM_MBO_CELL_DATA_AWARE_NETWORKS_SCAN_RESULTS = 2;
552     private static final long NUM_OCE_SUPPORTED_NETWORKS_SCAN_RESULTS = 2;
553     private static final long NUM_FILS_SUPPORTED_NETWORKS_SCAN_RESULTS = 2;
554     private static final long NUM_11AX_NETWORKS_SCAN_RESULTS = 3;
555     private static final long NUM_6G_NETWORKS_SCAN_RESULTS = 2;
556     private static final long NUM_6G_PSC_NETWORKS_SCAN_RESULTS = 1;
557     private static final long NUM_BSSID_FILTERED_DUE_TO_MBO_ASSOC_DISALLOW_IND = 3;
558     private static final long NUM_CONNECT_TO_MBO_SUPPORTED_NETWORKS = 4;
559     private static final long NUM_CONNECT_TO_OCE_SUPPORTED_NETWORKS = 3;
560     private static final long NUM_STEERING_REQUEST = 3;
561     private static final long NUM_FORCE_SCAN_DUE_TO_STEERING_REQUEST = 2;
562     private static final long NUM_MBO_CELLULAR_SWITCH_REQUEST = 3;
563     private static final long NUM_STEERING_REQUEST_INCLUDING_MBO_ASSOC_RETRY_DELAY = 3;
564     private static final long NUM_CONNECT_REQUEST_WITH_FILS_AKM = 4;
565     private static final long NUM_L2_CONNECTION_THROUGH_FILS_AUTHENTICATION = 3;
566 
567     private static final int FEATURE_MBO = 1 << 0;
568     private static final int FEATURE_MBO_CELL_DATA_AWARE = 1 << 1;
569     private static final int FEATURE_OCE = 1 << 2;
570     private static final int FEATURE_11AX = 1 << 3;
571     private static final int FEATURE_6G = 1 << 4;
572     private static final int FEATURE_6G_PSC = 1 << 5;
573 
buildMockScanDetail(boolean hidden, NetworkDetail.HSRelease hSRelease, String capabilities, int supportedFeatures)574     private ScanDetail buildMockScanDetail(boolean hidden, NetworkDetail.HSRelease hSRelease,
575             String capabilities, int supportedFeatures) {
576         ScanDetail mockScanDetail = mock(ScanDetail.class);
577         NetworkDetail mockNetworkDetail = mock(NetworkDetail.class);
578         ScanResult mockScanResult = mock(ScanResult.class);
579         when(mockScanDetail.getNetworkDetail()).thenReturn(mockNetworkDetail);
580         when(mockScanDetail.getScanResult()).thenReturn(mockScanResult);
581         when(mockNetworkDetail.isHiddenBeaconFrame()).thenReturn(hidden);
582         when(mockNetworkDetail.getHSRelease()).thenReturn(hSRelease);
583         mockScanResult.capabilities = capabilities;
584         if ((supportedFeatures & FEATURE_MBO) != 0) {
585             when(mockNetworkDetail.isMboSupported()).thenReturn(true);
586         }
587         if ((supportedFeatures & FEATURE_MBO_CELL_DATA_AWARE) != 0) {
588             when(mockNetworkDetail.isMboCellularDataAware()).thenReturn(true);
589         }
590         if ((supportedFeatures & FEATURE_OCE) != 0) {
591             when(mockNetworkDetail.isOceSupported()).thenReturn(true);
592         }
593         if ((supportedFeatures & FEATURE_11AX) != 0) {
594             when(mockNetworkDetail.getWifiMode())
595                     .thenReturn(InformationElementUtil.WifiMode.MODE_11AX);
596         }
597         if ((supportedFeatures & FEATURE_6G) != 0) {
598             when(mockScanResult.is6GHz()).thenReturn(true);
599         }
600         if ((supportedFeatures & FEATURE_6G_PSC) != 0) {
601             when(mockScanResult.is6GhzPsc()).thenReturn(true);
602         }
603         return mockScanDetail;
604     }
605 
buildMockScanDetail(String ssid, String bssid, boolean isOpen, boolean isSaved, boolean isProvider, boolean isWeakRssi)606     private ScanDetail buildMockScanDetail(String ssid, String bssid, boolean isOpen,
607             boolean isSaved, boolean isProvider, boolean isWeakRssi) {
608         ScanDetail mockScanDetail = mock(ScanDetail.class);
609         NetworkDetail mockNetworkDetail = mock(NetworkDetail.class);
610         ScanResult scanResult = new ScanResult();
611         scanResult.SSID = ssid;
612         scanResult.setWifiSsid(WifiSsid.fromUtf8Text(ssid));
613         scanResult.BSSID = bssid;
614         when(mockScanDetail.getNetworkDetail()).thenReturn(mockNetworkDetail);
615         when(mockScanDetail.getScanResult()).thenReturn(scanResult);
616         when(mWns.isSignalTooWeak(eq(scanResult))).thenReturn(isWeakRssi);
617         scanResult.capabilities = isOpen ? "" : "PSK";
618         if (isSaved) {
619             when(mWcm.getSavedNetworkForScanDetail(eq(mockScanDetail)))
620                     .thenReturn(mock(WifiConfiguration.class));
621         }
622         if (isProvider) {
623             PasspointProvider provider = mock(PasspointProvider.class);
624             List<Pair<PasspointProvider, PasspointMatch>> matchedProviders = new ArrayList<>();
625             matchedProviders.add(Pair.create(provider, null));
626             when(mockNetworkDetail.isInterworking()).thenReturn(true);
627             when(mPpm.matchProvider(eq(scanResult), eq(false))).thenReturn(matchedProviders);
628         }
629         return mockScanDetail;
630     }
631 
buildMockScanDetailPasspoint(String ssid, String bssid, long hessid, int anqpDomainId, NetworkDetail.HSRelease hsRelease, boolean weakSignal)632     private ScanDetail buildMockScanDetailPasspoint(String ssid, String bssid, long hessid,
633             int anqpDomainId, NetworkDetail.HSRelease hsRelease, boolean weakSignal) {
634         ScanDetail mockScanDetail = mock(ScanDetail.class);
635         NetworkDetail mockNetworkDetail = mock(NetworkDetail.class);
636         ScanResult scanResult = new ScanResult();
637         scanResult.SSID = ssid;
638         scanResult.setWifiSsid(WifiSsid.fromUtf8Text(ssid));
639         scanResult.BSSID = bssid;
640         scanResult.hessid = hessid;
641         scanResult.capabilities = "PSK";
642         when(mockScanDetail.getNetworkDetail()).thenReturn(mockNetworkDetail);
643         when(mockScanDetail.getScanResult()).thenReturn(scanResult);
644         when(mockNetworkDetail.getHSRelease()).thenReturn(hsRelease);
645         when(mockNetworkDetail.getAnqpDomainID()).thenReturn(anqpDomainId);
646         when(mockNetworkDetail.isInterworking()).thenReturn(true);
647         when(mWns.isSignalTooWeak(eq(scanResult))).thenReturn(weakSignal);
648         return mockScanDetail;
649     }
650 
buildMockScanDetailList()651     private List<ScanDetail> buildMockScanDetailList() {
652         List<ScanDetail> mockScanDetails = new ArrayList<ScanDetail>();
653         mockScanDetails.add(buildMockScanDetail(true, null, "[ESS]", 0));
654         mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-PSK-CCMP][ESS]", FEATURE_11AX));
655         mockScanDetails.add(buildMockScanDetail(false, null, "[WPA-PSK-CCMP]", 0));
656         mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-SAE-CCMP]", FEATURE_MBO));
657         mockScanDetails.add(buildMockScanDetail(false, null, "[WPA-PSK-CCMP]",
658                 FEATURE_11AX | FEATURE_6G));
659         mockScanDetails.add(buildMockScanDetail(false, null, "[WEP]", 0));
660         mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-SAE-CCMP]",
661                 FEATURE_MBO | FEATURE_MBO_CELL_DATA_AWARE));
662         mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-OWE-CCMP]",
663                 FEATURE_MBO | FEATURE_MBO_CELL_DATA_AWARE | FEATURE_OCE));
664         mockScanDetails.add(buildMockScanDetail(false, null, "[RSN-SUITE_B_192][MFPR]",
665                 FEATURE_11AX | FEATURE_6G | FEATURE_6G_PSC));
666         // WPA3 Enterprise transition network
667         mockScanDetails.add(buildMockScanDetail(false, null,
668                 "[RSN-EAP/SHA1+EAP/SHA256-CCMP][MFPC]", 0));
669         // WPA3 Enterprise only network
670         mockScanDetails.add(buildMockScanDetail(false, null,
671                 "[RSN-EAP/SHA256-CCMP][MFPR][MFPC]", 0));
672         mockScanDetails.add(buildMockScanDetail(false, null, "[WAPI-WAPI-PSK-SMS4-SMS4]", 0));
673         mockScanDetails.add(buildMockScanDetail(false, null, "[WAPI-WAPI-CERT-SMS4-SMS4]", 0));
674         mockScanDetails.add(buildMockScanDetail(false, null, "[WAPI-WAPI-CERT-SMS4-SMS4]", 0));
675         // Number of scans of R2 networks must be equal to NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS
676         mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R2,
677                 "[WPA-EAP/SHA1-CCMP+EAP-FILS-SHA256-CCMP]", FEATURE_MBO | FEATURE_OCE));
678         mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R2,
679                 "[WPA2-EAP/SHA1+FT/EAP-CCMP+EAP-FILS-SHA256-CCMP]", 0));
680         // Number of scans of R1 networks must be equal to NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS
681         mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R1,
682                 "[WPA-EAP/SHA1-CCMP]", 0));
683         // Number of scans of R3 networks must be equal to NUM_HOTSPOT2_R3_NETWORK_SCAN_RESULTS
684         mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R3,
685                 "[WPA-EAP/SHA1-CCMP]", 0));
686         // WPA2 Enterprise network with MFPR and MFPC
687         mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R3,
688                 "[WPA-EAP/SHA1-CCMP][MFPR][MFPC]", 0));
689         return mockScanDetails;
690     }
691 
buildSavedNetworkList()692     private List<WifiConfiguration> buildSavedNetworkList() {
693         List<WifiConfiguration> testSavedNetworks = new ArrayList<WifiConfiguration>();
694         for (int i = 0; i < NUM_OPEN_NETWORKS; i++) {
695             testSavedNetworks.add(WifiConfigurationTestUtil.createOpenHiddenNetwork());
696         }
697         for (int i = 0; i < NUM_LEGACY_PERSONAL_NETWORKS; i++) {
698             testSavedNetworks.add(WifiConfigurationTestUtil.createPskNetwork());
699         }
700         for (int i = 0; i < NUM_LEGACY_ENTERPRISE_NETWORKS; i++) {
701             // Passpoint networks are counted in both Passpoint and Enterprise counters
702             testSavedNetworks.add(WifiConfigurationTestUtil.createPasspointNetwork());
703         }
704         for (int i = 0; i < NUM_ENHANCED_OPEN_NETWORKS; i++) {
705             testSavedNetworks.add(WifiConfigurationTestUtil.createOweNetwork());
706         }
707         for (int i = 0; i < NUM_WPA3_PERSONAL_NETWORKS; i++) {
708             testSavedNetworks.add(WifiConfigurationTestUtil.createSaeNetwork());
709         }
710         for (int i = 0; i < NUM_WPA3_ENTERPRISE_NETWORKS; i++) {
711             testSavedNetworks.add(WifiConfigurationTestUtil.createEapSuiteBNetwork());
712         }
713         for (int i = 0; i < NUM_WAPI_PERSONAL_NETWORKS; i++) {
714             testSavedNetworks.add(WifiConfigurationTestUtil.createWapiPskNetwork());
715         }
716         for (int i = 0; i < NUM_WAPI_ENTERPRISE_NETWORKS; i++) {
717             testSavedNetworks.add(WifiConfigurationTestUtil.createWapiCertNetwork());
718         }
719         testSavedNetworks.get(0).macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
720         return testSavedNetworks;
721     }
722 
createMockProvider(int eapType, boolean validateForR2)723     private PasspointProvider createMockProvider(int eapType, boolean validateForR2) {
724         PasspointProvider provider = mock(PasspointProvider.class);
725         PasspointConfiguration config = mock(PasspointConfiguration.class);
726         Credential credential = new Credential();
727 
728         switch (eapType) {
729             case EAPConstants.EAP_TLS:
730                 credential.setCertCredential(new Credential.CertificateCredential());
731                 break;
732             case EAPConstants.EAP_TTLS:
733                 credential.setUserCredential(new Credential.UserCredential());
734                 break;
735             case EAPConstants.EAP_AKA:
736             case EAPConstants.EAP_AKA_PRIME:
737             case EAPConstants.EAP_SIM:
738                 Credential.SimCredential simCredential = new Credential.SimCredential();
739                 simCredential.setEapType(eapType);
740                 credential.setSimCredential(simCredential);
741                 break;
742         }
743         when(provider.getConfig()).thenReturn(config);
744         when(config.getCredential()).thenReturn(credential);
745         when(config.validateForR2()).thenReturn(validateForR2);
746         return provider;
747     }
748 
749     /**
750      * Set simple metrics, increment others
751      */
setAndIncrementMetrics()752     public void setAndIncrementMetrics() throws Exception {
753         Map<String, PasspointProvider> providers = new HashMap<>();
754         mWifiMetrics.updateSavedNetworks(buildSavedNetworkList());
755         mWifiMetrics.updateSavedPasspointProfiles(NUM_PASSPOINT_PROVIDERS,
756                 NUM_PASSPOINT_PROVIDERS_SUCCESSFULLY_CONNECTED);
757         for (int i = 0; i < SAVED_PASSPOINT_PROVIDERS_TYPE.size(); i++) {
758             int eapType = SAVED_PASSPOINT_PROVIDERS_TYPE.keyAt(i);
759             int count = SAVED_PASSPOINT_PROVIDERS_TYPE.valueAt(i);
760             for (int j = 0; j < count; j++) {
761                 providers.put(Integer.toString(eapType) + j, createMockProvider(eapType, false));
762             }
763             for (int j = count; j < count * 2; j++) {
764                 providers.put(Integer.toString(eapType) + j, createMockProvider(eapType, true));
765             }
766         }
767         mWifiMetrics.updateSavedPasspointProfilesInfo(providers);
768 
769         mWifiMetrics.setIsLocationEnabled(TEST_VAL_IS_LOCATION_ENABLED);
770         mWifiMetrics.setIsScanningAlwaysEnabled(IS_SCANNING_ALWAYS_ENABLED);
771         mWifiMetrics.setVerboseLoggingEnabled(IS_VERBOSE_LOGGING_ENABLED);
772         mWifiMetrics.setNonPersistentMacRandomizationForceEnabled(
773                 IS_NON_PERSISTENT_MAC_RANDOMIZATION_FORCE_ENABLED);
774         mWifiMetrics.setWifiWakeEnabled(IS_WIFI_WAKE_ENABLED);
775 
776         for (int i = 0; i < NUM_EMPTY_SCAN_RESULTS; i++) {
777             mWifiMetrics.incrementEmptyScanResultCount();
778         }
779         for (int i = 0; i < NUM_NON_EMPTY_SCAN_RESULTS; i++) {
780             mWifiMetrics.incrementNonEmptyScanResultCount();
781         }
782         mWifiMetrics.incrementScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN,
783                 NUM_SCAN_UNKNOWN);
784         mWifiMetrics.incrementScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS,
785                 NUM_SCAN_SUCCESS);
786         mWifiMetrics.incrementScanReturnEntry(
787                 WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED,
788                 NUM_SCAN_FAILURE_INTERRUPTED);
789         mWifiMetrics.incrementScanReturnEntry(
790                 WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION,
791                 NUM_SCAN_FAILURE_INVALID_CONFIGURATION);
792         for (int i = 0; i < NUM_WIFI_UNKNOWN_SCREEN_OFF; i++) {
793             mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN,
794                     false);
795         }
796         for (int i = 0; i < NUM_WIFI_UNKNOWN_SCREEN_ON; i++) {
797             mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN,
798                     true);
799         }
800         for (int i = 0; i < NUM_WIFI_ASSOCIATED_SCREEN_OFF; i++) {
801             mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED,
802                     false);
803         }
804         for (int i = 0; i < NUM_WIFI_ASSOCIATED_SCREEN_ON; i++) {
805             mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED,
806                     true);
807         }
808         for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD; i++) {
809             mWifiMetrics.incrementNumConnectivityWatchdogPnoGood();
810         }
811         for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_PNO_BAD; i++) {
812             mWifiMetrics.incrementNumConnectivityWatchdogPnoBad();
813         }
814         for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD; i++) {
815             mWifiMetrics.incrementNumConnectivityWatchdogBackgroundGood();
816         }
817         for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD; i++) {
818             mWifiMetrics.incrementNumConnectivityWatchdogBackgroundBad();
819         }
820         for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS; i++) {
821             mWifiMetrics.incrementNumLastResortWatchdogTriggers();
822         }
823         mWifiMetrics.addCountToNumLastResortWatchdogBadAssociationNetworksTotal(
824                 NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL);
825         mWifiMetrics.addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal(
826                 NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL);
827         mWifiMetrics.addCountToNumLastResortWatchdogBadDhcpNetworksTotal(
828                 NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL);
829         mWifiMetrics.addCountToNumLastResortWatchdogBadOtherNetworksTotal(
830                 NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL);
831         mWifiMetrics.addCountToNumLastResortWatchdogAvailableNetworksTotal(
832                 NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL);
833         for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION; i++) {
834             mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadAssociation();
835         }
836         for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION; i++) {
837             mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadAuthentication();
838         }
839         for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP; i++) {
840             mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadDhcp();
841         }
842         for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER; i++) {
843             mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadOther();
844         }
845         for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_SUCCESSES; i++) {
846             mWifiMetrics.incrementNumLastResortWatchdogSuccesses();
847         }
848         for (int i = 0; i < WATCHDOG_TOTAL_CONNECTION_FAILURE_COUNT_AFTER_TRIGGER; i++) {
849             mWifiMetrics.incrementWatchdogTotalConnectionFailureCountAfterTrigger();
850         }
851         for (int i = 0; i < NUM_RSSI_LEVELS_TO_INCREMENT; i++) {
852             for (int j = 0; j <= i; j++) {
853                 mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, MIN_RSSI_LEVEL + i);
854             }
855         }
856         for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
857             mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, MIN_RSSI_LEVEL - i);
858         }
859         for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
860             mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, MAX_RSSI_LEVEL + i);
861         }
862 
863         // Test alert-reason clamping.
864         mWifiMetrics.logFirmwareAlert(TEST_IFACE_NAME, WifiLoggerHal.WIFI_ALERT_REASON_MIN - 1);
865         mWifiMetrics.logFirmwareAlert(TEST_IFACE_NAME, WifiLoggerHal.WIFI_ALERT_REASON_MAX + 1);
866         // Simple cases for alert reason.
867         mWifiMetrics.logFirmwareAlert(TEST_IFACE_NAME, 1);
868         mWifiMetrics.logFirmwareAlert(TEST_IFACE_NAME, 1);
869         mWifiMetrics.logFirmwareAlert(TEST_IFACE_NAME, 1);
870         mWifiMetrics.logFirmwareAlert(TEST_IFACE_NAME, 2);
871         List<ScanDetail> mockScanDetails = buildMockScanDetailList();
872         for (int i = 0; i < NUM_SCANS; i++) {
873             mWifiMetrics.countScanResults(mockScanDetails);
874         }
875         // increment connectivity scan metrics
876         for (int i = 0; i < NUM_CONNECTIVITY_ONESHOT_SCAN_EVENT; i++) {
877             mWifiMetrics.incrementConnectivityOneshotScanCount();
878         }
879         for (int i = 0; i < NUM_EXTERNAL_APP_ONESHOT_SCAN_REQUESTS; i++) {
880             mWifiMetrics.incrementExternalAppOneshotScanRequestsCount();
881         }
882         for (int i = 0; i < NUM_EXTERNAL_FOREGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED; i++) {
883             mWifiMetrics.incrementExternalForegroundAppOneshotScanRequestsThrottledCount();
884         }
885         for (int i = 0; i < NUM_EXTERNAL_BACKGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED; i++) {
886             mWifiMetrics.incrementExternalBackgroundAppOneshotScanRequestsThrottledCount();
887         }
888         for (int score = 0; score < NUM_WIFI_SCORES_TO_INCREMENT; score++) {
889             for (int offset = 0; offset <= score; offset++) {
890                 mWifiMetrics.incrementWifiScoreCount(TEST_IFACE_NAME, WIFI_SCORE_RANGE_MIN + score);
891             }
892         }
893         for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
894             mWifiMetrics.incrementWifiScoreCount(TEST_IFACE_NAME, WIFI_SCORE_RANGE_MIN - i);
895         }
896         for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
897             mWifiMetrics.incrementWifiScoreCount(TEST_IFACE_NAME, WIFI_SCORE_RANGE_MAX + i);
898         }
899         for (int score = 0; score < NUM_WIFI_SCORES_TO_INCREMENT; score++) {
900             for (int offset = 0; offset <= score; offset++) {
901                 mWifiMetrics.incrementWifiUsabilityScoreCount(
902                         TEST_IFACE_NAME, 1, WIFI_SCORE_RANGE_MIN + score, 15);
903             }
904         }
905         for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
906             mWifiMetrics.incrementWifiUsabilityScoreCount(
907                     TEST_IFACE_NAME, 1, WIFI_SCORE_RANGE_MIN - i, 15);
908         }
909         for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
910             mWifiMetrics.incrementWifiUsabilityScoreCount(
911                     TEST_IFACE_NAME, 1, WIFI_SCORE_RANGE_MAX + i, 15);
912         }
913 
914         // increment soft ap start return codes
915         for (int i = 0; i < NUM_SOFTAP_START_SUCCESS; i++) {
916             mWifiMetrics.incrementSoftApStartResult(true, 0);
917         }
918         for (int i = 0; i < NUM_SOFTAP_FAILED_GENERAL_ERROR; i++) {
919             mWifiMetrics.incrementSoftApStartResult(false, WifiManager.SAP_START_FAILURE_GENERAL);
920         }
921         for (int i = 0; i < NUM_SOFTAP_FAILED_NO_CHANNEL; i++) {
922             mWifiMetrics.incrementSoftApStartResult(false,
923                     WifiManager.SAP_START_FAILURE_NO_CHANNEL);
924         }
925         for (int i = 0; i < NUM_HAL_CRASHES; i++) {
926             mWifiMetrics.incrementNumHalCrashes();
927         }
928         for (int i = 0; i < NUM_WIFICOND_CRASHES; i++) {
929             mWifiMetrics.incrementNumWificondCrashes();
930         }
931         for (int i = 0; i < NUM_SUPPLICANT_CRASHES; i++) {
932             mWifiMetrics.incrementNumSupplicantCrashes();
933         }
934         for (int i = 0; i < NUM_HOSTAPD_CRASHES; i++) {
935             mWifiMetrics.incrementNumHostapdCrashes();
936         }
937         for (int i = 0; i < NUM_WIFI_ON_FAILURE_DUE_TO_HAL; i++) {
938             mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
939         }
940         for (int i = 0; i < NUM_WIFI_ON_FAILURE_DUE_TO_WIFICOND; i++) {
941             mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond();
942         }
943         for (int i = 0; i < NUM_WIFI_ON_FAILURE_DUE_TO_SUPPLICANT; i++) {
944             mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
945         }
946         for (int i = 0; i < NUM_SOFTAP_ON_FAILURE_DUE_TO_HAL; i++) {
947             mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHal();
948         }
949         for (int i = 0; i < NUM_SOFTAP_ON_FAILURE_DUE_TO_WIFICOND; i++) {
950             mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToWificond();
951         }
952         for (int i = 0; i < NUM_SOFTAP_ON_FAILURE_DUE_TO_HOSTAPD; i++) {
953             mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();
954         }
955         for (int i = 0; i < NUM_SOFTAP_INTERFACE_DOWN; i++) {
956             mWifiMetrics.incrementNumSoftApInterfaceDown();
957         }
958         for (int i = 0; i < NUM_CLIENT_INTERFACE_DOWN; i++) {
959             mWifiMetrics.incrementNumClientInterfaceDown();
960         }
961         for (int i = 0; i < NUM_PASSPOINT_PROVIDER_INSTALLATION; i++) {
962             mWifiMetrics.incrementNumPasspointProviderInstallation();
963         }
964         for (int i = 0; i < NUM_PASSPOINT_PROVIDER_INSTALL_SUCCESS; i++) {
965             mWifiMetrics.incrementNumPasspointProviderInstallSuccess();
966         }
967         for (int i = 0; i < NUM_PASSPOINT_PROVIDER_UNINSTALLATION; i++) {
968             mWifiMetrics.incrementNumPasspointProviderUninstallation();
969         }
970         for (int i = 0; i < NUM_PASSPOINT_PROVIDER_UNINSTALL_SUCCESS; i++) {
971             mWifiMetrics.incrementNumPasspointProviderUninstallSuccess();
972         }
973         for (int i = 0; i < NUM_PASSPOINT_PROVIDERS_WITH_NO_ROOT_CA; i++) {
974             mWifiMetrics.incrementNumPasspointProviderWithNoRootCa();
975         }
976         for (int i = 0; i < NUM_PASSPOINT_PROVIDERS_WITH_SELF_SIGNED_ROOT_CA; i++) {
977             mWifiMetrics.incrementNumPasspointProviderWithSelfSignedRootCa();
978         }
979         for (int i = 0; i < NUM_PASSPOINT_PROVIDERS_WITH_EXPIRATION_DATE; i++) {
980             mWifiMetrics.incrementNumPasspointProviderWithSubscriptionExpiration();
981         }
982         for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_MCC; i++) {
983             mWifiMetrics.incrementNumRadioModeChangeToMcc();
984         }
985         for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_SCC; i++) {
986             mWifiMetrics.incrementNumRadioModeChangeToScc();
987         }
988         for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_SBS; i++) {
989             mWifiMetrics.incrementNumRadioModeChangeToSbs();
990         }
991         for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_DBS; i++) {
992             mWifiMetrics.incrementNumRadioModeChangeToDbs();
993         }
994         for (int i = 0; i < NUM_SOFTAP_USER_BAND_PREFERENCE_UNSATISFIED; i++) {
995             mWifiMetrics.incrementNumSoftApUserBandPreferenceUnsatisfied();
996         }
997 
998         // increment pno scan metrics
999         for (int i = 0; i < NUM_PNO_SCAN_ATTEMPTS; i++) {
1000             mWifiMetrics.incrementPnoScanStartAttemptCount();
1001         }
1002         for (int i = 0; i < NUM_PNO_SCAN_FAILED; i++) {
1003             mWifiMetrics.incrementPnoScanFailedCount();
1004         }
1005         for (int i = 0; i < NUM_PNO_FOUND_NETWORK_EVENTS; i++) {
1006             mWifiMetrics.incrementPnoFoundNetworkEventCount();
1007         }
1008         for (int i = 0; i < NUM_BSSID_SELECTION_DIFFERENT_BETWEEN_FRAMEWORK_FIRMWARE; i++) {
1009             mWifiMetrics.incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware();
1010         }
1011 
1012         // set and increment "connect to network" notification metrics
1013         for (int i = 0; i < NUM_CONNECT_TO_NETWORK_NOTIFICATIONS.length; i++) {
1014             int count = NUM_CONNECT_TO_NETWORK_NOTIFICATIONS[i];
1015             for (int j = 0; j < count; j++) {
1016                 mWifiMetrics.incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, i);
1017             }
1018         }
1019         for (int i = 0; i < NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS.length; i++) {
1020             int[] actions = NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS[i];
1021             for (int j = 0; j < actions.length; j++) {
1022                 int count = actions[j];
1023                 for (int k = 0; k < count; k++) {
1024                     mWifiMetrics.incrementConnectToNetworkNotificationAction(OPEN_NET_NOTIFIER_TAG,
1025                             i, j);
1026                 }
1027             }
1028         }
1029         mWifiMetrics.setNetworkRecommenderBlocklistSize(OPEN_NET_NOTIFIER_TAG,
1030                 SIZE_OPEN_NETWORK_RECOMMENDER_BLOCKLIST);
1031         mWifiMetrics.setIsWifiNetworksAvailableNotificationEnabled(OPEN_NET_NOTIFIER_TAG,
1032                 IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON);
1033         for (int i = 0; i < NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES; i++) {
1034             mWifiMetrics.incrementNumNetworkRecommendationUpdates(OPEN_NET_NOTIFIER_TAG);
1035         }
1036         for (int i = 0; i < NUM_OPEN_NETWORK_CONNECT_MESSAGE_FAILED_TO_SEND; i++) {
1037             mWifiMetrics.incrementNumNetworkConnectMessageFailedToSend(OPEN_NET_NOTIFIER_TAG);
1038         }
1039 
1040         addSoftApEventsToMetrics();
1041 
1042         for (int i = 0; i < NUM_ONESHOT_SCAN_REQUESTS_WITH_DFS_CHANNELS; i++) {
1043             mWifiMetrics.incrementOneshotScanWithDfsCount();
1044         }
1045         for (int i = 0; i < NUM_ADD_OR_UPDATE_NETWORK_CALLS; i++) {
1046             mWifiMetrics.incrementNumAddOrUpdateNetworkCalls();
1047         }
1048         for (int i = 0; i < NUM_ENABLE_NETWORK_CALLS; i++) {
1049             mWifiMetrics.incrementNumEnableNetworkCalls();
1050         }
1051         for (int i = 0; i < NUM_IP_RENEWAL_FAILURE; i++) {
1052             mWifiMetrics.incrementIpRenewalFailure();
1053         }
1054 
1055         mWifiMetrics.setWatchdogSuccessTimeDurationMs(NUM_WATCHDOG_SUCCESS_DURATION_MS);
1056         mResources.setBoolean(R.bool.config_wifi_connected_mac_randomization_supported,
1057                 IS_MAC_RANDOMIZATION_ON);
1058 
1059         addWifiPowerMetrics();
1060 
1061         addWifiHealthMetrics();
1062 
1063         mResources.setBoolean(R.bool.config_wifiIsUnusableEventMetricsEnabled,
1064                 WIFI_IS_UNUSABLE_EVENT_LOGGING_SETTING);
1065         mResources.setBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled,
1066                 LINK_SPEED_COUNTS_LOGGING_SETTING);
1067         mResources.setInteger(R.integer.config_wifiDataStallMinTxBad,
1068                 DATA_STALL_MIN_TX_BAD_SETTING);
1069         mResources.setInteger(R.integer.config_wifiDataStallMinTxSuccessWithoutRx,
1070                 DATA_STALL_MIN_TX_SUCCESS_WITHOUT_RX_SETTING);
1071 
1072         for (int i = 0; i < NUM_BSSID_FILTERED_DUE_TO_MBO_ASSOC_DISALLOW_IND; i++) {
1073             mWifiMetrics.incrementNetworkSelectionFilteredBssidCountDueToMboAssocDisallowInd();
1074         }
1075         for (int i = 0; i < NUM_STEERING_REQUEST; i++) {
1076             mWifiMetrics.incrementSteeringRequestCount();
1077         }
1078         for (int i = 0; i < NUM_FORCE_SCAN_DUE_TO_STEERING_REQUEST; i++) {
1079             mWifiMetrics.incrementForceScanCountDueToSteeringRequest();
1080         }
1081         for (int i = 0; i < NUM_MBO_CELLULAR_SWITCH_REQUEST; i++) {
1082             mWifiMetrics.incrementMboCellularSwitchRequestCount();
1083         }
1084         for (int i = 0; i < NUM_STEERING_REQUEST_INCLUDING_MBO_ASSOC_RETRY_DELAY; i++) {
1085             mWifiMetrics.incrementSteeringRequestCountIncludingMboAssocRetryDelay();
1086         }
1087         for (int i = 0; i < NUM_CONNECT_REQUEST_WITH_FILS_AKM; i++) {
1088             mWifiMetrics.incrementConnectRequestWithFilsAkmCount();
1089         }
1090         for (int i = 0; i < NUM_L2_CONNECTION_THROUGH_FILS_AUTHENTICATION; i++) {
1091             mWifiMetrics.incrementL2ConnectionThroughFilsAuthCount();
1092         }
1093     }
1094 
addWifiPowerMetrics()1095     private void addWifiPowerMetrics() {
1096         WifiRadioUsage wifiRadioUsage = new WifiRadioUsage();
1097         wifiRadioUsage.loggingDurationMs = WIFI_POWER_METRICS_LOGGING_DURATION;
1098         wifiRadioUsage.scanTimeMs = WIFI_POWER_METRICS_SCAN_TIME;
1099         when(mWifiPowerMetrics.buildWifiRadioUsageProto()).thenReturn(wifiRadioUsage);
1100     }
1101 
addWifiHealthMetrics()1102     private void addWifiHealthMetrics() {
1103         HealthMonitorMetrics metrics = new HealthMonitorMetrics();
1104         metrics.failureStatsIncrease = new HealthMonitorFailureStats();
1105         metrics.failureStatsDecrease = new HealthMonitorFailureStats();
1106         metrics.failureStatsHigh = new HealthMonitorFailureStats();
1107         metrics.failureStatsIncrease.cntAssocRejection = NUM_NETWORK_ABNORMAL_ASSOC_REJECTION;
1108         metrics.failureStatsDecrease.cntDisconnectionNonlocalConnecting =
1109                 NUM_NETWORK_ABNORMAL_CONNECTION_FAILURE_DISCONNECTION;
1110         metrics.numNetworkSufficientRecentStatsOnly = NUM_NETWORK_SUFFICIENT_RECENT_STATS_ONLY;
1111         metrics.numNetworkSufficientRecentPrevStats = NUM_NETWORK_SUFFICIENT_RECENT_PREV_STATS;
1112         when(mWifiHealthMonitor.buildProto()).thenReturn(metrics);
1113         when(mWifiHealthMonitor.getWifiStackVersion()).thenReturn(WIFI_MAINLINE_MODULE_VERSION);
1114     }
1115 
addSoftApEventsToMetrics()1116     private void addSoftApEventsToMetrics() {
1117         SoftApInfo testSoftApInfo_2G = new SoftApInfo();
1118         testSoftApInfo_2G.setFrequency(SOFT_AP_CHANNEL_FREQUENCY_2G);
1119         testSoftApInfo_2G.setBandwidth(SOFT_AP_CHANNEL_BANDWIDTH_2G);
1120         testSoftApInfo_2G.setWifiStandard(SOFT_AP_GENERATION_2G);
1121         SoftApInfo testSoftApInfo_5G = new SoftApInfo();
1122         testSoftApInfo_5G.setFrequency(SOFT_AP_CHANNEL_FREQUENCY_5G);
1123         testSoftApInfo_5G.setBandwidth(SOFT_AP_CHANNEL_BANDWIDTH_5G);
1124         testSoftApInfo_5G.setWifiStandard(SOFT_AP_GENERATION_5G);
1125 
1126         // Total number of events recorded is NUM_SOFT_AP_EVENT_ENTRIES in both modes
1127         mWifiMetrics.addSoftApUpChangedEvent(true, WifiManager.IFACE_IP_MODE_TETHERED,
1128                 SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING, false);
1129         mWifiMetrics.addSoftApNumAssociatedStationsChangedEvent(NUM_SOFT_AP_ASSOCIATED_STATIONS,
1130                 NUM_SOFT_AP_ASSOCIATED_STATIONS, WifiManager.IFACE_IP_MODE_TETHERED,
1131                 testSoftApInfo_2G);
1132 
1133         // Should be dropped.
1134         mWifiMetrics.addSoftApNumAssociatedStationsChangedEvent(NUM_SOFT_AP_ASSOCIATED_STATIONS,
1135                 NUM_SOFT_AP_ASSOCIATED_STATIONS, WifiManager.IFACE_IP_MODE_UNSPECIFIED,
1136                 testSoftApInfo_2G);
1137 
1138         mWifiMetrics.addSoftApUpChangedEvent(false, WifiManager.IFACE_IP_MODE_TETHERED,
1139                 SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING, false);
1140 
1141 
1142 
1143         // Channel switch info should be added to the last Soft AP UP event in the list
1144         mWifiMetrics.addSoftApChannelSwitchedEvent(new ArrayList<>() {{ add(testSoftApInfo_2G); }},
1145                 WifiManager.IFACE_IP_MODE_TETHERED, false);
1146         SoftApConfiguration testSoftApConfig = new SoftApConfiguration.Builder()
1147                 .setSsid("Test_Metric_SSID")
1148                 .setMaxNumberOfClients(SOFT_AP_MAX_CLIENT_SETTING)
1149                 .setShutdownTimeoutMillis(SOFT_AP_SHUTDOWN_TIMEOUT_SETTING)
1150                 .setClientControlByUserEnabled(SOFT_AP_CLIENT_CONTROL_ENABLE)
1151                 .build();
1152         mWifiMetrics.updateSoftApConfiguration(testSoftApConfig,
1153                 WifiManager.IFACE_IP_MODE_TETHERED, false);
1154         SoftApCapability testSoftApCapability = new SoftApCapability(0);
1155         testSoftApCapability.setMaxSupportedClients(SOFT_AP_MAX_CLIENT_CAPABILITY);
1156         mWifiMetrics.updateSoftApCapability(testSoftApCapability,
1157                 WifiManager.IFACE_IP_MODE_TETHERED, false);
1158 
1159         mWifiMetrics.addSoftApUpChangedEvent(true, WifiManager.IFACE_IP_MODE_LOCAL_ONLY,
1160                 SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING, false);
1161         mWifiMetrics.addSoftApNumAssociatedStationsChangedEvent(NUM_SOFT_AP_ASSOCIATED_STATIONS,
1162                 NUM_SOFT_AP_ASSOCIATED_STATIONS, WifiManager.IFACE_IP_MODE_LOCAL_ONLY,
1163                 testSoftApInfo_2G);
1164 
1165         // Should be dropped.
1166         mWifiMetrics.addSoftApUpChangedEvent(false, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR,
1167                 SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING, false);
1168         mWifiMetrics.addSoftApUpChangedEvent(false, WifiManager.IFACE_IP_MODE_LOCAL_ONLY,
1169                 SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING, false);
1170 
1171         // Bridged mode test, total NUM_SOFT_AP_EVENT_ENTRIES_FOR_BRIDGED_AP events for bridged mode
1172         mWifiMetrics.addSoftApUpChangedEvent(true, WifiManager.IFACE_IP_MODE_TETHERED,
1173                 SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING, true);
1174         mWifiMetrics.addSoftApChannelSwitchedEvent(new ArrayList<>() {{
1175                     add(testSoftApInfo_2G);
1176                     add(testSoftApInfo_5G);
1177                 }},
1178                 WifiManager.IFACE_IP_MODE_TETHERED, true);
1179 
1180         mWifiMetrics.updateSoftApConfiguration(testSoftApConfig,
1181                 WifiManager.IFACE_IP_MODE_TETHERED, true);
1182         mWifiMetrics.updateSoftApCapability(testSoftApCapability,
1183                 WifiManager.IFACE_IP_MODE_TETHERED, true);
1184 
1185         mWifiMetrics.addSoftApInstanceDownEventInDualMode(WifiManager.IFACE_IP_MODE_TETHERED,
1186                 testSoftApInfo_5G);
1187         mWifiMetrics.addSoftApUpChangedEvent(false, WifiManager.IFACE_IP_MODE_TETHERED,
1188                 SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING, true);
1189     }
1190 
verifySoftApEventsStoredInProto()1191     private void verifySoftApEventsStoredInProto() {
1192         // Tethered mode includes single AP and dual AP test.
1193         assertEquals(NUM_SOFT_AP_EVENT_ENTRIES + NUM_SOFT_AP_EVENT_ENTRIES_FOR_BRIDGED_AP,
1194                 mDecodedProto.softApConnectedClientsEventsTethered.length);
1195         assertEquals(SoftApConnectedClientsEvent.SOFT_AP_UP,
1196                 mDecodedProto.softApConnectedClientsEventsTethered[0].eventType);
1197         assertEquals(0, mDecodedProto.softApConnectedClientsEventsTethered[0].numConnectedClients);
1198         assertEquals(SOFT_AP_CHANNEL_FREQUENCY_2G,
1199                 mDecodedProto.softApConnectedClientsEventsTethered[0].channelFrequency);
1200         assertEquals(SOFT_AP_CHANNEL_BANDWIDTH_2G,
1201                 mDecodedProto.softApConnectedClientsEventsTethered[0].channelBandwidth);
1202         assertEquals(SOFT_AP_MAX_CLIENT_SETTING,
1203                 mDecodedProto.softApConnectedClientsEventsTethered[0]
1204                 .maxNumClientsSettingInSoftapConfiguration);
1205         assertEquals(SOFT_AP_MAX_CLIENT_CAPABILITY,
1206                 mDecodedProto.softApConnectedClientsEventsTethered[0]
1207                 .maxNumClientsSettingInSoftapCapability);
1208         assertEquals(SOFT_AP_SHUTDOWN_TIMEOUT_SETTING,
1209                 mDecodedProto.softApConnectedClientsEventsTethered[0]
1210                 .shutdownTimeoutSettingInSoftapConfiguration);
1211         assertEquals(SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING,
1212                 mDecodedProto.softApConnectedClientsEventsTethered[0]
1213                 .defaultShutdownTimeoutSetting);
1214         assertEquals(SOFT_AP_CLIENT_CONTROL_ENABLE,
1215                 mDecodedProto.softApConnectedClientsEventsTethered[0].clientControlIsEnabled);
1216 
1217         assertEquals(SoftApConnectedClientsEvent.NUM_CLIENTS_CHANGED,
1218                 mDecodedProto.softApConnectedClientsEventsTethered[1].eventType);
1219         assertEquals(NUM_SOFT_AP_ASSOCIATED_STATIONS,
1220                 mDecodedProto.softApConnectedClientsEventsTethered[1].numConnectedClients);
1221         assertEquals(SoftApConnectedClientsEvent.SOFT_AP_DOWN,
1222                 mDecodedProto.softApConnectedClientsEventsTethered[2].eventType);
1223         assertEquals(0, mDecodedProto.softApConnectedClientsEventsTethered[2].numConnectedClients);
1224 
1225         // Verify the bridged AP metrics
1226         assertEquals(SoftApConnectedClientsEvent.DUAL_AP_BOTH_INSTANCES_UP,
1227                 mDecodedProto.softApConnectedClientsEventsTethered[3].eventType);
1228         assertEquals(0, mDecodedProto.softApConnectedClientsEventsTethered[3].numConnectedClients);
1229         assertEquals(SOFT_AP_CHANNEL_FREQUENCY_2G,
1230                 mDecodedProto.softApConnectedClientsEventsTethered[3].channelFrequency);
1231         assertEquals(SOFT_AP_CHANNEL_BANDWIDTH_2G,
1232                 mDecodedProto.softApConnectedClientsEventsTethered[3].channelBandwidth);
1233         assertEquals(SOFT_AP_MAX_CLIENT_SETTING,
1234                 mDecodedProto.softApConnectedClientsEventsTethered[3]
1235                 .maxNumClientsSettingInSoftapConfiguration);
1236         assertEquals(SOFT_AP_MAX_CLIENT_CAPABILITY,
1237                 mDecodedProto.softApConnectedClientsEventsTethered[3]
1238                 .maxNumClientsSettingInSoftapCapability);
1239         assertEquals(SOFT_AP_SHUTDOWN_TIMEOUT_SETTING,
1240                 mDecodedProto.softApConnectedClientsEventsTethered[3]
1241                 .shutdownTimeoutSettingInSoftapConfiguration);
1242         assertEquals(SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING,
1243                 mDecodedProto.softApConnectedClientsEventsTethered[3]
1244                 .defaultShutdownTimeoutSetting);
1245         assertEquals(SOFT_AP_CLIENT_CONTROL_ENABLE,
1246                 mDecodedProto.softApConnectedClientsEventsTethered[3].clientControlIsEnabled);
1247         assertEquals(SoftApConnectedClientsEvent.DUAL_AP_BOTH_INSTANCES_UP,
1248                 mDecodedProto.softApConnectedClientsEventsTethered[4].eventType);
1249         assertEquals(0, mDecodedProto.softApConnectedClientsEventsTethered[4].numConnectedClients);
1250         assertEquals(SOFT_AP_CHANNEL_FREQUENCY_5G,
1251                 mDecodedProto.softApConnectedClientsEventsTethered[4].channelFrequency);
1252         assertEquals(SOFT_AP_CHANNEL_BANDWIDTH_5G,
1253                 mDecodedProto.softApConnectedClientsEventsTethered[4].channelBandwidth);
1254         assertEquals(SOFT_AP_MAX_CLIENT_SETTING,
1255                 mDecodedProto.softApConnectedClientsEventsTethered[4]
1256                 .maxNumClientsSettingInSoftapConfiguration);
1257         assertEquals(SOFT_AP_MAX_CLIENT_CAPABILITY,
1258                 mDecodedProto.softApConnectedClientsEventsTethered[4]
1259                 .maxNumClientsSettingInSoftapCapability);
1260         assertEquals(SOFT_AP_SHUTDOWN_TIMEOUT_SETTING,
1261                 mDecodedProto.softApConnectedClientsEventsTethered[4]
1262                 .shutdownTimeoutSettingInSoftapConfiguration);
1263         assertEquals(SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING,
1264                 mDecodedProto.softApConnectedClientsEventsTethered[4]
1265                 .defaultShutdownTimeoutSetting);
1266         assertEquals(SOFT_AP_CLIENT_CONTROL_ENABLE,
1267                 mDecodedProto.softApConnectedClientsEventsTethered[4].clientControlIsEnabled);
1268         assertEquals(SoftApConnectedClientsEvent.DUAL_AP_ONE_INSTANCE_DOWN,
1269                 mDecodedProto.softApConnectedClientsEventsTethered[5].eventType);
1270         assertEquals(0, mDecodedProto.softApConnectedClientsEventsTethered[5].numConnectedClients);
1271         assertEquals(SoftApConnectedClientsEvent.SOFT_AP_DOWN,
1272                 mDecodedProto.softApConnectedClientsEventsTethered[6].eventType);
1273         assertEquals(0, mDecodedProto.softApConnectedClientsEventsTethered[6].numConnectedClients);
1274 
1275         assertEquals(SoftApConnectedClientsEvent.SOFT_AP_UP,
1276                 mDecodedProto.softApConnectedClientsEventsLocalOnly[0].eventType);
1277         assertEquals(0, mDecodedProto.softApConnectedClientsEventsLocalOnly[0].numConnectedClients);
1278         assertEquals(SoftApConnectedClientsEvent.NUM_CLIENTS_CHANGED,
1279                 mDecodedProto.softApConnectedClientsEventsLocalOnly[1].eventType);
1280         assertEquals(NUM_SOFT_AP_ASSOCIATED_STATIONS,
1281                 mDecodedProto.softApConnectedClientsEventsLocalOnly[1].numConnectedClients);
1282         assertEquals(SoftApConnectedClientsEvent.SOFT_AP_DOWN,
1283                 mDecodedProto.softApConnectedClientsEventsLocalOnly[2].eventType);
1284         assertEquals(0, mDecodedProto.softApConnectedClientsEventsLocalOnly[2].numConnectedClients);
1285     }
1286 
1287     /**
1288      * Assert that values in deserializedWifiMetrics match those set in 'setAndIncrementMetrics'
1289      */
assertDeserializedMetricsCorrect()1290     private void assertDeserializedMetricsCorrect() throws Exception {
1291         assertEquals("mDecodedProto.numSavedNetworks == NUM_SAVED_NETWORKS",
1292                 NUM_SAVED_NETWORKS, mDecodedProto.numSavedNetworks);
1293         assertEquals("mDecodedProto.numSavedNetworksWithMacRandomization == NUM_SAVED_NETWORKS-1",
1294                 NUM_SAVED_NETWORKS - 1, mDecodedProto.numSavedNetworksWithMacRandomization);
1295         assertEquals("mDecodedProto.numOpenNetworks == NUM_OPEN_NETWORKS",
1296                 NUM_OPEN_NETWORKS, mDecodedProto.numOpenNetworks);
1297         assertEquals("mDecodedProto.numLegacyPersonalNetworks == NUM_LEGACY_PERSONAL_NETWORKS",
1298                 NUM_LEGACY_PERSONAL_NETWORKS, mDecodedProto.numLegacyPersonalNetworks);
1299         assertEquals(
1300                 "mDecodedProto.numLegacyEnterpriseNetworks == NUM_LEGACY_ENTERPRISE_NETWORKS",
1301                 NUM_LEGACY_ENTERPRISE_NETWORKS, mDecodedProto.numLegacyEnterpriseNetworks);
1302         assertEquals("mDecodedProto.numEnhancedOpenNetworks == NUM_ENHANCED_OPEN_NETWORKS",
1303                 NUM_ENHANCED_OPEN_NETWORKS, mDecodedProto.numEnhancedOpenNetworks);
1304         assertEquals("mDecodedProto.numWpa3PersonalNetworks == NUM_WPA3_PERSONAL_NETWORKS",
1305                 NUM_WPA3_PERSONAL_NETWORKS, mDecodedProto.numWpa3PersonalNetworks);
1306         assertEquals("mDecodedProto.numWpa3EnterpriseNetworks == NUM_WPA3_ENTERPRISE_NETWORKS",
1307                 NUM_WPA3_ENTERPRISE_NETWORKS, mDecodedProto.numWpa3EnterpriseNetworks);
1308         assertEquals("mDecodedProto.numWapiPersonalNetworks == NUM_WAPI_PERSONAL_NETWORKS",
1309                 NUM_WAPI_PERSONAL_NETWORKS, mDecodedProto.numWapiPersonalNetworks);
1310         assertEquals("mDecodedProto.numWapiEnterpriseNetworks == NUM_WAPI_ENTERPRISE_NETWORKS",
1311                 NUM_WAPI_ENTERPRISE_NETWORKS, mDecodedProto.numWapiEnterpriseNetworks);
1312         assertEquals("mDecodedProto.numNetworksAddedByUser == NUM_NETWORKS_ADDED_BY_USER",
1313                 NUM_NETWORKS_ADDED_BY_USER, mDecodedProto.numNetworksAddedByUser);
1314         assertEquals(NUM_HIDDEN_NETWORKS, mDecodedProto.numHiddenNetworks);
1315         assertEquals(NUM_PASSPOINT_NETWORKS, mDecodedProto.numPasspointNetworks);
1316         assertEquals("mDecodedProto.numNetworksAddedByApps == NUM_NETWORKS_ADDED_BY_APPS",
1317                 NUM_NETWORKS_ADDED_BY_APPS, mDecodedProto.numNetworksAddedByApps);
1318         assertEquals("mDecodedProto.isLocationEnabled == TEST_VAL_IS_LOCATION_ENABLED",
1319                 TEST_VAL_IS_LOCATION_ENABLED, mDecodedProto.isLocationEnabled);
1320         assertEquals("mDecodedProto.isScanningAlwaysEnabled == IS_SCANNING_ALWAYS_ENABLED",
1321                 IS_SCANNING_ALWAYS_ENABLED, mDecodedProto.isScanningAlwaysEnabled);
1322         assertEquals(IS_VERBOSE_LOGGING_ENABLED, mDecodedProto.isVerboseLoggingEnabled);
1323         assertEquals(IS_NON_PERSISTENT_MAC_RANDOMIZATION_FORCE_ENABLED,
1324                 mDecodedProto.isEnhancedMacRandomizationForceEnabled);
1325         assertEquals(IS_WIFI_WAKE_ENABLED, mDecodedProto.isWifiWakeEnabled);
1326         assertEquals("mDecodedProto.numEmptyScanResults == NUM_EMPTY_SCAN_RESULTS",
1327                 NUM_EMPTY_SCAN_RESULTS, mDecodedProto.numEmptyScanResults);
1328         assertEquals("mDecodedProto.numNonEmptyScanResults == NUM_NON_EMPTY_SCAN_RESULTS",
1329                 NUM_NON_EMPTY_SCAN_RESULTS, mDecodedProto.numNonEmptyScanResults);
1330         assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_UNKNOWN, NUM_SCAN_UNKNOWN);
1331         assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_SUCCESS, NUM_SCAN_SUCCESS);
1332         assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED,
1333                 NUM_SCAN_FAILURE_INTERRUPTED);
1334         assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION,
1335                 NUM_SCAN_FAILURE_INVALID_CONFIGURATION);
1336         assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, false,
1337                 NUM_WIFI_UNKNOWN_SCREEN_OFF);
1338         assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, true,
1339                 NUM_WIFI_UNKNOWN_SCREEN_ON);
1340         assertSystemStateEntryEquals(
1341                 WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, false, NUM_WIFI_ASSOCIATED_SCREEN_OFF);
1342         assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, true,
1343                 NUM_WIFI_ASSOCIATED_SCREEN_ON);
1344         assertEquals(NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD,
1345                 mDecodedProto.numConnectivityWatchdogPnoGood);
1346         assertEquals(NUM_CONNECTIVITY_WATCHDOG_PNO_BAD,
1347                 mDecodedProto.numConnectivityWatchdogPnoBad);
1348         assertEquals(NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD,
1349                 mDecodedProto.numConnectivityWatchdogBackgroundGood);
1350         assertEquals(NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD,
1351                 mDecodedProto.numConnectivityWatchdogBackgroundBad);
1352         assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS,
1353                 mDecodedProto.numLastResortWatchdogTriggers);
1354         assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL,
1355                 mDecodedProto.numLastResortWatchdogBadAssociationNetworksTotal);
1356         assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL,
1357                 mDecodedProto.numLastResortWatchdogBadAuthenticationNetworksTotal);
1358         assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL,
1359                 mDecodedProto.numLastResortWatchdogBadDhcpNetworksTotal);
1360         assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL,
1361                 mDecodedProto.numLastResortWatchdogBadOtherNetworksTotal);
1362         assertEquals(NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL,
1363                 mDecodedProto.numLastResortWatchdogAvailableNetworksTotal);
1364         assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION,
1365                 mDecodedProto.numLastResortWatchdogTriggersWithBadAssociation);
1366         assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION,
1367                 mDecodedProto.numLastResortWatchdogTriggersWithBadAuthentication);
1368         assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP,
1369                 mDecodedProto.numLastResortWatchdogTriggersWithBadDhcp);
1370         assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER,
1371                 mDecodedProto.numLastResortWatchdogTriggersWithBadOther);
1372         assertEquals(NUM_LAST_RESORT_WATCHDOG_SUCCESSES,
1373                 mDecodedProto.numLastResortWatchdogSuccesses);
1374         assertEquals(WATCHDOG_TOTAL_CONNECTION_FAILURE_COUNT_AFTER_TRIGGER,
1375                 mDecodedProto.watchdogTotalConnectionFailureCountAfterTrigger);
1376         assertEquals(TEST_RECORD_DURATION_SEC,
1377                 mDecodedProto.recordDurationSec);
1378         for (int i = 0; i < NUM_RSSI_LEVELS_TO_INCREMENT; i++) {
1379             assertEquals(RSSI_POLL_FREQUENCY,
1380                     mDecodedProto.rssiPollRssiCount[i].frequency);
1381             assertEquals(MIN_RSSI_LEVEL + i, mDecodedProto.rssiPollRssiCount[i].rssi);
1382             assertEquals(i + 1, mDecodedProto.rssiPollRssiCount[i].count);
1383         }
1384         StringBuilder sb_rssi = new StringBuilder();
1385         sb_rssi.append("Number of RSSIs = " + mDecodedProto.rssiPollRssiCount.length);
1386         assertTrue(sb_rssi.toString(), (mDecodedProto.rssiPollRssiCount.length
1387                      <= (MAX_RSSI_LEVEL - MIN_RSSI_LEVEL + 1)));
1388         assertEquals(2, mDecodedProto.alertReasonCount[0].count);  // Clamped reasons.
1389         assertEquals(3, mDecodedProto.alertReasonCount[1].count);
1390         assertEquals(1, mDecodedProto.alertReasonCount[2].count);
1391         assertEquals(3, mDecodedProto.alertReasonCount.length);
1392         assertEquals(NUM_TOTAL_SCAN_RESULTS * NUM_SCANS,
1393                 mDecodedProto.numTotalScanResults);
1394         assertEquals(NUM_OPEN_NETWORK_SCAN_RESULTS * NUM_SCANS,
1395                 mDecodedProto.numOpenNetworkScanResults);
1396         assertEquals(NUM_LEGACY_PERSONAL_NETWORK_SCAN_RESULTS * NUM_SCANS,
1397                 mDecodedProto.numLegacyPersonalNetworkScanResults);
1398         assertEquals(NUM_LEGACY_ENTERPRISE_NETWORK_SCAN_RESULTS * NUM_SCANS,
1399                 mDecodedProto.numLegacyEnterpriseNetworkScanResults);
1400         assertEquals(NUM_ENHANCED_OPEN_NETWORK_SCAN_RESULTS * NUM_SCANS,
1401                 mDecodedProto.numEnhancedOpenNetworkScanResults);
1402         assertEquals(NUM_WPA3_PERSONAL_NETWORK_SCAN_RESULTS * NUM_SCANS,
1403                 mDecodedProto.numWpa3PersonalNetworkScanResults);
1404         assertEquals(NUM_WPA3_ENTERPRISE_NETWORK_SCAN_RESULTS * NUM_SCANS,
1405                 mDecodedProto.numWpa3EnterpriseNetworkScanResults);
1406         assertEquals(NUM_WAPI_PERSONAL_NETWORK_SCAN_RESULTS * NUM_SCANS,
1407                 mDecodedProto.numWapiPersonalNetworkScanResults);
1408         assertEquals(NUM_WAPI_ENTERPRISE_NETWORK_SCAN_RESULTS * NUM_SCANS,
1409                 mDecodedProto.numWapiEnterpriseNetworkScanResults);
1410         assertEquals(NUM_HIDDEN_NETWORK_SCAN_RESULTS * NUM_SCANS,
1411                 mDecodedProto.numHiddenNetworkScanResults);
1412         assertEquals(NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS * NUM_SCANS,
1413                 mDecodedProto.numHotspot2R1NetworkScanResults);
1414         assertEquals(NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS * NUM_SCANS,
1415                 mDecodedProto.numHotspot2R2NetworkScanResults);
1416         assertEquals(NUM_HOTSPOT2_R3_NETWORK_SCAN_RESULTS * NUM_SCANS,
1417                 mDecodedProto.numHotspot2R3NetworkScanResults);
1418 
1419         assertEquals(NUM_MBO_SUPPORTED_NETWORKS_SCAN_RESULTS * NUM_SCANS,
1420                 mDecodedProto.numMboSupportedNetworkScanResults);
1421         assertEquals(NUM_MBO_CELL_DATA_AWARE_NETWORKS_SCAN_RESULTS * NUM_SCANS,
1422                 mDecodedProto.numMboCellularDataAwareNetworkScanResults);
1423         assertEquals(NUM_OCE_SUPPORTED_NETWORKS_SCAN_RESULTS * NUM_SCANS,
1424                 mDecodedProto.numOceSupportedNetworkScanResults);
1425         assertEquals(NUM_FILS_SUPPORTED_NETWORKS_SCAN_RESULTS * NUM_SCANS,
1426                 mDecodedProto.numFilsSupportedNetworkScanResults);
1427         assertEquals(NUM_11AX_NETWORKS_SCAN_RESULTS * NUM_SCANS,
1428                 mDecodedProto.num11AxNetworkScanResults);
1429         assertEquals(NUM_6G_NETWORKS_SCAN_RESULTS * NUM_SCANS,
1430                 mDecodedProto.num6GNetworkScanResults);
1431         assertEquals(NUM_6G_PSC_NETWORKS_SCAN_RESULTS * NUM_SCANS,
1432                 mDecodedProto.num6GPscNetworkScanResults);
1433         assertEquals(NUM_SCANS,
1434                 mDecodedProto.numScans);
1435         assertEquals(NUM_CONNECTIVITY_ONESHOT_SCAN_EVENT,
1436                 mDecodedProto.numConnectivityOneshotScans);
1437         assertEquals(NUM_EXTERNAL_APP_ONESHOT_SCAN_REQUESTS,
1438                 mDecodedProto.numExternalAppOneshotScanRequests);
1439         assertEquals(NUM_EXTERNAL_FOREGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED,
1440                 mDecodedProto.numExternalForegroundAppOneshotScanRequestsThrottled);
1441         assertEquals(NUM_EXTERNAL_BACKGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED,
1442                 mDecodedProto.numExternalBackgroundAppOneshotScanRequestsThrottled);
1443 
1444         for (int score_index = 0; score_index < NUM_WIFI_SCORES_TO_INCREMENT; score_index++) {
1445             assertEquals(WIFI_SCORE_RANGE_MIN + score_index,
1446                     mDecodedProto.wifiScoreCount[score_index].score);
1447             assertEquals(WIFI_SCORE_RANGE_MIN + score_index + 1,
1448                     mDecodedProto.wifiScoreCount[score_index].count);
1449             assertEquals(WIFI_SCORE_RANGE_MIN + score_index,
1450                     mDecodedProto.wifiUsabilityScoreCount[score_index].score);
1451             assertEquals(WIFI_SCORE_RANGE_MIN + score_index + 1,
1452                     mDecodedProto.wifiUsabilityScoreCount[score_index].count);
1453         }
1454         StringBuilder sb_wifi_score = new StringBuilder();
1455         sb_wifi_score.append("Number of wifi_scores = " + mDecodedProto.wifiScoreCount.length);
1456         assertTrue(sb_wifi_score.toString(), (mDecodedProto.wifiScoreCount.length
1457                 <= (WIFI_SCORE_RANGE_MAX - WIFI_SCORE_RANGE_MIN + 1)));
1458         StringBuilder sb_wifi_limits = new StringBuilder();
1459         sb_wifi_limits.append("Wifi Score limit is " +  ConnectedScore.WIFI_MAX_SCORE
1460                 + ">= " + WIFI_SCORE_RANGE_MAX);
1461         assertTrue(sb_wifi_limits.toString(),
1462                 ConnectedScore.WIFI_MAX_SCORE <= WIFI_SCORE_RANGE_MAX);
1463         StringBuilder sb_wifi_usability_score = new StringBuilder();
1464         sb_wifi_usability_score.append("Number of wifi_usability_scores = "
1465                 + mDecodedProto.wifiUsabilityScoreCount.length);
1466         assertTrue(sb_wifi_usability_score.toString(), (mDecodedProto.wifiUsabilityScoreCount.length
1467                 <= (WIFI_SCORE_RANGE_MAX - WIFI_SCORE_RANGE_MIN + 1)));
1468         StringBuilder sb_wifi_usablity_limits = new StringBuilder();
1469         sb_wifi_limits.append("Wifi Usability Score limit is " +  ConnectedScore.WIFI_MAX_SCORE
1470                 + ">= " + WIFI_SCORE_RANGE_MAX);
1471         assertTrue(sb_wifi_limits.toString(),
1472                 ConnectedScore.WIFI_MAX_SCORE <= WIFI_SCORE_RANGE_MAX);
1473         assertEquals(MAX_NUM_SOFTAP_RETURN_CODES, mDecodedProto.softApReturnCode.length);
1474         assertEquals(WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY,
1475                      mDecodedProto.softApReturnCode[0].startResult);
1476         assertEquals(NUM_SOFTAP_START_SUCCESS, mDecodedProto.softApReturnCode[0].count);
1477         assertEquals(WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR,
1478                      mDecodedProto.softApReturnCode[1].startResult);
1479         assertEquals(NUM_SOFTAP_FAILED_GENERAL_ERROR,
1480                      mDecodedProto.softApReturnCode[1].count);
1481         assertEquals(WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL,
1482                      mDecodedProto.softApReturnCode[2].startResult);
1483         assertEquals(NUM_SOFTAP_FAILED_NO_CHANNEL,
1484                      mDecodedProto.softApReturnCode[2].count);
1485         assertEquals(NUM_HAL_CRASHES, mDecodedProto.numHalCrashes);
1486         assertEquals(NUM_WIFICOND_CRASHES, mDecodedProto.numWificondCrashes);
1487         assertEquals(NUM_SUPPLICANT_CRASHES, mDecodedProto.numSupplicantCrashes);
1488         assertEquals(NUM_HOSTAPD_CRASHES, mDecodedProto.numHostapdCrashes);
1489         assertEquals(NUM_WIFI_ON_FAILURE_DUE_TO_HAL,
1490                 mDecodedProto.numSetupClientInterfaceFailureDueToHal);
1491         assertEquals(NUM_WIFI_ON_FAILURE_DUE_TO_WIFICOND,
1492                 mDecodedProto.numSetupClientInterfaceFailureDueToWificond);
1493         assertEquals(NUM_WIFI_ON_FAILURE_DUE_TO_SUPPLICANT,
1494                 mDecodedProto.numSetupClientInterfaceFailureDueToSupplicant);
1495         assertEquals(NUM_SOFTAP_ON_FAILURE_DUE_TO_HAL,
1496                 mDecodedProto.numSetupSoftApInterfaceFailureDueToHal);
1497         assertEquals(NUM_SOFTAP_ON_FAILURE_DUE_TO_WIFICOND,
1498                 mDecodedProto.numSetupSoftApInterfaceFailureDueToWificond);
1499         assertEquals(NUM_SOFTAP_ON_FAILURE_DUE_TO_HOSTAPD,
1500                 mDecodedProto.numSetupSoftApInterfaceFailureDueToHostapd);
1501         assertEquals(NUM_CLIENT_INTERFACE_DOWN, mDecodedProto.numClientInterfaceDown);
1502         assertEquals(NUM_SOFTAP_INTERFACE_DOWN, mDecodedProto.numSoftApInterfaceDown);
1503         assertEquals(NUM_PASSPOINT_PROVIDERS, mDecodedProto.numPasspointProviders);
1504         assertPasspointProfileTypeCount(mDecodedProto.installedPasspointProfileTypeForR1);
1505         assertPasspointProfileTypeCount(mDecodedProto.installedPasspointProfileTypeForR2);
1506         assertEquals(NUM_PASSPOINT_PROVIDER_INSTALLATION,
1507                 mDecodedProto.numPasspointProviderInstallation);
1508         assertEquals(NUM_PASSPOINT_PROVIDER_INSTALL_SUCCESS,
1509                 mDecodedProto.numPasspointProviderInstallSuccess);
1510         assertEquals(NUM_PASSPOINT_PROVIDER_UNINSTALLATION,
1511                 mDecodedProto.numPasspointProviderUninstallation);
1512         assertEquals(NUM_PASSPOINT_PROVIDER_UNINSTALL_SUCCESS,
1513                 mDecodedProto.numPasspointProviderUninstallSuccess);
1514         assertEquals(NUM_PASSPOINT_PROVIDERS_SUCCESSFULLY_CONNECTED,
1515                 mDecodedProto.numPasspointProvidersSuccessfullyConnected);
1516         assertEquals(NUM_PASSPOINT_PROVIDERS_WITH_NO_ROOT_CA,
1517                 mDecodedProto.numPasspointProviderWithNoRootCa);
1518         assertEquals(NUM_PASSPOINT_PROVIDERS_WITH_SELF_SIGNED_ROOT_CA,
1519                 mDecodedProto.numPasspointProviderWithSelfSignedRootCa);
1520         assertEquals(NUM_PASSPOINT_PROVIDERS_WITH_EXPIRATION_DATE,
1521                 mDecodedProto.numPasspointProviderWithSubscriptionExpiration);
1522         assertEquals(NUM_BSSID_SELECTION_DIFFERENT_BETWEEN_FRAMEWORK_FIRMWARE,
1523                 mDecodedProto.numBssidDifferentSelectionBetweenFrameworkAndFirmware);
1524 
1525         assertEquals(NUM_RADIO_MODE_CHANGE_TO_MCC, mDecodedProto.numRadioModeChangeToMcc);
1526         assertEquals(NUM_RADIO_MODE_CHANGE_TO_SCC, mDecodedProto.numRadioModeChangeToScc);
1527         assertEquals(NUM_RADIO_MODE_CHANGE_TO_SBS, mDecodedProto.numRadioModeChangeToSbs);
1528         assertEquals(NUM_RADIO_MODE_CHANGE_TO_DBS, mDecodedProto.numRadioModeChangeToDbs);
1529         assertEquals(NUM_SOFTAP_USER_BAND_PREFERENCE_UNSATISFIED,
1530                 mDecodedProto.numSoftApUserBandPreferenceUnsatisfied);
1531 
1532         PnoScanMetrics pno_metrics = mDecodedProto.pnoScanMetrics;
1533         assertNotNull(pno_metrics);
1534         assertEquals(NUM_PNO_SCAN_ATTEMPTS, pno_metrics.numPnoScanAttempts);
1535         assertEquals(NUM_PNO_SCAN_FAILED, pno_metrics.numPnoScanFailed);
1536         assertEquals(NUM_PNO_FOUND_NETWORK_EVENTS, pno_metrics.numPnoFoundNetworkEvents);
1537 
1538         for (ConnectToNetworkNotificationAndActionCount notificationCount
1539                 : mDecodedProto.connectToNetworkNotificationCount) {
1540             assertEquals(NUM_CONNECT_TO_NETWORK_NOTIFICATIONS[notificationCount.notification],
1541                     notificationCount.count);
1542             assertEquals(ConnectToNetworkNotificationAndActionCount.RECOMMENDER_OPEN,
1543                     notificationCount.recommender);
1544         }
1545         for (ConnectToNetworkNotificationAndActionCount notificationActionCount
1546                 : mDecodedProto.connectToNetworkNotificationActionCount) {
1547             assertEquals(NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS
1548                             [notificationActionCount.notification]
1549                             [notificationActionCount.action],
1550                     notificationActionCount.count);
1551             assertEquals(ConnectToNetworkNotificationAndActionCount.RECOMMENDER_OPEN,
1552                     notificationActionCount.recommender);
1553         }
1554 
1555         assertEquals(SIZE_OPEN_NETWORK_RECOMMENDER_BLOCKLIST,
1556                 mDecodedProto.openNetworkRecommenderBlocklistSize);
1557         assertEquals(IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
1558                 mDecodedProto.isWifiNetworksAvailableNotificationOn);
1559         assertEquals(NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES,
1560                 mDecodedProto.numOpenNetworkRecommendationUpdates);
1561         assertEquals(NUM_OPEN_NETWORK_CONNECT_MESSAGE_FAILED_TO_SEND,
1562                 mDecodedProto.numOpenNetworkConnectMessageFailedToSend);
1563 
1564         verifySoftApEventsStoredInProto();
1565 
1566         assertEquals(NUM_WATCHDOG_SUCCESS_DURATION_MS,
1567                 mDecodedProto.watchdogTriggerToConnectionSuccessDurationMs);
1568         assertEquals(IS_MAC_RANDOMIZATION_ON, mDecodedProto.isMacRandomizationOn);
1569         assertEquals(WIFI_POWER_METRICS_LOGGING_DURATION,
1570                 mDecodedProto.wifiRadioUsage.loggingDurationMs);
1571         assertEquals(WIFI_POWER_METRICS_SCAN_TIME,
1572                 mDecodedProto.wifiRadioUsage.scanTimeMs);
1573         assertEquals(WIFI_IS_UNUSABLE_EVENT_LOGGING_SETTING,
1574                 mDecodedProto.experimentValues.wifiIsUnusableLoggingEnabled);
1575         assertEquals(LINK_SPEED_COUNTS_LOGGING_SETTING,
1576                 mDecodedProto.experimentValues.linkSpeedCountsLoggingEnabled);
1577         assertEquals(DATA_STALL_MIN_TX_BAD_SETTING,
1578                 mDecodedProto.experimentValues.wifiDataStallMinTxBad);
1579         assertEquals(DATA_STALL_MIN_TX_SUCCESS_WITHOUT_RX_SETTING,
1580                 mDecodedProto.experimentValues.wifiDataStallMinTxSuccessWithoutRx);
1581         assertEquals(NUM_ONESHOT_SCAN_REQUESTS_WITH_DFS_CHANNELS,
1582                 mDecodedProto.numOneshotHasDfsChannelScans);
1583         assertEquals(NUM_ADD_OR_UPDATE_NETWORK_CALLS, mDecodedProto.numAddOrUpdateNetworkCalls);
1584         assertEquals(NUM_ENABLE_NETWORK_CALLS, mDecodedProto.numEnableNetworkCalls);
1585         assertEquals(NUM_IP_RENEWAL_FAILURE, mDecodedProto.numIpRenewalFailure);
1586         assertEquals(NUM_NETWORK_ABNORMAL_ASSOC_REJECTION,
1587                 mDecodedProto.healthMonitorMetrics.failureStatsIncrease.cntAssocRejection);
1588         assertEquals(NUM_NETWORK_ABNORMAL_CONNECTION_FAILURE_DISCONNECTION,
1589                 mDecodedProto.healthMonitorMetrics.failureStatsDecrease
1590                         .cntDisconnectionNonlocalConnecting);
1591         assertEquals(0,
1592                 mDecodedProto.healthMonitorMetrics.failureStatsIncrease.cntAssocTimeout);
1593         assertEquals(NUM_NETWORK_SUFFICIENT_RECENT_STATS_ONLY,
1594                 mDecodedProto.healthMonitorMetrics.numNetworkSufficientRecentStatsOnly);
1595         assertEquals(NUM_NETWORK_SUFFICIENT_RECENT_PREV_STATS,
1596                 mDecodedProto.healthMonitorMetrics.numNetworkSufficientRecentPrevStats);
1597         assertEquals(NUM_BSSID_FILTERED_DUE_TO_MBO_ASSOC_DISALLOW_IND,
1598                 mDecodedProto.numBssidFilteredDueToMboAssocDisallowInd);
1599         assertEquals(NUM_STEERING_REQUEST,
1600                 mDecodedProto.numSteeringRequest);
1601         assertEquals(NUM_FORCE_SCAN_DUE_TO_STEERING_REQUEST,
1602                 mDecodedProto.numForceScanDueToSteeringRequest);
1603         assertEquals(NUM_MBO_CELLULAR_SWITCH_REQUEST,
1604                 mDecodedProto.numMboCellularSwitchRequest);
1605         assertEquals(NUM_STEERING_REQUEST_INCLUDING_MBO_ASSOC_RETRY_DELAY,
1606                 mDecodedProto.numSteeringRequestIncludingMboAssocRetryDelay);
1607         assertEquals(NUM_CONNECT_REQUEST_WITH_FILS_AKM,
1608                 mDecodedProto.numConnectRequestWithFilsAkm);
1609         assertEquals(NUM_L2_CONNECTION_THROUGH_FILS_AUTHENTICATION,
1610                 mDecodedProto.numL2ConnectionThroughFilsAuthentication);
1611         assertEquals(WIFI_MAINLINE_MODULE_VERSION, mDecodedProto.mainlineModuleVersion);
1612 
1613     }
1614 
1615     @Test
testHalCrashSoftApFailureCount()1616     public void testHalCrashSoftApFailureCount() throws Exception {
1617         mWifiMetrics.incrementNumHalCrashes();
1618         mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();
1619         ExtendedMockito.verify(() -> WifiStatsLog.write(
1620                 WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED,
1621                 WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED__TYPE__SOFT_AP_FAILURE_HOSTAPD));
1622         ExtendedMockito.verify(() -> WifiStatsLog.write(
1623                 WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED,
1624                 WifiStatsLog.WIFI_SETUP_FAILURE_CRASH_REPORTED__TYPE__HAL_CRASH));
1625     }
1626 
1627     /**
1628      *  Assert deserialized metrics Scan Return Entry equals count
1629      */
assertScanReturnEntryEquals(int returnCode, int count)1630     public void assertScanReturnEntryEquals(int returnCode, int count) {
1631         for (int i = 0; i < mDecodedProto.scanReturnEntries.length; i++) {
1632             if (mDecodedProto.scanReturnEntries[i].scanReturnCode == returnCode) {
1633                 assertEquals(count, mDecodedProto.scanReturnEntries[i].scanResultsCount);
1634                 return;
1635             }
1636         }
1637         assertEquals(null, count);
1638     }
1639 
1640     /**
1641      *  Assert deserialized metrics SystemState entry equals count
1642      */
assertSystemStateEntryEquals(int state, boolean screenOn, int count)1643     public void assertSystemStateEntryEquals(int state, boolean screenOn, int count) {
1644         for (int i = 0; i < mDecodedProto.wifiSystemStateEntries.length; i++) {
1645             if (mDecodedProto.wifiSystemStateEntries[i].wifiState == state
1646                     && mDecodedProto.wifiSystemStateEntries[i].isScreenOn == screenOn) {
1647                 assertEquals(count, mDecodedProto.wifiSystemStateEntries[i].wifiStateCount);
1648                 return;
1649             }
1650         }
1651         assertEquals(null, count);
1652     }
1653 
1654     /**
1655      * Test the number of Passpoint provision with the failure code are collected correctly
1656      *
1657      * @throws Exception
1658      */
1659     @Test
testPasspointProvisionMetrics()1660     public void testPasspointProvisionMetrics() throws Exception {
1661         //Increment count for provisioning success.
1662         mWifiMetrics.incrementPasspointProvisionSuccess();
1663 
1664         // Increment count for provisioning unavailable
1665         mWifiMetrics.incrementPasspointProvisionFailure(
1666                 ProvisioningCallback.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE);
1667         mWifiMetrics.incrementPasspointProvisionFailure(
1668                 ProvisioningCallback.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE);
1669 
1670         // Increment count for server connection failure
1671         mWifiMetrics.incrementPasspointProvisionFailure(
1672                 ProvisioningCallback.OSU_FAILURE_AP_CONNECTION);
1673 
1674         // Dump proto and deserialize
1675         dumpProtoAndDeserialize();
1676 
1677         assertEquals(mDecodedProto.passpointProvisionStats.numProvisionSuccess, 1);
1678         assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount.length, 2);
1679         assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[0].failureCode,
1680                 PasspointProvisionStats.OSU_FAILURE_AP_CONNECTION);
1681         assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[0].count, 1);
1682         assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[1].failureCode,
1683                 PasspointProvisionStats.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE);
1684         assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[1].count, 2);
1685     }
1686 
1687     /**
1688      * Combination of all other WifiMetrics unit tests, an internal-integration test, or functional
1689      * test
1690      */
1691     @Test
setMetricsSerializeDeserializeAssertMetricsSame()1692     public void setMetricsSerializeDeserializeAssertMetricsSame() throws Exception {
1693         setAndIncrementMetrics();
1694         startAndEndConnectionEventSucceeds();
1695         dumpProtoAndDeserialize();
1696         assertDeserializedMetricsCorrect();
1697         assertEquals("mDecodedProto.connectionEvent.length",
1698                 2, mDecodedProto.connectionEvent.length);
1699         //<TODO> test individual connectionEvents for correctness,
1700         // check scanReturnEntries & wifiSystemStateEntries counts and individual elements
1701         // pending their implementation</TODO>
1702     }
1703 
1704     /**
1705      * Test that score breach events are properly generated
1706      */
1707     @Test
testScoreBeachEvents()1708     public void testScoreBeachEvents() throws Exception {
1709         int upper = WifiMetrics.LOW_WIFI_SCORE + 7;
1710         int mid = WifiMetrics.LOW_WIFI_SCORE;
1711         int lower = WifiMetrics.LOW_WIFI_SCORE - 8;
1712         mWifiMetrics.setWifiState(TEST_IFACE_NAME, WifiMetricsProto.WifiLog.WIFI_ASSOCIATED);
1713         for (int score = upper; score >= mid; score--) {
1714             mWifiMetrics.incrementWifiScoreCount(TEST_IFACE_NAME, score);
1715         }
1716         mWifiMetrics.incrementWifiScoreCount(TEST_IFACE_NAME, mid + 1);
1717         mWifiMetrics.incrementWifiScoreCount(TEST_IFACE_NAME, lower); // First breach
1718         for (int score = lower; score <= mid; score++) {
1719             mWifiMetrics.incrementWifiScoreCount(TEST_IFACE_NAME, score);
1720         }
1721         mWifiMetrics.incrementWifiScoreCount(TEST_IFACE_NAME, mid - 1);
1722         mWifiMetrics.incrementWifiScoreCount(TEST_IFACE_NAME, upper); // Second breach
1723 
1724         dumpProtoAndDeserialize();
1725 
1726         assertEquals(2, mDecodedProto.staEventList.length);
1727         assertEquals(StaEvent.TYPE_SCORE_BREACH, mDecodedProto.staEventList[0].type);
1728         assertEquals(TEST_IFACE_NAME, mDecodedProto.staEventList[0].interfaceName);
1729         assertEquals(lower, mDecodedProto.staEventList[0].lastScore);
1730         assertEquals(StaEvent.TYPE_SCORE_BREACH, mDecodedProto.staEventList[1].type);
1731         assertEquals(TEST_IFACE_NAME, mDecodedProto.staEventList[1].interfaceName);
1732         assertEquals(upper, mDecodedProto.staEventList[1].lastScore);
1733     }
1734 
1735     /**
1736      * Test that Wifi usability score breach events are properly generated
1737      */
1738     @Test
testWifiUsabilityScoreBreachEvents()1739     public void testWifiUsabilityScoreBreachEvents() throws Exception {
1740         int upper = WifiMetrics.LOW_WIFI_USABILITY_SCORE + 7;
1741         int mid = WifiMetrics.LOW_WIFI_USABILITY_SCORE;
1742         int lower = WifiMetrics.LOW_WIFI_USABILITY_SCORE - 8;
1743         mWifiMetrics.setWifiState(TEST_IFACE_NAME, WifiMetricsProto.WifiLog.WIFI_ASSOCIATED);
1744         for (int score = upper; score >= mid; score--) {
1745             mWifiMetrics.incrementWifiUsabilityScoreCount(TEST_IFACE_NAME, 1, score, 15);
1746         }
1747         mWifiMetrics.incrementWifiUsabilityScoreCount(TEST_IFACE_NAME, 1, mid + 1, 15);
1748         // First breach
1749         mWifiMetrics.incrementWifiUsabilityScoreCount(TEST_IFACE_NAME, 1, lower, 15);
1750         for (int score = lower; score <= mid; score++) {
1751             mWifiMetrics.incrementWifiUsabilityScoreCount(TEST_IFACE_NAME, 1, score, 15);
1752         }
1753         mWifiMetrics.incrementWifiUsabilityScoreCount(TEST_IFACE_NAME, 1, mid - 1, 15);
1754         // Second breach
1755         mWifiMetrics.incrementWifiUsabilityScoreCount(TEST_IFACE_NAME, 1, upper, 15);
1756 
1757         dumpProtoAndDeserialize();
1758 
1759         assertEquals(2, mDecodedProto.staEventList.length);
1760         assertEquals(StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH, mDecodedProto.staEventList[0].type);
1761         assertEquals(lower, mDecodedProto.staEventList[0].lastWifiUsabilityScore);
1762         assertEquals(StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH, mDecodedProto.staEventList[1].type);
1763         assertEquals(upper, mDecodedProto.staEventList[1].lastWifiUsabilityScore);
1764     }
1765 
1766     /**
1767      * Test that WifiMetrics is correctly getting data from ScanDetail and WifiConfiguration
1768      */
1769     @Test
testScanDetailAndWifiConfigurationUsage()1770     public void testScanDetailAndWifiConfigurationUsage() throws Exception {
1771         setupNetworkAndVerify();
1772     }
1773 
1774     /**
1775      * Test that WifiMetrics is correctly getting data from ScanDetail and WifiConfiguration for
1776      * Passpoint use cases.
1777      */
1778     @Test
testScanDetailAndWifiConfigurationUsageForPasspoint()1779     public void testScanDetailAndWifiConfigurationUsageForPasspoint() throws Exception {
1780         setupNetworkAndVerify(true, false);
1781         setupNetworkAndVerify(true, true);
1782     }
1783 
1784     private static final String SSID = "red";
1785     private static final int CONFIG_DTIM = 3;
1786     private static final int NETWORK_DETAIL_WIFIMODE = 5;
1787     private static final int NETWORK_DETAIL_DTIM = 7;
1788     private static final int SCAN_RESULT_LEVEL = -30;
1789 
setupNetworkAndVerify()1790     private void setupNetworkAndVerify() throws Exception {
1791         setupNetworkAndVerify(false, false);
1792     }
1793 
setupNetworkAndVerify(boolean isPasspoint, boolean isPasspointHomeProvider)1794     private void setupNetworkAndVerify(boolean isPasspoint, boolean isPasspointHomeProvider)
1795             throws Exception {
1796         //Setup mock configs and scan details
1797         NetworkDetail networkDetail = mock(NetworkDetail.class);
1798         when(networkDetail.getWifiMode()).thenReturn(NETWORK_DETAIL_WIFIMODE);
1799         when(networkDetail.getSSID()).thenReturn(SSID);
1800         when(networkDetail.getDtimInterval()).thenReturn(NETWORK_DETAIL_DTIM);
1801         ScanResult scanResult = mock(ScanResult.class);
1802         scanResult.level = SCAN_RESULT_LEVEL;
1803         scanResult.capabilities = "EAP/SHA1";
1804         WifiConfiguration config = mock(WifiConfiguration.class);
1805         config.SSID = "\"" + SSID + "\"";
1806         config.dtimInterval = CONFIG_DTIM;
1807         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_AUTO;
1808         config.allowedKeyManagement = new BitSet();
1809         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
1810         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
1811         config.enterpriseConfig = new WifiEnterpriseConfig();
1812         config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS);
1813         config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAPV2);
1814         config.enterpriseConfig.setOcsp(WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS);
1815         WifiConfiguration.NetworkSelectionStatus networkSelectionStat =
1816                 mock(WifiConfiguration.NetworkSelectionStatus.class);
1817         when(networkSelectionStat.getCandidate()).thenReturn(scanResult);
1818         when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStat);
1819         ScanDetail scanDetail = mock(ScanDetail.class);
1820         when(scanDetail.getNetworkDetail()).thenReturn(networkDetail);
1821         when(scanDetail.getScanResult()).thenReturn(scanResult);
1822         when(networkDetail.isMboSupported()).thenReturn(true);
1823         when(networkDetail.isOceSupported()).thenReturn(true);
1824 
1825         config.networkId = TEST_NETWORK_ID;
1826         mWifiMetrics.setNominatorForNetwork(TEST_NETWORK_ID,
1827                 WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL);
1828 
1829         when(config.isPasspoint()).thenReturn(isPasspoint);
1830         config.isHomeProviderNetwork = isPasspointHomeProvider;
1831 
1832         //Create a connection event using only the config
1833         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, config,
1834                 "Red", WifiMetricsProto.ConnectionEvent.ROAM_NONE);
1835         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
1836                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
1837                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
1838                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
1839 
1840         //Change configuration to open without randomization
1841         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
1842         scanResult.capabilities = "";
1843 
1844         //Create a connection event using the config and a scan detail
1845         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, config,
1846                 "Green", WifiMetricsProto.ConnectionEvent.ROAM_NONE);
1847         mWifiMetrics.setConnectionScanDetail(TEST_IFACE_NAME, scanDetail);
1848         mWifiMetrics.logBugReport();
1849         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
1850                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
1851                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
1852                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
1853 
1854         //Dump proto from mWifiMetrics and deserialize it to mDecodedProto
1855         dumpProtoAndDeserialize();
1856 
1857         //Check that the correct values are being flowed through
1858         assertEquals(2, mDecodedProto.connectionEvent.length);
1859         assertEquals(CONFIG_DTIM, mDecodedProto.connectionEvent[0].routerFingerprint.dtim);
1860         assertEquals(WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE,
1861                 mDecodedProto.connectionEvent[0].routerFingerprint.authentication);
1862         assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_EAP_TTLS,
1863                 mDecodedProto.connectionEvent[0].routerFingerprint.eapMethod);
1864         assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_MSCHAPV2,
1865                 mDecodedProto.connectionEvent[0].routerFingerprint.authPhase2Method);
1866         assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_REQUIRE_CERT_STATUS,
1867                 mDecodedProto.connectionEvent[0].routerFingerprint.ocspType);
1868         assertEquals(SCAN_RESULT_LEVEL, mDecodedProto.connectionEvent[0].signalStrength);
1869         assertEquals(NETWORK_DETAIL_DTIM, mDecodedProto.connectionEvent[1].routerFingerprint.dtim);
1870         assertEquals(WifiMetricsProto.RouterFingerPrint.AUTH_OPEN,
1871                 mDecodedProto.connectionEvent[1].routerFingerprint.authentication);
1872         assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_EAP_UNKNOWN,
1873                 mDecodedProto.connectionEvent[1].routerFingerprint.eapMethod);
1874         assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_NONE,
1875                 mDecodedProto.connectionEvent[1].routerFingerprint.authPhase2Method);
1876         assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_OCSP_NONE,
1877                 mDecodedProto.connectionEvent[1].routerFingerprint.ocspType);
1878         assertEquals(SCAN_RESULT_LEVEL, mDecodedProto.connectionEvent[1].signalStrength);
1879         assertEquals(NETWORK_DETAIL_WIFIMODE,
1880                 mDecodedProto.connectionEvent[1].routerFingerprint.routerTechnology);
1881         assertFalse(mDecodedProto.connectionEvent[0].automaticBugReportTaken);
1882         assertTrue(mDecodedProto.connectionEvent[1].automaticBugReportTaken);
1883         assertTrue(mDecodedProto.connectionEvent[0].useRandomizedMac);
1884         assertFalse(mDecodedProto.connectionEvent[1].useRandomizedMac);
1885         assertEquals(WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL,
1886                 mDecodedProto.connectionEvent[0].connectionNominator);
1887         assertEquals(1, mDecodedProto.numConnectToNetworkSupportingMbo);
1888         assertEquals(1, mDecodedProto.numConnectToNetworkSupportingOce);
1889         assertEquals(isPasspoint, mDecodedProto.connectionEvent[0].routerFingerprint.passpoint);
1890         assertEquals(isPasspointHomeProvider,
1891                 mDecodedProto.connectionEvent[0].routerFingerprint.isPasspointHomeProvider);
1892     }
1893 
1894     /**
1895      * Tests that the mapping from networkId to nominatorId is not cleared.
1896      */
1897     @Test
testNetworkToNominatorNotCleared()1898     public void testNetworkToNominatorNotCleared() throws Exception {
1899         //Setup mock configs and scan details
1900         NetworkDetail networkDetail = mock(NetworkDetail.class);
1901         when(networkDetail.getWifiMode()).thenReturn(NETWORK_DETAIL_WIFIMODE);
1902         when(networkDetail.getSSID()).thenReturn(SSID);
1903         when(networkDetail.getDtimInterval()).thenReturn(NETWORK_DETAIL_DTIM);
1904         ScanResult scanResult = mock(ScanResult.class);
1905         scanResult.level = SCAN_RESULT_LEVEL;
1906         WifiConfiguration config = mock(WifiConfiguration.class);
1907         config.SSID = "\"" + SSID + "\"";
1908         config.dtimInterval = CONFIG_DTIM;
1909         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_AUTO;
1910         config.allowedKeyManagement = new BitSet();
1911         WifiConfiguration.NetworkSelectionStatus networkSelectionStat =
1912                 mock(WifiConfiguration.NetworkSelectionStatus.class);
1913         when(networkSelectionStat.getCandidate()).thenReturn(scanResult);
1914         when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStat);
1915         ScanDetail scanDetail = mock(ScanDetail.class);
1916         when(scanDetail.getNetworkDetail()).thenReturn(networkDetail);
1917         when(scanDetail.getScanResult()).thenReturn(scanResult);
1918 
1919         config.networkId = TEST_NETWORK_ID;
1920         mWifiMetrics.setNominatorForNetwork(TEST_NETWORK_ID,
1921                 WifiMetricsProto.ConnectionEvent.NOMINATOR_CARRIER);
1922 
1923         // dump() calls clear() internally
1924         mWifiMetrics.dump(null, new PrintWriter(new StringWriter()),
1925                 new String[]{WifiMetrics.PROTO_DUMP_ARG});
1926 
1927         // Create a connection event using only the config
1928         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, config,
1929                 "Red", WifiMetricsProto.ConnectionEvent.ROAM_NONE);
1930         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
1931                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
1932                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
1933                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
1934 
1935         dumpProtoAndDeserialize();
1936 
1937         assertEquals(WifiMetricsProto.ConnectionEvent.NOMINATOR_CARRIER,
1938                 mDecodedProto.connectionEvent[0].connectionNominator);
1939     }
1940 
1941     /**
1942      * Test that WifiMetrics is serializing/deserializing association time out events.
1943      */
1944     @Test
testMetricsAssociationTimedOut()1945     public void testMetricsAssociationTimedOut() throws Exception {
1946         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, null,
1947                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_NONE);
1948         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
1949                 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
1950                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
1951                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
1952 
1953         //Dump proto and deserialize
1954         //This should clear all the metrics in mWifiMetrics,
1955         dumpProtoAndDeserialize();
1956         //Check there is only 1 connection events
1957         assertEquals(1, mDecodedProto.connectionEvent.length);
1958         assertEquals(WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
1959                 mDecodedProto.connectionEvent[0].level2FailureCode);
1960         assertEquals(WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN,
1961                 mDecodedProto.connectionEvent[0].level2FailureReason);
1962     }
1963 
1964     /**
1965      * Verify the logging of number of blocked BSSIDs in ConnectionEvent.
1966      */
1967     @Test
testMetricNumBssidInBlocklist()1968     public void testMetricNumBssidInBlocklist() throws Exception {
1969         WifiConfiguration config = mock(WifiConfiguration.class);
1970         config.SSID = "\"" + SSID + "\"";
1971         config.allowedKeyManagement = new BitSet();
1972         when(config.getNetworkSelectionStatus()).thenReturn(
1973                 mock(WifiConfiguration.NetworkSelectionStatus.class));
1974         when(mWifiBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid(eq(config.SSID)))
1975                 .thenReturn(3);
1976         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, config,
1977                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_NONE);
1978         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
1979                 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
1980                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
1981                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
1982         dumpProtoAndDeserialize();
1983 
1984         assertEquals(1, mDecodedProto.connectionEvent.length);
1985         assertEquals(3, mDecodedProto.connectionEvent[0].numBssidInBlocklist);
1986     }
1987 
1988     /**
1989      * Verify the ConnectionEvent is labeled with networkType open network correctly.
1990      */
1991     @Test
testConnectionNetworkTypeOpen()1992     public void testConnectionNetworkTypeOpen() throws Exception {
1993         WifiConfiguration config = mock(WifiConfiguration.class);
1994         config.SSID = "\"" + SSID + "\"";
1995         config.allowedKeyManagement = new BitSet();
1996         when(config.getNetworkSelectionStatus()).thenReturn(
1997                 mock(WifiConfiguration.NetworkSelectionStatus.class));
1998         when(config.isOpenNetwork()).thenReturn(true);
1999         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, config,
2000                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_NONE);
2001         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
2002                 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
2003                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
2004                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
2005         dumpProtoAndDeserialize();
2006 
2007         assertEquals(1, mDecodedProto.connectionEvent.length);
2008         assertEquals(WifiMetricsProto.ConnectionEvent.TYPE_OPEN,
2009                 mDecodedProto.connectionEvent[0].networkType);
2010         assertFalse(mDecodedProto.connectionEvent[0].isOsuProvisioned);
2011     }
2012 
2013     @Test
testStart2ConnectionEventsOnDifferentIfaces_endOneAndDump_endOtherAndDump()2014     public void testStart2ConnectionEventsOnDifferentIfaces_endOneAndDump_endOtherAndDump()
2015             throws Exception {
2016         WifiConfiguration config1 = WifiConfigurationTestUtil.createPskNetwork();
2017         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, config1, "RED",
2018                 WifiMetricsProto.ConnectionEvent.ROAM_DBDC);
2019         WifiConfiguration config2 = WifiConfigurationTestUtil.createOpenNetwork();
2020         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME2, config2, "BLUE",
2021                 WifiMetricsProto.ConnectionEvent.ROAM_USER_SELECTED);
2022 
2023         mWifiMetrics.setConnectionScanDetail(TEST_IFACE_NAME, mock(ScanDetail.class));
2024         mWifiMetrics.setConnectionPmkCache(TEST_IFACE_NAME, false);
2025         mWifiMetrics.setConnectionMaxSupportedLinkSpeedMbps(TEST_IFACE_NAME, 100, 50);
2026 
2027         mWifiMetrics.setConnectionScanDetail(TEST_IFACE_NAME2, mock(ScanDetail.class));
2028         mWifiMetrics.setConnectionPmkCache(TEST_IFACE_NAME2, true);
2029         mWifiMetrics.setConnectionMaxSupportedLinkSpeedMbps(TEST_IFACE_NAME2, 400, 200);
2030 
2031         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME2,
2032                 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
2033                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
2034                 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_TIMEOUT, 5745);
2035 
2036         dumpProtoAndDeserialize();
2037 
2038         assertEquals(1, mDecodedProto.connectionEvent.length);
2039         WifiMetricsProto.ConnectionEvent connectionEvent = mDecodedProto.connectionEvent[0];
2040         assertEquals(TEST_IFACE_NAME2, connectionEvent.interfaceName);
2041         assertTrue(connectionEvent.routerFingerprint.pmkCacheEnabled);
2042         assertEquals(400, connectionEvent.routerFingerprint.maxSupportedTxLinkSpeedMbps);
2043         assertEquals(200, connectionEvent.routerFingerprint.maxSupportedRxLinkSpeedMbps);
2044         assertEquals(WifiMetricsProto.ConnectionEvent.ROAM_USER_SELECTED, connectionEvent.roamType);
2045         assertEquals(WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_TIMEOUT,
2046                 connectionEvent.level2FailureReason);
2047 
2048         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
2049                 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION,
2050                 WifiMetricsProto.ConnectionEvent.HLF_DHCP,
2051                 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD, 2412);
2052 
2053         dumpProtoAndDeserialize();
2054 
2055         assertEquals(1, mDecodedProto.connectionEvent.length);
2056         connectionEvent = mDecodedProto.connectionEvent[0];
2057         assertEquals(TEST_IFACE_NAME, connectionEvent.interfaceName);
2058         assertFalse(connectionEvent.routerFingerprint.pmkCacheEnabled);
2059         assertEquals(100, connectionEvent.routerFingerprint.maxSupportedTxLinkSpeedMbps);
2060         assertEquals(50, connectionEvent.routerFingerprint.maxSupportedRxLinkSpeedMbps);
2061         assertEquals(WifiMetricsProto.ConnectionEvent.ROAM_DBDC, connectionEvent.roamType);
2062         assertEquals(WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD,
2063                 connectionEvent.level2FailureReason);
2064     }
2065 
2066     @Test
testStart2ConnectionEventsOnDifferentIfaces_end2AndDump()2067     public void testStart2ConnectionEventsOnDifferentIfaces_end2AndDump() throws Exception {
2068         WifiConfiguration config1 = WifiConfigurationTestUtil.createPskNetwork();
2069         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, config1, "RED",
2070                 WifiMetricsProto.ConnectionEvent.ROAM_DBDC);
2071         WifiConfiguration config2 = WifiConfigurationTestUtil.createOpenNetwork();
2072         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME2, config2, "BLUE",
2073                 WifiMetricsProto.ConnectionEvent.ROAM_USER_SELECTED);
2074 
2075         mWifiMetrics.setConnectionScanDetail(TEST_IFACE_NAME, mock(ScanDetail.class));
2076         mWifiMetrics.setConnectionPmkCache(TEST_IFACE_NAME, false);
2077         mWifiMetrics.setConnectionMaxSupportedLinkSpeedMbps(TEST_IFACE_NAME, 100, 50);
2078 
2079         mWifiMetrics.setConnectionScanDetail(TEST_IFACE_NAME2, mock(ScanDetail.class));
2080         mWifiMetrics.setConnectionPmkCache(TEST_IFACE_NAME2, true);
2081         mWifiMetrics.setConnectionMaxSupportedLinkSpeedMbps(TEST_IFACE_NAME2, 400, 200);
2082 
2083         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
2084                 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION,
2085                 WifiMetricsProto.ConnectionEvent.HLF_DHCP,
2086                 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD, 2412);
2087 
2088         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME2,
2089                 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
2090                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
2091                 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_TIMEOUT, 5745);
2092 
2093         dumpProtoAndDeserialize();
2094 
2095         assertEquals(2, mDecodedProto.connectionEvent.length);
2096 
2097         WifiMetricsProto.ConnectionEvent connectionEvent = mDecodedProto.connectionEvent[0];
2098         assertEquals(TEST_IFACE_NAME, connectionEvent.interfaceName);
2099         assertFalse(connectionEvent.routerFingerprint.pmkCacheEnabled);
2100         assertEquals(100, connectionEvent.routerFingerprint.maxSupportedTxLinkSpeedMbps);
2101         assertEquals(50, connectionEvent.routerFingerprint.maxSupportedRxLinkSpeedMbps);
2102         assertEquals(WifiMetricsProto.ConnectionEvent.ROAM_DBDC, connectionEvent.roamType);
2103         assertEquals(WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD,
2104                 connectionEvent.level2FailureReason);
2105 
2106         connectionEvent = mDecodedProto.connectionEvent[1];
2107         assertEquals(TEST_IFACE_NAME2, connectionEvent.interfaceName);
2108         assertTrue(connectionEvent.routerFingerprint.pmkCacheEnabled);
2109         assertEquals(400, connectionEvent.routerFingerprint.maxSupportedTxLinkSpeedMbps);
2110         assertEquals(200, connectionEvent.routerFingerprint.maxSupportedRxLinkSpeedMbps);
2111         assertEquals(WifiMetricsProto.ConnectionEvent.ROAM_USER_SELECTED, connectionEvent.roamType);
2112         assertEquals(WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_TIMEOUT,
2113                 connectionEvent.level2FailureReason);
2114     }
2115 
2116     @Test
testStartAndEnd2ConnectionEventsOnDifferentIfacesAndDump()2117     public void testStartAndEnd2ConnectionEventsOnDifferentIfacesAndDump() throws Exception {
2118         WifiConfiguration config1 = WifiConfigurationTestUtil.createPskNetwork();
2119         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, config1, "RED",
2120                 WifiMetricsProto.ConnectionEvent.ROAM_DBDC);
2121         mWifiMetrics.setConnectionScanDetail(TEST_IFACE_NAME, mock(ScanDetail.class));
2122         mWifiMetrics.setConnectionPmkCache(TEST_IFACE_NAME, false);
2123         mWifiMetrics.setConnectionMaxSupportedLinkSpeedMbps(TEST_IFACE_NAME, 100, 50);
2124         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
2125                 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION,
2126                 WifiMetricsProto.ConnectionEvent.HLF_DHCP,
2127                 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD, 2412);
2128 
2129         WifiConfiguration config2 = WifiConfigurationTestUtil.createOpenNetwork();
2130         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME2, config2, "BLUE",
2131                 WifiMetricsProto.ConnectionEvent.ROAM_USER_SELECTED);
2132         mWifiMetrics.setConnectionScanDetail(TEST_IFACE_NAME2, mock(ScanDetail.class));
2133         mWifiMetrics.setConnectionPmkCache(TEST_IFACE_NAME2, true);
2134         mWifiMetrics.setConnectionMaxSupportedLinkSpeedMbps(TEST_IFACE_NAME2, 400, 200);
2135         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME2,
2136                 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
2137                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
2138                 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_TIMEOUT, 5745);
2139 
2140         dumpProtoAndDeserialize();
2141 
2142         assertEquals(2, mDecodedProto.connectionEvent.length);
2143 
2144         WifiMetricsProto.ConnectionEvent connectionEvent = mDecodedProto.connectionEvent[0];
2145         assertEquals(TEST_IFACE_NAME, connectionEvent.interfaceName);
2146         assertFalse(connectionEvent.routerFingerprint.pmkCacheEnabled);
2147         assertEquals(100, connectionEvent.routerFingerprint.maxSupportedTxLinkSpeedMbps);
2148         assertEquals(50, connectionEvent.routerFingerprint.maxSupportedRxLinkSpeedMbps);
2149         assertEquals(WifiMetricsProto.ConnectionEvent.ROAM_DBDC, connectionEvent.roamType);
2150         assertEquals(WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD,
2151                 connectionEvent.level2FailureReason);
2152 
2153         connectionEvent = mDecodedProto.connectionEvent[1];
2154         assertEquals(TEST_IFACE_NAME2, connectionEvent.interfaceName);
2155         assertTrue(connectionEvent.routerFingerprint.pmkCacheEnabled);
2156         assertEquals(400, connectionEvent.routerFingerprint.maxSupportedTxLinkSpeedMbps);
2157         assertEquals(200, connectionEvent.routerFingerprint.maxSupportedRxLinkSpeedMbps);
2158         assertEquals(WifiMetricsProto.ConnectionEvent.ROAM_USER_SELECTED, connectionEvent.roamType);
2159         assertEquals(WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_TIMEOUT,
2160                 connectionEvent.level2FailureReason);
2161     }
2162 
2163     @Test
testNonExistentConnectionEventIface_doesntCrash()2164     public void testNonExistentConnectionEventIface_doesntCrash() throws Exception {
2165         mWifiMetrics.setConnectionScanDetail("nonexistentIface", mock(ScanDetail.class));
2166         mWifiMetrics.setConnectionPmkCache("nonexistentIface", false);
2167         mWifiMetrics.setConnectionMaxSupportedLinkSpeedMbps("nonexistentIface", 100, 50);
2168         mWifiMetrics.endConnectionEvent("nonexistentIface",
2169                 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION,
2170                 WifiMetricsProto.ConnectionEvent.HLF_DHCP,
2171                 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD, 2412);
2172     }
2173 
2174     /**
2175      * Verify the ConnectionEvent is labeled with networkType Passpoint correctly.
2176      */
2177     @Test
testConnectionNetworkTypePasspoint()2178     public void testConnectionNetworkTypePasspoint() throws Exception {
2179         WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork();
2180         config.carrierMerged = true;
2181         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, config,
2182                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_NONE);
2183         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
2184                 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
2185                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
2186                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
2187         dumpProtoAndDeserialize();
2188 
2189         assertEquals(1, mDecodedProto.connectionEvent.length);
2190         assertEquals(WifiMetricsProto.ConnectionEvent.TYPE_PASSPOINT,
2191                 mDecodedProto.connectionEvent[0].networkType);
2192         assertFalse(mDecodedProto.connectionEvent[0].isOsuProvisioned);
2193         assertTrue(mDecodedProto.connectionEvent[0].isCarrierMerged);
2194     }
2195 
2196     /**
2197      * Verify the ConnectionEvent is created with correct creatorUid.
2198      */
2199     @Test
testConnectionCreatorUid()2200     public void testConnectionCreatorUid() throws Exception {
2201         WifiConfiguration config = mock(WifiConfiguration.class);
2202         config.SSID = "\"" + SSID + "\"";
2203         config.allowedKeyManagement = new BitSet();
2204         when(config.getNetworkSelectionStatus()).thenReturn(
2205                 mock(WifiConfiguration.NetworkSelectionStatus.class));
2206 
2207         // First network is created by the user
2208         config.fromWifiNetworkSuggestion = false;
2209         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, config,
2210                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_NONE);
2211         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
2212                 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
2213                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
2214                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
2215 
2216         // Second network is created by a carrier app
2217         config.fromWifiNetworkSuggestion = true;
2218         config.carrierId = 123;
2219         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, config,
2220                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_NONE);
2221         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
2222                 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
2223                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
2224                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
2225 
2226         // Third network is created by an unknown app
2227         config.fromWifiNetworkSuggestion = true;
2228         config.carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
2229         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, config,
2230                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_NONE);
2231         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
2232                 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
2233                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
2234                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
2235 
2236         dumpProtoAndDeserialize();
2237 
2238         assertEquals(3, mDecodedProto.connectionEvent.length);
2239         assertEquals(WifiMetricsProto.ConnectionEvent.CREATOR_USER,
2240                 mDecodedProto.connectionEvent[0].networkCreator);
2241         assertEquals(WifiMetricsProto.ConnectionEvent.CREATOR_CARRIER,
2242                 mDecodedProto.connectionEvent[1].networkCreator);
2243         assertEquals(WifiMetricsProto.ConnectionEvent.CREATOR_UNKNOWN,
2244                 mDecodedProto.connectionEvent[2].networkCreator);
2245     }
2246 
2247     /**
2248      * Test that WifiMetrics is serializing/deserializing authentication failure events.
2249      */
2250     @Test
testMetricsAuthenticationFailureReason()2251     public void testMetricsAuthenticationFailureReason() throws Exception {
2252         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, null,
2253                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_NONE);
2254         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
2255                 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
2256                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
2257                 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD, 0);
2258 
2259         //Dump proto and deserialize
2260         //This should clear all the metrics in mWifiMetrics,
2261         dumpProtoAndDeserialize();
2262         //Check there is only 1 connection events
2263         assertEquals(1, mDecodedProto.connectionEvent.length);
2264         assertEquals(WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
2265                 mDecodedProto.connectionEvent[0].level2FailureCode);
2266         //Check the authentication failure reason
2267         assertEquals(WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD,
2268                 mDecodedProto.connectionEvent[0].level2FailureReason);
2269     }
2270 
2271     /**
2272      * Test the logging of BssidBlocklistStats.
2273      */
2274     @Test
testBssidBlocklistMetrics()2275     public void testBssidBlocklistMetrics() throws Exception {
2276         for (int i = 0; i < 3; i++) {
2277             mWifiMetrics.incrementNetworkSelectionFilteredBssidCount(i);
2278             mWifiMetrics.incrementBssidBlocklistCount(
2279                     WifiBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT);
2280             mWifiMetrics.incrementWificonfigurationBlocklistCount(
2281                     NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION);
2282         }
2283         mWifiMetrics.incrementNetworkSelectionFilteredBssidCount(2);
2284         mWifiMetrics.incrementBssidBlocklistCount(
2285                 WifiBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE);
2286         mWifiMetrics.incrementWificonfigurationBlocklistCount(
2287                 NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY);
2288         mResources.setBoolean(R.bool.config_wifiHighMovementNetworkSelectionOptimizationEnabled,
2289                 true);
2290         mWifiMetrics.incrementNumHighMovementConnectionStarted();
2291         mWifiMetrics.incrementNumHighMovementConnectionSkipped();
2292         mWifiMetrics.incrementNumHighMovementConnectionSkipped();
2293         dumpProtoAndDeserialize();
2294 
2295         Int32Count[] expectedFilteredBssidHistogram = {
2296                 buildInt32Count(0, 1),
2297                 buildInt32Count(1, 1),
2298                 buildInt32Count(2, 2),
2299         };
2300         Int32Count[] expectedBssidBlocklistPerReasonHistogram = {
2301                 buildInt32Count(WifiBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE, 1),
2302                 buildInt32Count(WifiBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT, 3),
2303         };
2304         Int32Count[] expectedWificonfigBlocklistPerReasonHistogram = {
2305                 buildInt32Count(NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION, 3),
2306                 buildInt32Count(NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY, 1),
2307         };
2308         assertKeyCountsEqual(expectedFilteredBssidHistogram,
2309                 mDecodedProto.bssidBlocklistStats.networkSelectionFilteredBssidCount);
2310         assertKeyCountsEqual(expectedBssidBlocklistPerReasonHistogram,
2311                 mDecodedProto.bssidBlocklistStats.bssidBlocklistPerReasonCount);
2312         assertKeyCountsEqual(expectedWificonfigBlocklistPerReasonHistogram,
2313                 mDecodedProto.bssidBlocklistStats.wifiConfigBlocklistPerReasonCount);
2314         assertEquals(true, mDecodedProto.bssidBlocklistStats
2315                 .highMovementMultipleScansFeatureEnabled);
2316         assertEquals(1, mDecodedProto.bssidBlocklistStats.numHighMovementConnectionStarted);
2317         assertEquals(2, mDecodedProto.bssidBlocklistStats.numHighMovementConnectionSkipped);
2318     }
2319 
2320     /**
2321      * Test that WifiMetrics is being cleared after dumping via proto
2322      */
2323     @Test
testMetricsClearedAfterProtoRequested()2324     public void testMetricsClearedAfterProtoRequested() throws Exception {
2325         // Create 3 ConnectionEvents
2326         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, null,
2327                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
2328         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
2329                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
2330                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
2331                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
2332         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, null,
2333                 "YELLOW", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
2334         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
2335                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
2336                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
2337                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
2338         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, null,
2339                 "GREEN", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
2340         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
2341                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
2342                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
2343                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
2344         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, null,
2345                 "ORANGE", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
2346         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
2347                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
2348                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
2349                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
2350 
2351         //Dump proto and deserialize
2352         //This should clear all the metrics in mWifiMetrics,
2353         dumpProtoAndDeserialize();
2354         //Check there are 4 connection events
2355         assertEquals(4, mDecodedProto.connectionEvent.length);
2356         assertEquals(0, mDecodedProto.rssiPollRssiCount.length);
2357         assertEquals(0, mDecodedProto.alertReasonCount.length);
2358 
2359         // Create 2 ConnectionEvents
2360         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, null,
2361                 "BLUE", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
2362         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
2363                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
2364                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
2365                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
2366         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, null,
2367                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
2368         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
2369                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
2370                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
2371                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
2372 
2373         //Dump proto and deserialize
2374         dumpProtoAndDeserialize();
2375         //Check there are only 2 connection events
2376         assertEquals(2, mDecodedProto.connectionEvent.length);
2377     }
2378 
2379     /**
2380      * Test logging to statsd when a connection event finishes.
2381      */
2382     @Test
testLogWifiConnectionResultStatsd()2383     public void testLogWifiConnectionResultStatsd() throws Exception {
2384         // Start and end Connection event
2385         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, createComplexWifiConfig(),
2386                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
2387         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
2388                 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
2389                 WifiMetricsProto.ConnectionEvent.HLF_DHCP,
2390                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, TEST_CANDIDATE_FREQ);
2391 
2392         ExtendedMockito.verify(() -> WifiStatsLog.write(
2393                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED, false,
2394                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_AUTHENTICATION_GENERAL,
2395                 -80, 0,
2396                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__BAND__BAND_2G,
2397                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__AUTH_TYPE__AUTH_TYPE_WPA2_PSK,
2398                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__TRIGGER__AUTOCONNECT_BOOT,
2399                 true,
2400                 0));
2401     }
2402 
2403     /**
2404      * Test that current ongoing ConnectionEvent is not cleared and logged
2405      * when proto is dumped
2406      */
2407     @Test
testCurrentConnectionEventNotClearedAfterProtoRequested()2408     public void testCurrentConnectionEventNotClearedAfterProtoRequested() throws Exception {
2409         // Create 2 complete ConnectionEvents and 1 ongoing un-ended ConnectionEvent
2410         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, null,
2411                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
2412         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
2413                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
2414                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
2415                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
2416         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, null,
2417                 "YELLOW", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
2418         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
2419                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
2420                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
2421                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
2422         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, null,
2423                 "GREEN", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
2424 
2425         // Dump proto and deserialize
2426         // This should clear the metrics in mWifiMetrics,
2427         dumpProtoAndDeserialize();
2428         assertEquals(2, mDecodedProto.connectionEvent.length);
2429 
2430         // End the ongoing ConnectionEvent
2431         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
2432                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
2433                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
2434                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
2435 
2436         dumpProtoAndDeserialize();
2437         assertEquals(1, mDecodedProto.connectionEvent.length);
2438     }
2439 
2440     /**
2441      * Tests that after setting metrics values they can be serialized and deserialized with the
2442      *   $ adb shell dumpsys wifi wifiMetricsProto clean
2443      */
2444     @Test
testClearMetricsDump()2445     public void testClearMetricsDump() throws Exception {
2446         setAndIncrementMetrics();
2447         startAndEndConnectionEventSucceeds();
2448         cleanDumpProtoAndDeserialize();
2449         assertDeserializedMetricsCorrect();
2450         assertEquals("mDecodedProto.connectionEvent.length",
2451                 2, mDecodedProto.connectionEvent.length);
2452     }
2453 
2454     private static final int NUM_REPEATED_DELTAS = 7;
2455     private static final int REPEATED_DELTA = 0;
2456     private static final int SINGLE_GOOD_DELTA = 1;
2457     private static final int SINGLE_TIMEOUT_DELTA = 2;
2458     private static final int NUM_REPEATED_BOUND_DELTAS = 2;
2459     private static final int MAX_DELTA_LEVEL = 127;
2460     private static final int MIN_DELTA_LEVEL = -127;
2461     private static final int ARBITRARY_DELTA_LEVEL = 20;
2462 
2463     /**
2464      * Sunny day RSSI delta logging scenario.
2465      * Logs one rssi delta value multiple times
2466      * Logs a different delta value a single time
2467      */
2468     @Test
testRssiDeltasSuccessfulLogging()2469     public void testRssiDeltasSuccessfulLogging() throws Exception {
2470         // Generate some repeated deltas
2471         for (int i = 0; i < NUM_REPEATED_DELTAS; i++) {
2472             generateRssiDelta(MIN_RSSI_LEVEL, REPEATED_DELTA,
2473                     WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
2474         }
2475         // Generate a single delta
2476         generateRssiDelta(MIN_RSSI_LEVEL, SINGLE_GOOD_DELTA,
2477                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
2478         dumpProtoAndDeserialize();
2479         assertEquals(2, mDecodedProto.rssiPollDeltaCount.length);
2480         // Check the repeated deltas
2481         assertEquals(NUM_REPEATED_DELTAS, mDecodedProto.rssiPollDeltaCount[0].count);
2482         assertEquals(REPEATED_DELTA, mDecodedProto.rssiPollDeltaCount[0].rssi);
2483         // Check the single delta
2484         assertEquals(1, mDecodedProto.rssiPollDeltaCount[1].count);
2485         assertEquals(SINGLE_GOOD_DELTA, mDecodedProto.rssiPollDeltaCount[1].rssi);
2486     }
2487 
2488     /**
2489      * Tests that Rssi Delta events whose scanResult and Rssi Poll come too far apart, timeout,
2490      * and are not logged.
2491      */
2492     @Test
testRssiDeltasTimeout()2493     public void testRssiDeltasTimeout() throws Exception {
2494         // Create timed out rssi deltas
2495         generateRssiDelta(MIN_RSSI_LEVEL, REPEATED_DELTA,
2496                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS + 1);
2497         generateRssiDelta(MIN_RSSI_LEVEL, SINGLE_TIMEOUT_DELTA,
2498                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS + 1);
2499         dumpProtoAndDeserialize();
2500         assertEquals(0, mDecodedProto.rssiPollDeltaCount.length);
2501     }
2502 
2503     /**
2504      * Tests the exact inclusive boundaries of RSSI delta logging.
2505      */
2506     @Test
testRssiDeltaSuccessfulLoggingExactBounds()2507     public void testRssiDeltaSuccessfulLoggingExactBounds() throws Exception {
2508         generateRssiDelta(MIN_RSSI_LEVEL, MAX_DELTA_LEVEL,
2509                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
2510         generateRssiDelta(MAX_RSSI_LEVEL, MIN_DELTA_LEVEL,
2511                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
2512         dumpProtoAndDeserialize();
2513         assertEquals(2, mDecodedProto.rssiPollDeltaCount.length);
2514         assertEquals(MIN_DELTA_LEVEL, mDecodedProto.rssiPollDeltaCount[0].rssi);
2515         assertEquals(1, mDecodedProto.rssiPollDeltaCount[0].count);
2516         assertEquals(MAX_DELTA_LEVEL, mDecodedProto.rssiPollDeltaCount[1].rssi);
2517         assertEquals(1, mDecodedProto.rssiPollDeltaCount[1].count);
2518     }
2519 
2520     /**
2521      * Tests the exact exclusive boundaries of RSSI delta logging.
2522      * This test ensures that too much data is not generated.
2523      */
2524     @Test
testRssiDeltaOutOfBounds()2525     public void testRssiDeltaOutOfBounds() throws Exception {
2526         generateRssiDelta(MIN_RSSI_LEVEL, MAX_DELTA_LEVEL + 1,
2527                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
2528         generateRssiDelta(MAX_RSSI_LEVEL, MIN_DELTA_LEVEL - 1,
2529                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
2530         dumpProtoAndDeserialize();
2531         assertEquals(0, mDecodedProto.rssiPollDeltaCount.length);
2532     }
2533 
2534     /**
2535      * This test ensures no rssi Delta is logged after an unsuccessful ConnectionEvent
2536      */
2537     @Test
testUnsuccesfulConnectionEventRssiDeltaIsNotLogged()2538     public void testUnsuccesfulConnectionEventRssiDeltaIsNotLogged() throws Exception {
2539         generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL,
2540                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS,
2541                 false, // successfulConnectionEvent
2542                 true, // completeConnectionEvent
2543                 true, // useValidScanResult
2544                 true // dontDeserializeBeforePoll
2545         );
2546 
2547         dumpProtoAndDeserialize();
2548         assertEquals(0, mDecodedProto.rssiPollDeltaCount.length);
2549     }
2550 
2551     /**
2552      * This test ensures rssi Deltas can be logged during a ConnectionEvent
2553      */
2554     @Test
testIncompleteConnectionEventRssiDeltaIsLogged()2555     public void testIncompleteConnectionEventRssiDeltaIsLogged() throws Exception {
2556         generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL,
2557                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS,
2558                 true, // successfulConnectionEvent
2559                 false, // completeConnectionEvent
2560                 true, // useValidScanResult
2561                 true // dontDeserializeBeforePoll
2562         );
2563         dumpProtoAndDeserialize();
2564         assertEquals(1, mDecodedProto.rssiPollDeltaCount.length);
2565         assertEquals(ARBITRARY_DELTA_LEVEL, mDecodedProto.rssiPollDeltaCount[0].rssi);
2566         assertEquals(1, mDecodedProto.rssiPollDeltaCount[0].count);
2567     }
2568 
2569     /**
2570      * This test ensures that no delta is logged for a null ScanResult Candidate
2571      */
2572     @Test
testRssiDeltaNotLoggedForNullCandidateScanResult()2573     public void testRssiDeltaNotLoggedForNullCandidateScanResult() throws Exception {
2574         generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL,
2575                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS,
2576                 true, // successfulConnectionEvent
2577                 true, // completeConnectionEvent
2578                 false, // useValidScanResult
2579                 true // dontDeserializeBeforePoll
2580         );
2581         dumpProtoAndDeserialize();
2582         assertEquals(0, mDecodedProto.rssiPollDeltaCount.length);
2583     }
2584 
2585     /**
2586      * This test ensures that Rssi Deltas are not logged over a 'clear()' call (Metrics Serialized)
2587      */
2588     @Test
testMetricsSerializedDuringRssiDeltaEventLogsNothing()2589     public void testMetricsSerializedDuringRssiDeltaEventLogsNothing() throws Exception {
2590         generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL,
2591                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS,
2592                 true, // successfulConnectionEvent
2593                 true, // completeConnectionEvent
2594                 true, // useValidScanResult
2595                 false // dontDeserializeBeforePoll
2596         );
2597         dumpProtoAndDeserialize();
2598         assertEquals(0, mDecodedProto.rssiPollDeltaCount.length);
2599     }
2600 
2601     private static final int DEAUTH_REASON = 7;
2602     private static final int ASSOC_STATUS = 11;
2603     private static final boolean ASSOC_TIMEOUT = true;
2604     private static final boolean LOCAL_GEN = true;
2605     private static final int AUTH_FAILURE_REASON = WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD;
2606     private static final int NUM_TEST_STA_EVENTS = 19;
2607     private static final String   sSSID = "\"SomeTestSsid\"";
2608     private static final WifiSsid sWifiSsid = WifiSsid.fromUtf8Text(sSSID);
2609     private static final String   sBSSID = "01:02:03:04:05:06";
2610 
2611     private final StateChangeResult mStateDisconnected =
2612             new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED);
2613     private final StateChangeResult mStateCompleted =
2614             new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED);
2615     // Test bitmasks of supplicant state changes
2616     private final int mSupBm1 = WifiMetrics.supplicantStateToBit(mStateDisconnected.state);
2617     private final int mSupBm2 = WifiMetrics.supplicantStateToBit(mStateDisconnected.state)
2618             | WifiMetrics.supplicantStateToBit(mStateCompleted.state);
2619     // An invalid but interesting wifiConfiguration that exercises the StaEvent.ConfigInfo encoding
2620     private final WifiConfiguration mTestWifiConfig = createComplexWifiConfig();
2621     // <msg.what> <msg.arg1> <msg.arg2>
2622     private int[][] mTestStaMessageInts = {
2623         {WifiMonitor.ASSOCIATION_REJECTION_EVENT,   0, 0},
2624         {WifiMonitor.AUTHENTICATION_FAILURE_EVENT,  0, 0},
2625         {WifiMonitor.NETWORK_CONNECTION_EVENT,      0, 0},
2626         {WifiMonitor.NETWORK_DISCONNECTION_EVENT,   0, 0},
2627         {WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0},
2628         {WifiMonitor.ASSOCIATED_BSSID_EVENT,        0, 0},
2629         {WifiMonitor.TARGET_BSSID_EVENT,            0, 0},
2630         {WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0},
2631         {WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0}
2632     };
2633     private Object[] mTestStaMessageObjs = {
2634         new AssocRejectEventInfo(sSSID, sBSSID, ASSOC_STATUS, ASSOC_TIMEOUT),
2635         new AuthenticationFailureEventInfo(sSSID, MacAddress.fromString(sBSSID),
2636                 AUTH_FAILURE_REASON, -1),
2637         null,
2638         new DisconnectEventInfo(sSSID, sBSSID, DEAUTH_REASON, LOCAL_GEN),
2639         mStateDisconnected,
2640         null,
2641         null,
2642         mStateDisconnected,
2643         mStateCompleted
2644     };
2645     // Values used to generate the StaEvent log calls from ClientModeImpl
2646     // <StaEvent.Type>, <StaEvent.FrameworkDisconnectReason>, <1|0>(testWifiConfiguration, null)
2647     private int[][] mTestStaLogInts = {
2648         {StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL, 0,                          0},
2649         {StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST,       0,                          0},
2650         {StaEvent.TYPE_CMD_IP_REACHABILITY_LOST,        0,                          0},
2651         {StaEvent.TYPE_CMD_START_CONNECT,               0,                          1},
2652         {StaEvent.TYPE_CMD_START_ROAM,                  0,                          1},
2653         {StaEvent.TYPE_CONNECT_NETWORK,                 0,                          1},
2654         {StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK,     0,                          0},
2655         {StaEvent.TYPE_FRAMEWORK_DISCONNECT,            StaEvent.DISCONNECT_API,    0},
2656         {StaEvent.TYPE_SCORE_BREACH,                    0,                          0},
2657         {StaEvent.TYPE_MAC_CHANGE,                      0,                          1},
2658         {StaEvent.TYPE_WIFI_ENABLED,                    0,                          0},
2659         {StaEvent.TYPE_WIFI_DISABLED,                   0,                          0},
2660         {StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH,     0,                          0}
2661     };
2662     // Values used to generate the StaEvent log calls from WifiMonitor
2663     // <type>, <reason>, <status>, <local_gen>,
2664     // <auth_fail_reason>, <assoc_timed_out> <supplicantStateChangeBitmask> <1|0>(has ConfigInfo)
2665     private int[][] mExpectedValues = {
2666         {StaEvent.TYPE_ASSOCIATION_REJECTION_EVENT,     -1,  ASSOC_STATUS,         0,
2667             /**/                               0, ASSOC_TIMEOUT ? 1 : 0,        0, 0},    /**/
2668         {StaEvent.TYPE_AUTHENTICATION_FAILURE_EVENT,    -1,            -1,         0,
2669             /**/StaEvent.AUTH_FAILURE_WRONG_PSWD,             0,        0, 0},    /**/
2670         {StaEvent.TYPE_NETWORK_CONNECTION_EVENT,        -1,            -1,         0,
2671             /**/                               0,             0,        0, 0},    /**/
2672         {StaEvent.TYPE_NETWORK_DISCONNECTION_EVENT, DEAUTH_REASON,     -1, LOCAL_GEN ? 1 : 0,
2673             /**/                               0,             0,        0, 0},    /**/
2674         {StaEvent.TYPE_CMD_ASSOCIATED_BSSID,            -1,            -1,         0,
2675             /**/                               0,             0,  mSupBm1, 0},    /**/
2676         {StaEvent.TYPE_CMD_TARGET_BSSID,                -1,            -1,         0,
2677             /**/                               0,             0,        0, 0},    /**/
2678         {StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL, -1,            -1,         0,
2679             /**/                               0,             0,  mSupBm2, 0},    /**/
2680         {StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST,       -1,            -1,         0,
2681             /**/                               0,             0,        0, 0},    /**/
2682         {StaEvent.TYPE_CMD_IP_REACHABILITY_LOST,        -1,            -1,         0,
2683             /**/                               0,             0,        0, 0},    /**/
2684         {StaEvent.TYPE_CMD_START_CONNECT,               -1,            -1,         0,
2685             /**/                               0,             0,        0, 1},    /**/
2686         {StaEvent.TYPE_CMD_START_ROAM,                  -1,            -1,         0,
2687             /**/                               0,             0,        0, 1},    /**/
2688         {StaEvent.TYPE_CONNECT_NETWORK,                 -1,            -1,         0,
2689             /**/                               0,             0,        0, 1},    /**/
2690         {StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK,     -1,            -1,         0,
2691             /**/                               0,             0,        0, 0},    /**/
2692         {StaEvent.TYPE_FRAMEWORK_DISCONNECT,            -1,            -1,         0,
2693             /**/                               0,             0,        0, 0},    /**/
2694         {StaEvent.TYPE_SCORE_BREACH,                    -1,            -1,         0,
2695             /**/                               0,             0,        0, 0},    /**/
2696         {StaEvent.TYPE_MAC_CHANGE,                      -1,            -1,         0,
2697             /**/                               0,             0,        0, 1},    /**/
2698         {StaEvent.TYPE_WIFI_ENABLED,                    -1,            -1,         0,
2699             /**/                               0,             0,        0, 0},    /**/
2700         {StaEvent.TYPE_WIFI_DISABLED,                   -1,            -1,         0,
2701             /**/                               0,             0,        0, 0},     /**/
2702         {StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH,     -1,            -1,         0,
2703             /**/                               0,             0,        0, 0}    /**/
2704     };
2705 
2706     /**
2707      * Generates events from all the rows in mTestStaMessageInts, and then mTestStaLogInts
2708      */
generateStaEvents(WifiMetrics wifiMetrics)2709     private void generateStaEvents(WifiMetrics wifiMetrics) {
2710         Handler handler = mHandlerCaptor.getValue();
2711         for (int i = 0; i < mTestStaMessageInts.length; i++) {
2712             int[] mia = mTestStaMessageInts[i];
2713             Message message = handler.obtainMessage(mia[0], mia[1], mia[2], mTestStaMessageObjs[i]);
2714             message.getData().putString(WifiMonitor.KEY_IFACE, TEST_IFACE_NAME);
2715             handler.sendMessage(message);
2716         }
2717         mTestLooper.dispatchAll();
2718         setScreenState(true);
2719         when(mWifiDataStall.isCellularDataAvailable()).thenReturn(true);
2720         wifiMetrics.setAdaptiveConnectivityState(true);
2721         for (int i = 0; i < mTestStaLogInts.length; i++) {
2722             int[] lia = mTestStaLogInts[i];
2723             wifiMetrics.logStaEvent(
2724                     TEST_IFACE_NAME, lia[0], lia[1], lia[2] == 1 ? mTestWifiConfig : null);
2725         }
2726     }
verifyDeserializedStaEvents(WifiMetricsProto.WifiLog wifiLog)2727     private void verifyDeserializedStaEvents(WifiMetricsProto.WifiLog wifiLog) {
2728         assertNotNull(mTestWifiConfig);
2729         assertEquals(NUM_TEST_STA_EVENTS, wifiLog.staEventList.length);
2730         int j = 0; // De-serialized event index
2731         for (int i = 0; i < mTestStaMessageInts.length; i++) {
2732             StaEvent event = wifiLog.staEventList[j];
2733             int[] mia = mTestStaMessageInts[i];
2734             int[] evs = mExpectedValues[j];
2735             if (mia[0] != WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT) {
2736                 assertEquals(evs[0], event.type);
2737                 assertEquals(evs[1], event.reason);
2738                 assertEquals(evs[2], event.status);
2739                 assertEquals(evs[3] == 1 ? true : false, event.localGen);
2740                 assertEquals(evs[4], event.authFailureReason);
2741                 assertEquals(evs[5] == 1 ? true : false, event.associationTimedOut);
2742                 assertEquals(evs[6], event.supplicantStateChangesBitmask);
2743                 assertConfigInfoEqualsWifiConfig(
2744                         evs[7] == 1 ? mTestWifiConfig : null, event.configInfo);
2745                 j++;
2746             }
2747         }
2748         for (int i = 0; i < mTestStaLogInts.length; i++) {
2749             StaEvent event = wifiLog.staEventList[j];
2750             int[] evs = mExpectedValues[j];
2751             assertEquals(evs[0], event.type);
2752             assertEquals(evs[1], event.reason);
2753             assertEquals(evs[2], event.status);
2754             assertEquals(evs[3] == 1 ? true : false, event.localGen);
2755             assertEquals(evs[4], event.authFailureReason);
2756             assertEquals(evs[5] == 1 ? true : false, event.associationTimedOut);
2757             assertEquals(evs[6], event.supplicantStateChangesBitmask);
2758             assertConfigInfoEqualsWifiConfig(
2759                     evs[7] == 1 ? mTestWifiConfig : null, event.configInfo);
2760             assertEquals(true, event.screenOn);
2761             assertEquals(true, event.isCellularDataAvailable);
2762             assertEquals(true, event.isAdaptiveConnectivityEnabled);
2763             j++;
2764         }
2765         assertEquals(mExpectedValues.length, j);
2766     }
2767 
2768     /**
2769      * Generate StaEvents of each type, ensure all the different values are logged correctly,
2770      * and that they survive serialization & de-serialization
2771      */
2772     @Test
testStaEventsLogSerializeDeserialize()2773     public void testStaEventsLogSerializeDeserialize() throws Exception {
2774         generateStaEvents(mWifiMetrics);
2775         dumpProtoAndDeserialize();
2776         verifyDeserializedStaEvents(mDecodedProto);
2777     }
2778 
2779     /**
2780      * Ensure the number of StaEvents does not exceed MAX_STA_EVENTS by generating lots of events
2781      * and checking how many are deserialized
2782      */
2783     @Test
testStaEventBounding()2784     public void testStaEventBounding() throws Exception {
2785         for (int i = 0; i < (WifiMetrics.MAX_STA_EVENTS + 10); i++) {
2786             mWifiMetrics.logStaEvent(TEST_IFACE_NAME, StaEvent.TYPE_CMD_START_CONNECT);
2787         }
2788         dumpProtoAndDeserialize();
2789         assertEquals(WifiMetrics.MAX_STA_EVENTS, mDecodedProto.staEventList.length);
2790     }
2791 
2792     /**
2793      * Tests that link probe StaEvents do not exceed
2794      * {@link WifiMetrics#MAX_LINK_PROBE_STA_EVENTS}.
2795      */
2796     @Test
testLinkProbeStaEventBounding()2797     public void testLinkProbeStaEventBounding() throws Exception {
2798         for (int i = 0; i < WifiMetrics.MAX_LINK_PROBE_STA_EVENTS; i++) {
2799             mWifiMetrics.logLinkProbeSuccess(TEST_IFACE_NAME, 0, 0, 0, 0);
2800             mWifiMetrics.logLinkProbeFailure(TEST_IFACE_NAME, 0, 0, 0, 0);
2801         }
2802         for (int i = 0; i < 10; i++) {
2803             mWifiMetrics.logStaEvent(TEST_IFACE_NAME, StaEvent.TYPE_CMD_START_CONNECT);
2804         }
2805 
2806         dumpProtoAndDeserialize();
2807 
2808         long numLinkProbeStaEvents = Arrays.stream(mDecodedProto.staEventList)
2809                 .filter(event -> event.type == TYPE_LINK_PROBE)
2810                 .count();
2811         assertEquals(WifiMetrics.MAX_LINK_PROBE_STA_EVENTS, numLinkProbeStaEvents);
2812         assertEquals(WifiMetrics.MAX_LINK_PROBE_STA_EVENTS + 10, mDecodedProto.staEventList.length);
2813     }
2814 
2815     /**
2816      * Test the logging of UserActionEvent with a valid network ID
2817      */
2818     @Test
testLogUserActionEventValidNetworkId()2819     public void testLogUserActionEventValidNetworkId() throws Exception {
2820         int testEventType = WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI;
2821         int testNetworkId = 0;
2822         long testStartTimeMillis = 123123L;
2823         when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartTimeMillis);
2824         WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork();
2825         config.ephemeral = true;
2826         when(mWcm.getConfiguredNetwork(testNetworkId)).thenReturn(config);
2827 
2828         mWifiMetrics.logUserActionEvent(testEventType, testNetworkId);
2829         dumpProtoAndDeserialize();
2830 
2831         WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents;
2832         assertEquals(1, userActionEvents.length);
2833         assertEquals(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
2834                 userActionEvents[0].eventType);
2835         assertEquals(testStartTimeMillis, userActionEvents[0].startTimeMillis);
2836         assertEquals(true, userActionEvents[0].targetNetworkInfo.isEphemeral);
2837         assertEquals(true, userActionEvents[0].targetNetworkInfo.isPasspoint);
2838 
2839         // Verify that there are no disabled WifiConfiguration and BSSIDs
2840         NetworkDisableReason networkDisableReason = userActionEvents[0].networkDisableReason;
2841         assertEquals(NetworkDisableReason.REASON_UNKNOWN, networkDisableReason.disableReason);
2842         assertEquals(false, networkDisableReason.configTemporarilyDisabled);
2843         assertEquals(false, networkDisableReason.configPermanentlyDisabled);
2844         assertEquals(0, networkDisableReason.bssidDisableReasons.length);
2845     }
2846 
2847     /**
2848      * Verify the WifiStatus field in a UserActionEvent is populated correctly.
2849      * @throws Exception
2850      */
2851     @Test
testLogWifiStatusInUserActionEvent()2852     public void testLogWifiStatusInUserActionEvent() throws Exception {
2853         // setups WifiStatus for information
2854         int expectedRssi = -55;
2855         int testNetworkId = 1;
2856         int expectedTx = 1234;
2857         int expectedRx = 2345;
2858 
2859         WifiInfo wifiInfo = mock(WifiInfo.class);
2860         when(wifiInfo.getRssi()).thenReturn(expectedRssi);
2861         when(wifiInfo.getNetworkId()).thenReturn(testNetworkId);
2862         mWifiMetrics.handlePollResult(TEST_IFACE_NAME, wifiInfo);
2863         mWifiMetrics.incrementThroughputKbpsCount(expectedTx, expectedRx, RSSI_POLL_FREQUENCY);
2864         mWifiMetrics.setNominatorForNetwork(testNetworkId,
2865                 WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED_USER_CONNECT_CHOICE);
2866 
2867         // generate a user action event and then verify fields
2868         int testEventType = WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI;
2869         mWifiMetrics.logUserActionEvent(testEventType, testNetworkId);
2870         dumpProtoAndDeserialize();
2871 
2872         WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents;
2873         assertEquals(1, userActionEvents.length);
2874         assertEquals(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
2875                 userActionEvents[0].eventType);
2876         assertEquals(expectedRssi, userActionEvents[0].wifiStatus.lastRssi);
2877         assertEquals(expectedTx, userActionEvents[0].wifiStatus.estimatedTxKbps);
2878         assertEquals(expectedRx, userActionEvents[0].wifiStatus.estimatedRxKbps);
2879         assertTrue(userActionEvents[0].wifiStatus.isStuckDueToUserConnectChoice);
2880     }
2881 
2882     /**
2883      * verify NetworkDisableReason is populated properly when there exists a disabled
2884      * WifiConfiguration and BSSID.
2885      */
2886     @Test
testNetworkDisableReasonInUserActionEvent()2887     public void testNetworkDisableReasonInUserActionEvent() throws Exception {
2888         // Setup a temporarily blocked config due to DISABLED_ASSOCIATION_REJECTION
2889         WifiConfiguration testConfig = WifiConfigurationTestUtil.createOpenNetwork();
2890         NetworkSelectionStatus status = testConfig.getNetworkSelectionStatus();
2891         status.setNetworkSelectionStatus(
2892                 NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED);
2893         status.setNetworkSelectionDisableReason(
2894                 NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION);
2895         when(mWcm.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(testConfig);
2896 
2897         // Also setup the same BSSID level failure
2898         Set<Integer> testBssidBlocklistReasons = new HashSet<>();
2899         testBssidBlocklistReasons.add(WifiBlocklistMonitor.REASON_ASSOCIATION_REJECTION);
2900         when(mWifiBlocklistMonitor.getFailureReasonsForSsid(anyString()))
2901                 .thenReturn(testBssidBlocklistReasons);
2902 
2903         // Logging the user action event
2904         mWifiMetrics.logUserActionEvent(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
2905                 TEST_NETWORK_ID);
2906         dumpProtoAndDeserialize();
2907 
2908         WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents;
2909         assertEquals(1, userActionEvents.length);
2910         assertEquals(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
2911                 userActionEvents[0].eventType);
2912         NetworkDisableReason networkDisableReason = userActionEvents[0].networkDisableReason;
2913         assertEquals(NetworkDisableReason.REASON_ASSOCIATION_REJECTION,
2914                 networkDisableReason.disableReason);
2915         assertEquals(true, networkDisableReason.configTemporarilyDisabled);
2916         assertEquals(false, networkDisableReason.configPermanentlyDisabled);
2917         assertEquals(1, networkDisableReason.bssidDisableReasons.length);
2918         assertEquals(NetworkDisableReason.REASON_ASSOCIATION_REJECTION,
2919                 networkDisableReason.bssidDisableReasons[0]);
2920     }
2921 
2922     /**
2923      * verify that auto-join disable overrides any other disable reasons in NetworkDisableReason.
2924      */
2925     @Test
testNetworkDisableReasonDisableAutojoinInUserActionEvent()2926     public void testNetworkDisableReasonDisableAutojoinInUserActionEvent() throws Exception {
2927         // Setup a temporarily blocked config due to DISABLED_ASSOCIATION_REJECTION
2928         WifiConfiguration testConfig = WifiConfigurationTestUtil.createOpenNetwork();
2929         NetworkSelectionStatus status = testConfig.getNetworkSelectionStatus();
2930         status.setNetworkSelectionStatus(
2931                 NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED);
2932         status.setNetworkSelectionDisableReason(
2933                 NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION);
2934         when(mWcm.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(testConfig);
2935 
2936         // Disable autojoin
2937         testConfig.allowAutojoin = false;
2938 
2939         // Logging the user action event
2940         mWifiMetrics.logUserActionEvent(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
2941                 TEST_NETWORK_ID);
2942         dumpProtoAndDeserialize();
2943 
2944         WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents;
2945         NetworkDisableReason networkDisableReason = userActionEvents[0].networkDisableReason;
2946         assertEquals(NetworkDisableReason.REASON_AUTO_JOIN_DISABLED,
2947                 networkDisableReason.disableReason);
2948         assertEquals(false, networkDisableReason.configTemporarilyDisabled);
2949         assertEquals(true, networkDisableReason.configPermanentlyDisabled);
2950     }
2951 
2952     /**
2953      * Test the logging of UserActionEvent with invalid network ID
2954      */
2955     @Test
testLogUserActionEventInvalidNetworkId()2956     public void testLogUserActionEventInvalidNetworkId() throws Exception {
2957         int testEventType = WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI;
2958         int testNetworkId = 0;
2959         long testStartTimeMillis = 123123L;
2960         when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartTimeMillis);
2961         when(mWcm.getConfiguredNetwork(testNetworkId)).thenReturn(null);
2962 
2963         mWifiMetrics.logUserActionEvent(testEventType, testNetworkId);
2964         dumpProtoAndDeserialize();
2965 
2966         WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents;
2967         assertEquals(1, userActionEvents.length);
2968         assertEquals(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
2969                 userActionEvents[0].eventType);
2970         assertEquals(testStartTimeMillis, userActionEvents[0].startTimeMillis);
2971         assertNull(userActionEvents[0].targetNetworkInfo);
2972     }
2973 
2974     /**
2975      * Test the logging of UserActionEvent for Adaptive Connectivity toggle
2976      */
2977     @Test
testLogUserActionEventForAdaptiveConnectivity()2978     public void testLogUserActionEventForAdaptiveConnectivity() throws Exception {
2979         long testStartTimeMillis = 123123L;
2980         boolean adaptiveConnectivityEnabled = true;
2981         when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartTimeMillis);
2982         mWifiMetrics.logUserActionEvent(
2983                 mWifiMetrics.convertAdaptiveConnectivityStateToUserActionEventType(
2984                         adaptiveConnectivityEnabled));
2985         long testStartTimeMillis2 = 200000L;
2986         boolean adaptiveConnectivityEnabled2 = false;
2987         when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartTimeMillis2);
2988         mWifiMetrics.logUserActionEvent(
2989                 mWifiMetrics.convertAdaptiveConnectivityStateToUserActionEventType(
2990                         adaptiveConnectivityEnabled2));
2991         dumpProtoAndDeserialize();
2992 
2993         WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents;
2994         assertEquals(2, userActionEvents.length);
2995         assertEquals(WifiMetricsProto.UserActionEvent.EVENT_CONFIGURE_ADAPTIVE_CONNECTIVITY_ON,
2996                 userActionEvents[0].eventType);
2997         assertEquals(testStartTimeMillis, userActionEvents[0].startTimeMillis);
2998         assertEquals(WifiMetricsProto.UserActionEvent.EVENT_CONFIGURE_ADAPTIVE_CONNECTIVITY_OFF,
2999                 userActionEvents[1].eventType);
3000         assertEquals(testStartTimeMillis2, userActionEvents[1].startTimeMillis);
3001     }
3002 
3003     /**
3004      * Verify that the max length of the UserActionEvent list is limited to MAX_USER_ACTION_EVENTS.
3005      */
3006     @Test
testLogUserActionEventCapped()3007     public void testLogUserActionEventCapped() throws Exception {
3008         for (int i = 0; i < WifiMetrics.MAX_USER_ACTION_EVENTS + 1; i++) {
3009             mWifiMetrics.logUserActionEvent(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI, 0);
3010         }
3011         dumpProtoAndDeserialize();
3012         assertEquals(WifiMetrics.MAX_USER_ACTION_EVENTS, mDecodedProto.userActionEvents.length);
3013     }
3014 
3015     /**
3016      * Ensure WifiMetrics doesn't cause a null pointer exception when called with null args
3017      */
3018     @Test
testDumpNullArg()3019     public void testDumpNullArg() {
3020         mWifiMetrics.dump(new FileDescriptor(), new PrintWriter(new StringWriter()), null);
3021     }
3022 
3023     /**
3024      * Test the generation of 'NumConnectableNetwork' histograms from two scans of different
3025      * ScanDetails produces the correct histogram values, and relevant bounds are observed
3026      */
3027     @MediumTest
3028     @Test
testNumConnectableNetworksGeneration()3029     public void testNumConnectableNetworksGeneration() throws Exception {
3030         List<ScanDetail> scan = new ArrayList<ScanDetail>();
3031         //                                ssid, bssid, isOpen, isSaved, isProvider, isWeakRssi)
3032         scan.add(buildMockScanDetail("PASSPOINT_1", "bssid0", false, false, true, false));
3033         scan.add(buildMockScanDetail("PASSPOINT_2", "bssid1", false, false, true, false));
3034         scan.add(buildMockScanDetail("SSID_B", "bssid2", true, true, false, false));
3035         scan.add(buildMockScanDetail("SSID_B", "bssid3", true, true, false, false));
3036         scan.add(buildMockScanDetail("SSID_C", "bssid4", true, false, false, false));
3037         scan.add(buildMockScanDetail("SSID_D", "bssid5", false, true, false, false));
3038         scan.add(buildMockScanDetail("SSID_E", "bssid6", false, true, false, false));
3039         scan.add(buildMockScanDetail("SSID_F", "bssid7", false, false, false, false));
3040         scan.add(buildMockScanDetail("SSID_G_WEAK", "bssid9", false, false, false, true));
3041         scan.add(buildMockScanDetail("SSID_H_WEAK", "bssid10", false, false, false, true));
3042         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
3043         scan.add(buildMockScanDetail("SSID_B", "bssid8", true, true, false, false));
3044         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
3045         for (int i = 0; i < NUM_PARTIAL_SCAN_RESULTS; i++) {
3046             mWifiMetrics.incrementAvailableNetworksHistograms(scan, false);
3047         }
3048         dumpProtoAndDeserialize();
3049         verifyHist(mDecodedProto.totalSsidsInScanHistogram, 1,                    a(7),    a(2));
3050         verifyHist(mDecodedProto.totalBssidsInScanHistogram, 2,                   a(8, 9), a(1, 1));
3051         verifyHist(mDecodedProto.availableOpenSsidsInScanHistogram, 1,            a(2),    a(2));
3052         verifyHist(mDecodedProto.availableOpenBssidsInScanHistogram, 2,           a(3, 4), a(1, 1));
3053         verifyHist(mDecodedProto.availableSavedSsidsInScanHistogram, 1,           a(3),    a(2));
3054         verifyHist(mDecodedProto.availableSavedBssidsInScanHistogram, 2,          a(4, 5), a(1, 1));
3055         verifyHist(mDecodedProto.availableOpenOrSavedSsidsInScanHistogram, 1,     a(4),    a(2));
3056         verifyHist(mDecodedProto.availableOpenOrSavedBssidsInScanHistogram, 2,    a(5, 6), a(1, 1));
3057         verifyHist(mDecodedProto.availableSavedPasspointProviderProfilesInScanHistogram, 1,
3058                                                                                   a(2),    a(2));
3059         verifyHist(mDecodedProto.availableSavedPasspointProviderBssidsInScanHistogram, 1,
3060                                                                                   a(2),    a(2));
3061         assertEquals(2, mDecodedProto.fullBandAllSingleScanListenerResults);
3062         assertEquals(NUM_PARTIAL_SCAN_RESULTS, mDecodedProto.partialAllSingleScanListenerResults);
3063 
3064         // Check Bounds
3065         scan.clear();
3066         int lotsOfSSids = Math.max(WifiMetrics.MAX_TOTAL_SCAN_RESULT_SSIDS_BUCKET,
3067                 WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET) + 5;
3068         for (int i = 0; i < lotsOfSSids; i++) {
3069             scan.add(buildMockScanDetail("SSID_" + i, "bssid_" + i, true, true, false, false));
3070         }
3071         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
3072         dumpProtoAndDeserialize();
3073         verifyHist(mDecodedProto.totalSsidsInScanHistogram, 1,
3074                 a(WifiMetrics.MAX_TOTAL_SCAN_RESULT_SSIDS_BUCKET), a(1));
3075         verifyHist(mDecodedProto.availableOpenSsidsInScanHistogram, 1,
3076                 a(WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET), a(1));
3077         verifyHist(mDecodedProto.availableSavedSsidsInScanHistogram, 1,
3078                 a(WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET), a(1));
3079         verifyHist(mDecodedProto.availableOpenOrSavedSsidsInScanHistogram, 1,
3080                 a(WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET), a(1));
3081         scan.clear();
3082         int lotsOfBssids = Math.max(WifiMetrics.MAX_TOTAL_SCAN_RESULTS_BUCKET,
3083                 WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET) + 5;
3084         for (int i = 0; i < lotsOfBssids; i++) {
3085             scan.add(buildMockScanDetail("SSID", "bssid_" + i, true, true, false, false));
3086         }
3087         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
3088         dumpProtoAndDeserialize();
3089         verifyHist(mDecodedProto.totalBssidsInScanHistogram, 1,
3090                 a(WifiMetrics.MAX_TOTAL_SCAN_RESULTS_BUCKET), a(1));
3091         verifyHist(mDecodedProto.availableOpenBssidsInScanHistogram, 1,
3092                 a(WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET), a(1));
3093         verifyHist(mDecodedProto.availableSavedBssidsInScanHistogram, 1,
3094                 a(WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET), a(1));
3095         verifyHist(mDecodedProto.availableOpenOrSavedBssidsInScanHistogram, 1,
3096                 a(WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET), a(1));
3097     }
3098 
3099     /**
3100      * Test that Hotspot 2.0 (Passpoint) scan results are collected correctly and that relevant
3101      * bounds are observed.
3102      */
3103     @Test
testObservedHotspotAps()3104     public void testObservedHotspotAps() throws Exception {
3105         List<ScanDetail> scan = new ArrayList<ScanDetail>();
3106         // 2 R1 (Unknown AP isn't counted) passpoint APs belonging to a single provider: hessid1
3107         long hessid1 = 10;
3108         int anqpDomainId1 = 5;
3109         scan.add(buildMockScanDetailPasspoint("PASSPOINT_XX", "00:02:03:04:05:06", hessid1,
3110                 anqpDomainId1, NetworkDetail.HSRelease.R1, true));
3111         scan.add(buildMockScanDetailPasspoint("PASSPOINT_XY", "01:02:03:04:05:06", hessid1,
3112                 anqpDomainId1, NetworkDetail.HSRelease.R1, true));
3113         scan.add(buildMockScanDetailPasspoint("PASSPOINT_XYZ", "02:02:03:04:05:06", hessid1,
3114                 anqpDomainId1, NetworkDetail.HSRelease.Unknown, true));
3115         // 2 R2 passpoint APs belonging to a single provider: hessid2
3116         long hessid2 = 12;
3117         int anqpDomainId2 = 6;
3118         scan.add(buildMockScanDetailPasspoint("PASSPOINT_Y", "AA:02:03:04:05:06", hessid2,
3119                 anqpDomainId2, NetworkDetail.HSRelease.R2, true));
3120         scan.add(buildMockScanDetailPasspoint("PASSPOINT_Z", "AB:02:03:04:05:06", hessid2,
3121                 anqpDomainId2, NetworkDetail.HSRelease.R2, true));
3122         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
3123         scan = new ArrayList<ScanDetail>();
3124         // 3 R2 passpoint APs belonging to a single provider: hessid3 (in next scan)
3125         long hessid3 = 15;
3126         int anqpDomainId3 = 8;
3127         scan.add(buildMockScanDetailPasspoint("PASSPOINT_Y", "AA:02:03:04:05:06", hessid3,
3128                 anqpDomainId3, NetworkDetail.HSRelease.R2, true));
3129         scan.add(buildMockScanDetailPasspoint("PASSPOINT_Y", "AA:02:03:04:05:06", hessid3,
3130                 anqpDomainId3, NetworkDetail.HSRelease.R2, false));
3131         scan.add(buildMockScanDetailPasspoint("PASSPOINT_Z", "AB:02:03:04:05:06", hessid3,
3132                 anqpDomainId3, NetworkDetail.HSRelease.R2, true));
3133         // 2 R3 Passpoint APs belonging to a single provider: hessid4
3134         long hessid4 = 17;
3135         int anqpDomainId4 = 2;
3136         scan.add(buildMockScanDetailPasspoint("PASSPOINT_R3", "0C:02:03:04:05:01", hessid4,
3137                 anqpDomainId4, NetworkDetail.HSRelease.R3, true));
3138         scan.add(buildMockScanDetailPasspoint("PASSPOINT_R3_2", "0C:02:03:04:05:02", hessid4,
3139                 anqpDomainId4, NetworkDetail.HSRelease.R3, true));
3140         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
3141         dumpProtoAndDeserialize();
3142 
3143         verifyHist(mDecodedProto.observedHotspotR1ApsInScanHistogram, 2, a(0, 2), a(1, 1));
3144         verifyHist(mDecodedProto.observedHotspotR2ApsInScanHistogram, 2, a(2, 3), a(1, 1));
3145         verifyHist(mDecodedProto.observedHotspotR3ApsInScanHistogram, 2, a(0, 2), a(1, 1));
3146         verifyHist(mDecodedProto.observedHotspotR1EssInScanHistogram, 2, a(0, 1), a(1, 1));
3147         verifyHist(mDecodedProto.observedHotspotR2EssInScanHistogram, 1, a(1), a(2));
3148         verifyHist(mDecodedProto.observedHotspotR3EssInScanHistogram, 2, a(0, 1), a(1, 1));
3149         verifyHist(mDecodedProto.observedHotspotR1ApsPerEssInScanHistogram, 1, a(2), a(1));
3150         verifyHist(mDecodedProto.observedHotspotR2ApsPerEssInScanHistogram, 2, a(2, 3), a(1, 1));
3151         verifyHist(mDecodedProto.observedHotspotR3ApsPerEssInScanHistogram, 1, a(2), a(1));
3152 
3153         // check bounds
3154         scan.clear();
3155         int lotsOfSSids = Math.max(WifiMetrics.MAX_TOTAL_PASSPOINT_APS_BUCKET,
3156                 WifiMetrics.MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET) + 5;
3157         for (int i = 0; i < lotsOfSSids; i++) {
3158             scan.add(buildMockScanDetailPasspoint("PASSPOINT_XX" + i, "00:02:03:04:05:06", i,
3159                     i + 10, NetworkDetail.HSRelease.R1, true));
3160             scan.add(buildMockScanDetailPasspoint("PASSPOINT_XY" + i, "AA:02:03:04:05:06", 1000 * i,
3161                     i + 10, NetworkDetail.HSRelease.R2, false));
3162             scan.add(buildMockScanDetailPasspoint("PASSPOINT_XZ" + i, "0B:02:03:04:05:06", 101 * i,
3163                     i + 10, NetworkDetail.HSRelease.R3, false));
3164         }
3165         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
3166         dumpProtoAndDeserialize();
3167         verifyHist(mDecodedProto.observedHotspotR1ApsInScanHistogram, 1,
3168                 a(WifiMetrics.MAX_TOTAL_PASSPOINT_APS_BUCKET), a(1));
3169         verifyHist(mDecodedProto.observedHotspotR2ApsInScanHistogram, 1,
3170                 a(WifiMetrics.MAX_TOTAL_PASSPOINT_APS_BUCKET), a(1));
3171         verifyHist(mDecodedProto.observedHotspotR3ApsInScanHistogram, 1,
3172                 a(WifiMetrics.MAX_TOTAL_PASSPOINT_APS_BUCKET), a(1));
3173         verifyHist(mDecodedProto.observedHotspotR1EssInScanHistogram, 1,
3174                 a(WifiMetrics.MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET), a(1));
3175         verifyHist(mDecodedProto.observedHotspotR2EssInScanHistogram, 1,
3176                 a(WifiMetrics.MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET), a(1));
3177         verifyHist(mDecodedProto.observedHotspotR3EssInScanHistogram, 1,
3178                 a(WifiMetrics.MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET), a(1));
3179     }
3180 
3181     /**
3182      * Test that IEEE 802.11mc scan results are collected correctly and that relevant
3183      * bounds are observed.
3184      */
3185     @Test
testObserved80211mcAps()3186     public void testObserved80211mcAps() throws Exception {
3187         ScanDetail mockScanDetailNon80211mc = mock(ScanDetail.class);
3188         ScanDetail mockScanDetail80211mc = mock(ScanDetail.class);
3189         NetworkDetail mockNetworkDetailNon80211mc = mock(NetworkDetail.class);
3190         NetworkDetail mockNetworkDetail80211mc = mock(NetworkDetail.class);
3191         when(mockNetworkDetail80211mc.is80211McResponderSupport()).thenReturn(true);
3192         ScanResult mockScanResult = mock(ScanResult.class);
3193         mockScanResult.capabilities = "";
3194         when(mockScanDetailNon80211mc.getNetworkDetail()).thenReturn(mockNetworkDetailNon80211mc);
3195         when(mockScanDetail80211mc.getNetworkDetail()).thenReturn(mockNetworkDetail80211mc);
3196         when(mockScanDetailNon80211mc.getScanResult()).thenReturn(mockScanResult);
3197         when(mockScanDetail80211mc.getScanResult()).thenReturn(mockScanResult);
3198         when(mWns.isSignalTooWeak(eq(mockScanDetail80211mc.getScanResult()))).thenReturn(true);
3199         List<ScanDetail> scan = new ArrayList<ScanDetail>();
3200 
3201         // 4 scans (a few non-802.11mc supporting APs on each)
3202         //  scan1: no 802.11mc supporting APs
3203 
3204         scan.add(mockScanDetailNon80211mc);
3205         scan.add(mockScanDetailNon80211mc);
3206         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
3207 
3208         //  scan2: 2 802.11mc supporting APs
3209         scan.clear();
3210         scan.add(mockScanDetailNon80211mc);
3211         scan.add(mockScanDetail80211mc);
3212         scan.add(mockScanDetail80211mc);
3213         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
3214 
3215         //  scan3: 100 802.11mc supporting APs (> limit)
3216         scan.clear();
3217         scan.add(mockScanDetailNon80211mc);
3218         scan.add(mockScanDetailNon80211mc);
3219         scan.add(mockScanDetailNon80211mc);
3220         for (int i = 0; i < 100; ++i) {
3221             scan.add(mockScanDetail80211mc);
3222         }
3223         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
3224 
3225         //  scan4: 2 802.11mc supporting APs
3226         scan.clear();
3227         scan.add(mockScanDetailNon80211mc);
3228         scan.add(mockScanDetail80211mc);
3229         scan.add(mockScanDetail80211mc);
3230         scan.add(mockScanDetailNon80211mc);
3231         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
3232 
3233         dumpProtoAndDeserialize();
3234 
3235         verifyHist(mDecodedProto.observed80211McSupportingApsInScanHistogram, 3,
3236                 a(0, 2, WifiMetrics.MAX_TOTAL_80211MC_APS_BUCKET), a(1, 2, 1));
3237     }
3238 
3239     /**
3240      * Test that country code stats are collected correctly
3241      */
3242     @Test
testCountryCodeStats()3243     public void testCountryCodeStats() throws Exception {
3244         ScanDetail mockScanDetailUs = mock(ScanDetail.class);
3245         ScanDetail mockScanDetailNonUs = mock(ScanDetail.class);
3246         NetworkDetail mockNetworkDetailUs = mock(NetworkDetail.class);
3247         NetworkDetail mockNetworkDetailNonUs = mock(NetworkDetail.class);
3248         when(mockNetworkDetailUs.getCountryCode()).thenReturn("US");
3249         when(mockNetworkDetailNonUs.getCountryCode()).thenReturn("CA");
3250         ScanResult mockScanResult = mock(ScanResult.class);
3251         mockScanResult.capabilities = "";
3252         when(mockScanDetailUs.getScanResult()).thenReturn(mockScanResult);
3253         when(mockScanDetailNonUs.getScanResult()).thenReturn(mockScanResult);
3254         when(mockScanDetailUs.getNetworkDetail()).thenReturn(mockNetworkDetailUs);
3255         when(mockScanDetailNonUs.getNetworkDetail()).thenReturn(mockNetworkDetailNonUs);
3256         List<ScanDetail> scan = new ArrayList<ScanDetail>();
3257 
3258         for (int i = 0; i < (WifiMetrics.MAX_COUNTRY_CODE_COUNT + 1); i++) {
3259             scan.add(mockScanDetailUs);
3260         }
3261         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
3262         when(mTelephonyManager.getNetworkCountryIso()).thenReturn("CA");
3263         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
3264         scan.add(mockScanDetailNonUs);
3265         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
3266 
3267         dumpProtoAndDeserialize();
3268 
3269         Int32Count[] expectedCountryCodeScanHistogram = {
3270                 buildInt32Count(WifiMetrics.COUNTRY_CODE_CONFLICT_WIFI_SCAN_TELEPHONY, 1),
3271                 buildInt32Count(WifiMetrics.COUNTRY_CODE_CONFLICT_WIFI_SCAN, 1),
3272                 buildInt32Count(WifiMetrics.MAX_COUNTRY_CODE_COUNT, 1),
3273         };
3274         assertKeyCountsEqual(expectedCountryCodeScanHistogram,
3275                 mDecodedProto.countryCodeScanHistogram);
3276     }
3277 
3278 
3279     /**
3280      * Test Open Network Notification blocklist size and feature state are not cleared when proto
3281      * is dumped.
3282      */
3283     @Test
testOpenNetworkNotificationBlocklistSizeAndFeatureStateNotCleared()3284     public void testOpenNetworkNotificationBlocklistSizeAndFeatureStateNotCleared()
3285             throws Exception {
3286         mWifiMetrics.setNetworkRecommenderBlocklistSize(OPEN_NET_NOTIFIER_TAG,
3287                 SIZE_OPEN_NETWORK_RECOMMENDER_BLOCKLIST);
3288         mWifiMetrics.setIsWifiNetworksAvailableNotificationEnabled(OPEN_NET_NOTIFIER_TAG,
3289                 IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON);
3290         for (int i = 0; i < NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES; i++) {
3291             mWifiMetrics.incrementNumNetworkRecommendationUpdates(OPEN_NET_NOTIFIER_TAG);
3292         }
3293 
3294         // This should clear most metrics in mWifiMetrics
3295         dumpProtoAndDeserialize();
3296         assertEquals(SIZE_OPEN_NETWORK_RECOMMENDER_BLOCKLIST,
3297                 mDecodedProto.openNetworkRecommenderBlocklistSize);
3298         assertEquals(IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
3299                 mDecodedProto.isWifiNetworksAvailableNotificationOn);
3300         assertEquals(NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES,
3301                 mDecodedProto.numOpenNetworkRecommendationUpdates);
3302 
3303         // Check that blocklist size and feature state persist on next dump but
3304         // others do not.
3305         dumpProtoAndDeserialize();
3306         assertEquals(SIZE_OPEN_NETWORK_RECOMMENDER_BLOCKLIST,
3307                 mDecodedProto.openNetworkRecommenderBlocklistSize);
3308         assertEquals(IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
3309                 mDecodedProto.isWifiNetworksAvailableNotificationOn);
3310         assertEquals(0, mDecodedProto.numOpenNetworkRecommendationUpdates);
3311     }
3312 
3313     /**
3314      * Check network selector id
3315      */
3316     @Test
testNetworkSelectorExperimentId()3317     public void testNetworkSelectorExperimentId() throws Exception {
3318         final int id = 42888888;
3319         mWifiMetrics.setNetworkSelectorExperimentId(id);
3320         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, mTestWifiConfig,
3321                 "TestNetwork", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
3322         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
3323                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
3324                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
3325                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
3326         dumpProtoAndDeserialize();
3327         assertEquals(id, mDecodedProto.connectionEvent[0].networkSelectorExperimentId);
3328     }
3329 
3330     /**
3331      * Check pmk cache
3332      */
3333     @Test
testConnectionWithPmkCache()3334     public void testConnectionWithPmkCache() throws Exception {
3335         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, mTestWifiConfig,
3336                 "TestNetwork", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
3337         mWifiMetrics.setConnectionPmkCache(TEST_IFACE_NAME, true);
3338         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
3339                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
3340                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
3341                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
3342         dumpProtoAndDeserialize();
3343         assertEquals(true, mDecodedProto.connectionEvent[0].routerFingerprint.pmkCacheEnabled);
3344     }
3345 
3346     /**
3347      * Check max supported link speed and consecutive connection failure count
3348      */
3349     @Test
testConnectionMaxSupportedLinkSpeedConsecutiveFailureCnt()3350     public void testConnectionMaxSupportedLinkSpeedConsecutiveFailureCnt() throws Exception {
3351         setScreenState(true);
3352         when(mNetworkConnectionStats.getCount(WifiScoreCard.CNT_CONSECUTIVE_CONNECTION_FAILURE))
3353                 .thenReturn(2);
3354         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, mTestWifiConfig,
3355                 "TestNetwork", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
3356         mWifiMetrics.setConnectionMaxSupportedLinkSpeedMbps(TEST_IFACE_NAME,
3357                 MAX_SUPPORTED_TX_LINK_SPEED_MBPS, MAX_SUPPORTED_RX_LINK_SPEED_MBPS);
3358         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
3359                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
3360                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
3361                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
3362         dumpProtoAndDeserialize();
3363         assertEquals(MAX_SUPPORTED_TX_LINK_SPEED_MBPS, mDecodedProto.connectionEvent[0]
3364                 .routerFingerprint.maxSupportedTxLinkSpeedMbps);
3365         assertEquals(MAX_SUPPORTED_RX_LINK_SPEED_MBPS, mDecodedProto.connectionEvent[0]
3366                 .routerFingerprint.maxSupportedRxLinkSpeedMbps);
3367         assertEquals(2, mDecodedProto.connectionEvent[0].numConsecutiveConnectionFailure);
3368         assertEquals(true, mDecodedProto.connectionEvent[0].screenOn);
3369     }
3370 
3371     /**
3372      * Check ScoringParams
3373      */
3374     @Test
testExperimentId()3375     public void testExperimentId() throws Exception {
3376         final int id = 42;
3377         final String expectId = "x" + id;
3378         when(mScoringParams.getExperimentIdentifier()).thenReturn(id);
3379         dumpProtoAndDeserialize();
3380         assertEquals(expectId, mDecodedProto.scoreExperimentId);
3381     }
3382 
3383     /**
3384      * Check ScoringParams default case
3385      */
3386     @Test
testDefaultExperimentId()3387     public void testDefaultExperimentId() throws Exception {
3388         final int id = 0;
3389         final String expectId = "";
3390         when(mScoringParams.getExperimentIdentifier()).thenReturn(id);
3391         dumpProtoAndDeserialize();
3392         assertEquals(expectId, mDecodedProto.scoreExperimentId);
3393     }
3394 
3395     /** short hand for instantiating an anonymous int array, instead of 'new int[]{a1, a2, ...}' */
a(int... element)3396     private int[] a(int... element) {
3397         return element;
3398     }
3399 
verifyHist(WifiMetricsProto.NumConnectableNetworksBucket[] hist, int size, int[] keys, int[] counts)3400     private void verifyHist(WifiMetricsProto.NumConnectableNetworksBucket[] hist, int size,
3401             int[] keys, int[] counts) throws Exception {
3402         assertEquals(size, hist.length);
3403         for (int i = 0; i < keys.length; i++) {
3404             assertEquals(keys[i], hist[i].numConnectableNetworks);
3405             assertEquals(counts[i], hist[i].count);
3406         }
3407     }
3408 
3409     /**
3410      * Generate an RSSI delta event by creating a connection event and an RSSI poll within
3411      * 'interArrivalTime' milliseconds of each other.
3412      * Event will not be logged if interArrivalTime > mWifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS
3413      * successfulConnectionEvent, completeConnectionEvent, useValidScanResult and
3414      * dontDeserializeBeforePoll
3415      * each create an anomalous condition when set to false.
3416      */
generateRssiDelta(int scanRssi, int rssiDelta, long interArrivalTime, boolean successfulConnectionEvent, boolean completeConnectionEvent, boolean useValidScanResult, boolean dontDeserializeBeforePoll)3417     private void generateRssiDelta(int scanRssi, int rssiDelta,
3418             long interArrivalTime, boolean successfulConnectionEvent,
3419             boolean completeConnectionEvent, boolean useValidScanResult,
3420             boolean dontDeserializeBeforePoll) throws Exception {
3421         when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 0);
3422         ScanResult scanResult = null;
3423         if (useValidScanResult) {
3424             scanResult = mock(ScanResult.class);
3425             scanResult.level = scanRssi;
3426         }
3427         WifiConfiguration config = mock(WifiConfiguration.class);
3428         WifiConfiguration.NetworkSelectionStatus networkSelectionStat =
3429                 mock(WifiConfiguration.NetworkSelectionStatus.class);
3430         config.allowedKeyManagement = new BitSet();
3431         when(networkSelectionStat.getCandidate()).thenReturn(scanResult);
3432         when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStat);
3433         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, config,
3434                 "TestNetwork", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
3435         if (completeConnectionEvent) {
3436             if (successfulConnectionEvent) {
3437                 mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
3438                         WifiMetrics.ConnectionEvent.FAILURE_NONE,
3439                         WifiMetricsProto.ConnectionEvent.HLF_NONE,
3440                         WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
3441             } else {
3442                 mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
3443                         WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
3444                         WifiMetricsProto.ConnectionEvent.HLF_NONE,
3445                         WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
3446             }
3447         }
3448         when(mClock.getElapsedSinceBootMillis()).thenReturn(interArrivalTime);
3449         if (!dontDeserializeBeforePoll) {
3450             dumpProtoAndDeserialize();
3451         }
3452         mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, scanRssi + rssiDelta);
3453     }
3454 
3455     /**
3456      * Generate an RSSI delta event, with all extra conditions set to true.
3457      */
generateRssiDelta(int scanRssi, int rssiDelta, long interArrivalTime)3458     private void generateRssiDelta(int scanRssi, int rssiDelta,
3459             long interArrivalTime) throws Exception {
3460         generateRssiDelta(scanRssi, rssiDelta, interArrivalTime, true, true, true, true);
3461     }
3462 
assertStringContains( String actualString, String expectedSubstring)3463     private void assertStringContains(
3464             String actualString, String expectedSubstring) {
3465         assertTrue("Expected text not found in: " + actualString,
3466                 actualString.contains(expectedSubstring));
3467     }
3468 
getStateDump()3469     private String getStateDump() {
3470         ByteArrayOutputStream stream = new ByteArrayOutputStream();
3471         PrintWriter writer = new PrintWriter(stream);
3472         String[] args = new String[0];
3473         mWifiMetrics.dump(null, writer, args);
3474         writer.flush();
3475         return stream.toString();
3476     }
3477 
3478     private static final int TEST_ALLOWED_KEY_MANAGEMENT = 16;
3479     private static final int TEST_ALLOWED_PROTOCOLS = 22;
3480     private static final int TEST_ALLOWED_AUTH_ALGORITHMS = 11;
3481     private static final int TEST_ALLOWED_PAIRWISE_CIPHERS = 67;
3482     private static final int TEST_ALLOWED_GROUP_CIPHERS = 231;
3483     private static final int TEST_CANDIDATE_LEVEL = -80;
3484     private static final int TEST_CANDIDATE_FREQ = 2450;
3485 
createComplexWifiConfig()3486     private WifiConfiguration createComplexWifiConfig() {
3487         WifiConfiguration config = new WifiConfiguration();
3488         config.SSID = SSID;
3489         config.allowedKeyManagement = intToBitSet(TEST_ALLOWED_KEY_MANAGEMENT);
3490         config.allowedProtocols = intToBitSet(TEST_ALLOWED_PROTOCOLS);
3491         config.allowedAuthAlgorithms = intToBitSet(TEST_ALLOWED_AUTH_ALGORITHMS);
3492         config.allowedPairwiseCiphers = intToBitSet(TEST_ALLOWED_PAIRWISE_CIPHERS);
3493         config.allowedGroupCiphers = intToBitSet(TEST_ALLOWED_GROUP_CIPHERS);
3494         config.hiddenSSID = true;
3495         config.ephemeral = true;
3496         config.getNetworkSelectionStatus().setHasEverConnected(true);
3497         ScanResult candidate = new ScanResult();
3498         candidate.level = TEST_CANDIDATE_LEVEL;
3499         candidate.frequency = TEST_CANDIDATE_FREQ;
3500         config.getNetworkSelectionStatus().setCandidate(candidate);
3501         return config;
3502     }
3503 
assertConfigInfoEqualsWifiConfig(WifiConfiguration config, StaEvent.ConfigInfo info)3504     private void assertConfigInfoEqualsWifiConfig(WifiConfiguration config,
3505             StaEvent.ConfigInfo info) {
3506         if (config == null && info == null) return;
3507         assertEquals(config.allowedKeyManagement,   intToBitSet(info.allowedKeyManagement));
3508         assertEquals(config.allowedProtocols,       intToBitSet(info.allowedProtocols));
3509         assertEquals(config.allowedAuthAlgorithms,  intToBitSet(info.allowedAuthAlgorithms));
3510         assertEquals(config.allowedPairwiseCiphers, intToBitSet(info.allowedPairwiseCiphers));
3511         assertEquals(config.allowedGroupCiphers,    intToBitSet(info.allowedGroupCiphers));
3512         assertEquals(config.hiddenSSID, info.hiddenSsid);
3513         assertEquals(config.ephemeral, info.isEphemeral);
3514         assertEquals(config.getNetworkSelectionStatus().hasEverConnected(),
3515                 info.hasEverConnected);
3516         assertEquals(config.getNetworkSelectionStatus().getCandidate().level, info.scanRssi);
3517         assertEquals(config.getNetworkSelectionStatus().getCandidate().frequency, info.scanFreq);
3518     }
3519 
3520     /**
3521      * Sets the values of bitSet to match an int mask
3522      */
intToBitSet(int mask)3523     private static BitSet intToBitSet(int mask) {
3524         BitSet bitSet = new BitSet();
3525         for (int bitIndex = 0; mask > 0; mask >>>= 1, bitIndex++) {
3526             if ((mask & 1) != 0) bitSet.set(bitIndex);
3527         }
3528         return bitSet;
3529     }
3530 
3531     private static final int NUM_UNUSABLE_EVENT = 5;
3532     private static final int NUM_UNUSABLE_EVENT_TIME_THROTTLE = 3;
3533 
3534     /**
3535      * Values used to generate WifiIsUnusableEvent
3536      * <WifiIsUnusableEvent.TriggerType>, <last_score>, <tx_success_delta>, <tx_retries_delta>,
3537      * <tx_bad_delta>, <rx_success_delta>, <packet_update_time_delta>, <firmware_alert_code>,
3538      * <last_wifi_usability_score>, <mobile_tx_bytes>, <mobile_rx_bytes>, <total_tx_bytes>,
3539      * <total_rx_bytes>,
3540      */
3541     private int[][] mTestUnusableEvents = {
3542         {WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX,        60,  60,  50,  40,  30,  1000,  -1, 51,
3543                 11, 12, 13, 14},
3544         {WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX, 55,  40,  30,  0,   0,   500,   -1, 52,
3545                 15, 16, 17, 18},
3546         {WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH,          60,  90,  30,  30,  0,   1000,  -1, 53,
3547                 19, 20, 21, 22},
3548         {WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT,           55,  55,  30,  15,  10,  1000,   4, 54,
3549                 23, 24, 25, 26},
3550         {WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST,     50,  56,  28,  17,  12,  1000,  -1, 45,
3551                 27, 28, 29, 30}
3552     };
3553 
3554     /**
3555      * Generate all WifiIsUnusableEvents from mTestUnusableEvents
3556      */
generateAllUnusableEvents(WifiMetrics wifiMetrics)3557     private void generateAllUnusableEvents(WifiMetrics wifiMetrics) {
3558         for (int i = 0; i < mTestUnusableEvents.length; i++) {
3559             generateUnusableEventAtGivenTime(i, i * (WifiMetrics.MIN_DATA_STALL_WAIT_MS + 1000));
3560         }
3561     }
3562 
3563     /**
3564      * Generate a WifiIsUnusableEvent at the given timestamp with data from
3565      * mTestUnusableEvents[index]
3566      */
generateUnusableEventAtGivenTime(int index, long eventTime)3567     private void generateUnusableEventAtGivenTime(int index, long eventTime) {
3568         when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTime);
3569         int[] trigger = mTestUnusableEvents[index];
3570         when(mFacade.getMobileTxBytes()).thenReturn((long) trigger[9]);
3571         when(mFacade.getMobileRxBytes()).thenReturn((long) trigger[10]);
3572         when(mFacade.getTotalTxBytes()).thenReturn((long) trigger[11]);
3573         when(mFacade.getTotalRxBytes()).thenReturn((long) trigger[12]);
3574         mWifiMetrics.incrementWifiScoreCount(TEST_IFACE_NAME, trigger[1]);
3575         mWifiMetrics.incrementWifiUsabilityScoreCount(TEST_IFACE_NAME, 1, trigger[8], 15);
3576         mWifiMetrics.updateWifiIsUnusableLinkLayerStats(trigger[2], trigger[3], trigger[4],
3577                 trigger[5], trigger[6]);
3578         setScreenState(true);
3579         switch(trigger[0]) {
3580             case WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX:
3581             case WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX:
3582             case WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH:
3583                 mWifiMetrics.logWifiIsUnusableEvent(TEST_IFACE_NAME, trigger[0]);
3584                 break;
3585             case WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT:
3586                 mWifiMetrics.logWifiIsUnusableEvent(TEST_IFACE_NAME, trigger[0], trigger[7]);
3587                 break;
3588             case WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST:
3589                 mWifiMetrics.logWifiIsUnusableEvent(TEST_IFACE_NAME, trigger[0]);
3590                 break;
3591             default:
3592                 break;
3593         }
3594     }
3595 
3596     /**
3597      * Verify that WifiIsUnusableEvent in wifiLog matches mTestUnusableEvents
3598      */
verifyDeserializedUnusableEvents(WifiMetricsProto.WifiLog wifiLog)3599     private void verifyDeserializedUnusableEvents(WifiMetricsProto.WifiLog wifiLog) {
3600         assertEquals(NUM_UNUSABLE_EVENT, wifiLog.wifiIsUnusableEventList.length);
3601         for (int i = 0; i < mTestUnusableEvents.length; i++) {
3602             WifiIsUnusableEvent event = wifiLog.wifiIsUnusableEventList[i];
3603             verifyUnusableEvent(event, i);
3604         }
3605     }
3606 
3607     /**
3608      * Verify that the given WifiIsUnusableEvent matches mTestUnusableEvents
3609      * at given index
3610      */
verifyUnusableEvent(WifiIsUnusableEvent event, int index)3611     private void verifyUnusableEvent(WifiIsUnusableEvent event, int index) {
3612         int[] expectedValues = mTestUnusableEvents[index];
3613         assertEquals(expectedValues[0], event.type);
3614         assertEquals(expectedValues[1], event.lastScore);
3615         assertEquals(expectedValues[2], event.txSuccessDelta);
3616         assertEquals(expectedValues[3], event.txRetriesDelta);
3617         assertEquals(expectedValues[4], event.txBadDelta);
3618         assertEquals(expectedValues[5], event.rxSuccessDelta);
3619         assertEquals(expectedValues[6], event.packetUpdateTimeDelta);
3620         assertEquals(expectedValues[7], event.firmwareAlertCode);
3621         assertEquals(expectedValues[8], event.lastWifiUsabilityScore);
3622         assertEquals(true, event.screenOn);
3623         assertEquals(expectedValues[9], event.mobileTxBytes);
3624         assertEquals(expectedValues[10], event.mobileRxBytes);
3625         assertEquals(expectedValues[11], event.totalTxBytes);
3626         assertEquals(expectedValues[12], event.totalRxBytes);
3627     }
3628 
3629     /**
3630      * Verify that no WifiIsUnusableEvent is generated when it is disabled in the settings
3631      */
3632     @Test
testNoUnusableEventLogWhenDisabled()3633     public void testNoUnusableEventLogWhenDisabled() throws Exception {
3634         mResources.setBoolean(R.bool.config_wifiIsUnusableEventMetricsEnabled, false);
3635         generateAllUnusableEvents(mWifiMetrics);
3636         dumpProtoAndDeserialize();
3637         assertEquals(0, mDecodedProto.wifiIsUnusableEventList.length);
3638     }
3639 
3640     /**
3641      * Generate WifiIsUnusableEvent and verify that they are logged correctly
3642      */
3643     @Test
testUnusableEventLogSerializeDeserialize()3644     public void testUnusableEventLogSerializeDeserialize() throws Exception {
3645         mResources.setBoolean(R.bool.config_wifiIsUnusableEventMetricsEnabled, true);
3646         generateAllUnusableEvents(mWifiMetrics);
3647         dumpProtoAndDeserialize();
3648         verifyDeserializedUnusableEvents(mDecodedProto);
3649     }
3650 
3651     /**
3652      * Verify that the number of WifiIsUnusableEvents does not exceed MAX_UNUSABLE_EVENTS
3653      */
3654     @Test
testUnusableEventBounding()3655     public void testUnusableEventBounding() throws Exception {
3656         mResources.setBoolean(R.bool.config_wifiIsUnusableEventMetricsEnabled, true);
3657         for (int i = 0; i < (WifiMetrics.MAX_UNUSABLE_EVENTS + 2); i++) {
3658             generateAllUnusableEvents(mWifiMetrics);
3659         }
3660         dumpProtoAndDeserialize();
3661         assertEquals(WifiMetrics.MAX_UNUSABLE_EVENTS, mDecodedProto.wifiIsUnusableEventList.length);
3662     }
3663 
3664     /**
3665      * Verify that we don't generate new WifiIsUnusableEvent from data stalls
3666      * until MIN_DATA_STALL_WAIT_MS has passed since the last data stall WifiIsUnusableEvent
3667      */
3668     @Test
testUnusableEventTimeThrottleForDataStall()3669     public void testUnusableEventTimeThrottleForDataStall() throws Exception {
3670         mResources.setBoolean(R.bool.config_wifiIsUnusableEventMetricsEnabled, true);
3671         generateUnusableEventAtGivenTime(0, 0);
3672         // should be time throttled
3673         generateUnusableEventAtGivenTime(1, 1);
3674         generateUnusableEventAtGivenTime(2, WifiMetrics.MIN_DATA_STALL_WAIT_MS + 1000);
3675         // no time throttle for firmware alert
3676         generateUnusableEventAtGivenTime(3, WifiMetrics.MIN_DATA_STALL_WAIT_MS + 1001);
3677         dumpProtoAndDeserialize();
3678         assertEquals(NUM_UNUSABLE_EVENT_TIME_THROTTLE,
3679                 mDecodedProto.wifiIsUnusableEventList.length);
3680         verifyUnusableEvent(mDecodedProto.wifiIsUnusableEventList[0], 0);
3681         verifyUnusableEvent(mDecodedProto.wifiIsUnusableEventList[1], 2);
3682         verifyUnusableEvent(mDecodedProto.wifiIsUnusableEventList[2], 3);
3683     }
3684 
3685     /**
3686      * Verify that LinkSpeedCounts is correctly logged in metrics
3687      */
3688     @Test
testLinkSpeedCounts()3689     public void testLinkSpeedCounts() throws Exception {
3690         mResources.setBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled, true);
3691         for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) {
3692             for (int j = 0; j <= i; j++) {
3693                 mWifiMetrics.incrementLinkSpeedCount(
3694                         WifiMetrics.MIN_LINK_SPEED_MBPS + i, TEST_RSSI_LEVEL);
3695             }
3696         }
3697         dumpProtoAndDeserialize();
3698         assertEquals(NUM_LINK_SPEED_LEVELS_TO_INCREMENT, mDecodedProto.linkSpeedCounts.length);
3699         for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) {
3700             assertEquals("Incorrect link speed", WifiMetrics.MIN_LINK_SPEED_MBPS + i,
3701                     mDecodedProto.linkSpeedCounts[i].linkSpeedMbps);
3702             assertEquals("Incorrect count of link speed",
3703                     i + 1, mDecodedProto.linkSpeedCounts[i].count);
3704             assertEquals("Incorrect sum of absolute values of rssi values",
3705                     Math.abs(TEST_RSSI_LEVEL) * (i + 1),
3706                     mDecodedProto.linkSpeedCounts[i].rssiSumDbm);
3707             assertEquals("Incorrect sum of squares of rssi values",
3708                     TEST_RSSI_LEVEL * TEST_RSSI_LEVEL * (i + 1),
3709                     mDecodedProto.linkSpeedCounts[i].rssiSumOfSquaresDbmSq);
3710         }
3711     }
3712 
3713     /**
3714      * Verify that Tx and Rx per-band LinkSpeedCounts are correctly logged in metrics
3715      */
3716     @Test
testTxRxLinkSpeedBandCounts()3717     public void testTxRxLinkSpeedBandCounts() throws Exception {
3718         mResources.setBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled, true);
3719         for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) {
3720             for (int j = 0; j <= i; j++) {
3721                 mWifiMetrics.incrementTxLinkSpeedBandCount(
3722                         WifiMetrics.MIN_LINK_SPEED_MBPS + i, RSSI_POLL_FREQUENCY);
3723                 mWifiMetrics.incrementRxLinkSpeedBandCount(
3724                         WifiMetrics.MIN_LINK_SPEED_MBPS + i + 1, RSSI_POLL_FREQUENCY);
3725             }
3726         }
3727         dumpProtoAndDeserialize();
3728         assertEquals(0, mDecodedProto.txLinkSpeedCount2G.length);
3729         assertEquals(0, mDecodedProto.rxLinkSpeedCount2G.length);
3730         assertEquals(NUM_LINK_SPEED_LEVELS_TO_INCREMENT,
3731                 mDecodedProto.txLinkSpeedCount5GLow.length);
3732         assertEquals(NUM_LINK_SPEED_LEVELS_TO_INCREMENT,
3733                 mDecodedProto.rxLinkSpeedCount5GLow.length);
3734         assertEquals(0, mDecodedProto.txLinkSpeedCount5GMid.length);
3735         assertEquals(0, mDecodedProto.rxLinkSpeedCount5GMid.length);
3736         assertEquals(0, mDecodedProto.txLinkSpeedCount5GHigh.length);
3737         assertEquals(0, mDecodedProto.rxLinkSpeedCount5GHigh.length);
3738         for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) {
3739             assertEquals("Incorrect Tx link speed", WifiMetrics.MIN_LINK_SPEED_MBPS + i,
3740                     mDecodedProto.txLinkSpeedCount5GLow[i].key);
3741             assertEquals("Incorrect Rx link speed", WifiMetrics.MIN_LINK_SPEED_MBPS + i + 1,
3742                     mDecodedProto.rxLinkSpeedCount5GLow[i].key);
3743             assertEquals("Incorrect count of Tx link speed",
3744                     i + 1, mDecodedProto.txLinkSpeedCount5GLow[i].count);
3745             assertEquals("Incorrect count of Rx link speed",
3746                     i + 1, mDecodedProto.rxLinkSpeedCount5GLow[i].count);
3747         }
3748     }
3749 
3750     /**
3751      * Verify that LinkSpeedCounts is not logged when disabled in settings
3752      */
3753     @Test
testNoLinkSpeedCountsWhenDisabled()3754     public void testNoLinkSpeedCountsWhenDisabled() throws Exception {
3755         mResources.setBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled, false);
3756         for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) {
3757             for (int j = 0; j <= i; j++) {
3758                 mWifiMetrics.incrementLinkSpeedCount(
3759                         WifiMetrics.MIN_LINK_SPEED_MBPS + i, TEST_RSSI_LEVEL);
3760                 mWifiMetrics.incrementTxLinkSpeedBandCount(
3761                         WifiMetrics.MIN_LINK_SPEED_MBPS - i, RSSI_POLL_FREQUENCY);
3762                 mWifiMetrics.incrementRxLinkSpeedBandCount(
3763                         WifiMetrics.MIN_LINK_SPEED_MBPS - i, RSSI_POLL_FREQUENCY);
3764             }
3765         }
3766         dumpProtoAndDeserialize();
3767         assertEquals("LinkSpeedCounts should not be logged when disabled in settings",
3768                 0, mDecodedProto.linkSpeedCounts.length);
3769         assertEquals("Tx LinkSpeedCounts should not be logged when disabled in settings",
3770                 0, mDecodedProto.txLinkSpeedCount5GLow.length);
3771         assertEquals("Rx LinkSpeedCounts should not be logged when disabled in settings",
3772                 0, mDecodedProto.rxLinkSpeedCount5GLow.length);
3773     }
3774 
3775     /**
3776      * Verify that LinkSpeedCounts is not logged when the link speed value is lower than
3777      * MIN_LINK_SPEED_MBPS or when the rssi value is outside of
3778      * [MIN_RSSI_LEVEL, MAX_RSSI_LEVEL]
3779      */
3780     @Test
testNoLinkSpeedCountsForOutOfBoundValues()3781     public void testNoLinkSpeedCountsForOutOfBoundValues() throws Exception {
3782         mResources.setBoolean(R.bool.config_wifiLinkSpeedMetricsEnabled, true);
3783         for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
3784             mWifiMetrics.incrementLinkSpeedCount(
3785                     WifiMetrics.MIN_LINK_SPEED_MBPS - i, MIN_RSSI_LEVEL);
3786             mWifiMetrics.incrementTxLinkSpeedBandCount(
3787                     WifiMetrics.MIN_LINK_SPEED_MBPS - i, RSSI_POLL_FREQUENCY);
3788             mWifiMetrics.incrementRxLinkSpeedBandCount(
3789                     WifiMetrics.MIN_LINK_SPEED_MBPS - i, RSSI_POLL_FREQUENCY);
3790         }
3791         for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
3792             mWifiMetrics.incrementLinkSpeedCount(
3793                     WifiMetrics.MIN_LINK_SPEED_MBPS, MIN_RSSI_LEVEL - i);
3794         }
3795         for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
3796             mWifiMetrics.incrementLinkSpeedCount(
3797                     WifiMetrics.MIN_LINK_SPEED_MBPS, MAX_RSSI_LEVEL + i);
3798         }
3799         dumpProtoAndDeserialize();
3800         assertEquals("LinkSpeedCounts should not be logged for out of bound values",
3801                 0, mDecodedProto.linkSpeedCounts.length);
3802         assertEquals("Tx LinkSpeedCounts should not be logged for out of bound values",
3803                 0, mDecodedProto.txLinkSpeedCount5GLow.length);
3804         assertEquals("Rx LinkSpeedCounts should not be logged for out of bound values",
3805                 0, mDecodedProto.rxLinkSpeedCount5GLow.length);
3806     }
3807 
nextRandInt()3808     private int nextRandInt() {
3809         return mRandom.nextInt(1000);
3810     }
3811 
nextRandomStats(WifiLinkLayerStats current)3812     private WifiLinkLayerStats nextRandomStats(WifiLinkLayerStats current) {
3813         WifiLinkLayerStats out = new WifiLinkLayerStats();
3814         out.timeStampInMs = current.timeStampInMs + nextRandInt();
3815 
3816         out.rxmpdu_be = current.rxmpdu_be + nextRandInt();
3817         out.txmpdu_be = current.txmpdu_be + nextRandInt();
3818         out.lostmpdu_be = current.lostmpdu_be + nextRandInt();
3819         out.retries_be = current.retries_be + nextRandInt();
3820 
3821         out.rxmpdu_bk = current.rxmpdu_bk + nextRandInt();
3822         out.txmpdu_bk = current.txmpdu_bk + nextRandInt();
3823         out.lostmpdu_bk = current.lostmpdu_bk + nextRandInt();
3824         out.retries_bk = current.retries_bk + nextRandInt();
3825 
3826         out.rxmpdu_vi = current.rxmpdu_vi + nextRandInt();
3827         out.txmpdu_vi = current.txmpdu_vi + nextRandInt();
3828         out.lostmpdu_vi = current.lostmpdu_vi + nextRandInt();
3829         out.retries_vi = current.retries_vi + nextRandInt();
3830 
3831         out.rxmpdu_vo = current.rxmpdu_vo + nextRandInt();
3832         out.txmpdu_vo = current.txmpdu_vo + nextRandInt();
3833         out.lostmpdu_vo = current.lostmpdu_vo + nextRandInt();
3834         out.retries_vo = current.retries_vo + nextRandInt();
3835 
3836         out.on_time = current.on_time + nextRandInt();
3837         out.tx_time = current.tx_time + nextRandInt();
3838         out.rx_time = current.rx_time + nextRandInt();
3839         out.on_time_scan = current.on_time_scan + nextRandInt();
3840         out.on_time_nan_scan = current.on_time_nan_scan + nextRandInt();
3841         out.on_time_background_scan = current.on_time_background_scan + nextRandInt();
3842         out.on_time_roam_scan = current.on_time_roam_scan + nextRandInt();
3843         out.on_time_pno_scan = current.on_time_pno_scan + nextRandInt();
3844         out.on_time_hs20_scan = current.on_time_hs20_scan + nextRandInt();
3845         out.timeSliceDutyCycleInPercent =
3846                 (short) ((current.timeSliceDutyCycleInPercent + nextRandInt()) % 101);
3847         out.peerInfo = createNewPeerInfo(current.peerInfo);
3848         out.radioStats = createNewRadioStat(current.radioStats);
3849         return out;
3850     }
3851 
createNewPeerInfo(PeerInfo[] current)3852     private PeerInfo[] createNewPeerInfo(PeerInfo[] current) {
3853         if (current == null) {
3854             return null;
3855         }
3856         PeerInfo[] out = new PeerInfo[current.length];
3857         for (int i = 0; i < current.length; i++) {
3858             int numRates = 0;
3859             if (current[i].rateStats != null) {
3860                 numRates = current[i].rateStats.length;
3861             }
3862             RateStat[] rateStats = new RateStat[numRates];
3863             for (int j = 0; j < numRates; j++) {
3864                 RateStat curRate = current[i].rateStats[j];
3865                 RateStat newRate = new RateStat();
3866                 newRate.preamble = curRate.preamble;
3867                 newRate.nss = curRate.nss;
3868                 newRate.bw = curRate.bw;
3869                 newRate.rateMcsIdx = curRate.rateMcsIdx;
3870                 newRate.bitRateInKbps = curRate.bitRateInKbps;
3871                 newRate.txMpdu = curRate.txMpdu + nextRandInt();
3872                 newRate.rxMpdu = curRate.rxMpdu + nextRandInt();
3873                 newRate.mpduLost = curRate.mpduLost + nextRandInt();
3874                 newRate.retries = curRate.retries + nextRandInt();
3875                 rateStats[j] = newRate;
3876             }
3877             out[i] = new PeerInfo();
3878             out[i].rateStats = rateStats;
3879             out[i].staCount = (short) (current[i].staCount + nextRandInt() % 10);
3880             out[i].chanUtil = (short) ((current[i].chanUtil + nextRandInt()) % 100);
3881         }
3882         return out;
3883     }
3884 
createNewRadioStat(RadioStat[] current)3885     private RadioStat[] createNewRadioStat(RadioStat[] current) {
3886         if (current == null) {
3887             return null;
3888         }
3889         RadioStat[] out = new RadioStat[current.length];
3890         for (int i = 0; i < current.length; i++) {
3891             RadioStat currentRadio = current[i];
3892             RadioStat newRadio = new RadioStat();
3893             newRadio.radio_id = currentRadio.radio_id;
3894             newRadio.on_time = currentRadio.on_time + nextRandInt();
3895             newRadio.tx_time = currentRadio.tx_time + nextRandInt();
3896             newRadio.rx_time = currentRadio.rx_time + nextRandInt();
3897             newRadio.on_time_scan = currentRadio.on_time_scan + nextRandInt();
3898             newRadio.on_time_nan_scan = currentRadio.on_time_nan_scan + nextRandInt();
3899             newRadio.on_time_background_scan = currentRadio.on_time_background_scan + nextRandInt();
3900             newRadio.on_time_roam_scan = currentRadio.on_time_roam_scan + nextRandInt();
3901             newRadio.on_time_pno_scan = currentRadio.on_time_pno_scan + nextRandInt();
3902             newRadio.on_time_hs20_scan = currentRadio.on_time_hs20_scan + nextRandInt();
3903             out[i] = newRadio;
3904         }
3905         return out;
3906     }
3907 
assertWifiLinkLayerUsageHasDiff(WifiLinkLayerStats oldStats, WifiLinkLayerStats newStats)3908     private void assertWifiLinkLayerUsageHasDiff(WifiLinkLayerStats oldStats,
3909             WifiLinkLayerStats newStats) {
3910         assertEquals(newStats.timeStampInMs - oldStats.timeStampInMs,
3911                 mDecodedProto.wifiLinkLayerUsageStats.loggingDurationMs);
3912         assertEquals(newStats.on_time - oldStats.on_time,
3913                 mDecodedProto.wifiLinkLayerUsageStats.radioOnTimeMs);
3914         assertEquals(newStats.tx_time - oldStats.tx_time,
3915                 mDecodedProto.wifiLinkLayerUsageStats.radioTxTimeMs);
3916         assertEquals(newStats.rx_time - oldStats.rx_time,
3917                 mDecodedProto.wifiLinkLayerUsageStats.radioRxTimeMs);
3918         assertEquals(newStats.on_time_scan - oldStats.on_time_scan,
3919                 mDecodedProto.wifiLinkLayerUsageStats.radioScanTimeMs);
3920         assertEquals(newStats.on_time_nan_scan - oldStats.on_time_nan_scan,
3921                 mDecodedProto.wifiLinkLayerUsageStats.radioNanScanTimeMs);
3922         assertEquals(newStats.on_time_background_scan - oldStats.on_time_background_scan,
3923                 mDecodedProto.wifiLinkLayerUsageStats.radioBackgroundScanTimeMs);
3924         assertEquals(newStats.on_time_roam_scan - oldStats.on_time_roam_scan,
3925                 mDecodedProto.wifiLinkLayerUsageStats.radioRoamScanTimeMs);
3926         assertEquals(newStats.on_time_pno_scan - oldStats.on_time_pno_scan,
3927                 mDecodedProto.wifiLinkLayerUsageStats.radioPnoScanTimeMs);
3928         assertEquals(newStats.on_time_hs20_scan - oldStats.on_time_hs20_scan,
3929                 mDecodedProto.wifiLinkLayerUsageStats.radioHs20ScanTimeMs);
3930     }
3931 
assertPerRadioStatsUsageHasDiff(WifiLinkLayerStats oldStats, WifiLinkLayerStats newStats)3932     private void assertPerRadioStatsUsageHasDiff(WifiLinkLayerStats oldStats,
3933             WifiLinkLayerStats newStats) {
3934         assertEquals(oldStats.radioStats.length, newStats.radioStats.length);
3935         assertEquals(newStats.radioStats.length,
3936                 mDecodedProto.wifiLinkLayerUsageStats.radioStats.length);
3937         for (int i = 0; i < oldStats.radioStats.length; i++) {
3938             RadioStat oldRadioStats = oldStats.radioStats[i];
3939             RadioStat newRadioStats = newStats.radioStats[i];
3940             RadioStats radioStats =
3941                     mDecodedProto.wifiLinkLayerUsageStats.radioStats[i];
3942             assertEquals(oldRadioStats.radio_id, newRadioStats.radio_id);
3943             assertEquals(newRadioStats.radio_id, radioStats.radioId);
3944             assertEquals(newRadioStats.on_time - oldRadioStats.on_time,
3945                     radioStats.totalRadioOnTimeMs);
3946             assertEquals(newRadioStats.tx_time - oldRadioStats.tx_time,
3947                     radioStats.totalRadioTxTimeMs);
3948             assertEquals(newRadioStats.rx_time - oldRadioStats.rx_time,
3949                     radioStats.totalRadioRxTimeMs);
3950             assertEquals(newRadioStats.on_time_scan - oldRadioStats.on_time_scan,
3951                     radioStats.totalScanTimeMs);
3952             assertEquals(newRadioStats.on_time_nan_scan - oldRadioStats.on_time_nan_scan,
3953                     radioStats.totalNanScanTimeMs);
3954             assertEquals(newRadioStats.on_time_background_scan
3955                     - oldRadioStats.on_time_background_scan,
3956                     radioStats.totalBackgroundScanTimeMs);
3957             assertEquals(newRadioStats.on_time_roam_scan - oldRadioStats.on_time_roam_scan,
3958                     radioStats.totalRoamScanTimeMs);
3959             assertEquals(newRadioStats.on_time_pno_scan - oldRadioStats.on_time_pno_scan,
3960                     radioStats.totalPnoScanTimeMs);
3961             assertEquals(newRadioStats.on_time_hs20_scan - oldRadioStats.on_time_hs20_scan,
3962                     radioStats.totalHotspot2ScanTimeMs);
3963         }
3964     }
3965 
3966     /**
3967      * Verify that WifiMetrics is counting link layer usage correctly when given a series of
3968      * valid input.
3969      * @throws Exception
3970      */
3971     @Test
testWifiLinkLayerUsageStats()3972     public void testWifiLinkLayerUsageStats() throws Exception {
3973         WifiLinkLayerStats stat1 = nextRandomStats(createNewWifiLinkLayerStats());
3974         WifiLinkLayerStats stat2 = nextRandomStats(stat1);
3975         WifiLinkLayerStats stat3 = nextRandomStats(stat2);
3976         mWifiMetrics.incrementWifiLinkLayerUsageStats(TEST_IFACE_NAME, stat1);
3977         mWifiMetrics.incrementWifiLinkLayerUsageStats(TEST_IFACE_NAME, stat2);
3978         mWifiMetrics.incrementWifiLinkLayerUsageStats(TEST_IFACE_NAME, stat3);
3979         dumpProtoAndDeserialize();
3980 
3981         // After 2 increments, the counters should have difference between |stat1| and |stat3|
3982         assertWifiLinkLayerUsageHasDiff(stat1, stat3);
3983         assertPerRadioStatsUsageHasDiff(stat1, stat3);
3984     }
3985 
3986     /**
3987      * Verify that null input is handled and wifi link layer usage stats are not incremented.
3988      * @throws Exception
3989      */
3990     @Test
testWifiLinkLayerUsageStatsNullInput()3991     public void testWifiLinkLayerUsageStatsNullInput() throws Exception {
3992         WifiLinkLayerStats stat1 = nextRandomStats(createNewWifiLinkLayerStats());
3993         WifiLinkLayerStats stat2 = null;
3994         mWifiMetrics.incrementWifiLinkLayerUsageStats(TEST_IFACE_NAME, stat1);
3995         mWifiMetrics.incrementWifiLinkLayerUsageStats(TEST_IFACE_NAME, stat2);
3996         dumpProtoAndDeserialize();
3997 
3998         // Counter should be zero
3999         assertWifiLinkLayerUsageHasDiff(stat1, stat1);
4000         assertNotNull(mDecodedProto.wifiLinkLayerUsageStats.radioStats);
4001     }
4002 
4003     /**
4004      * Verify that when the new data appears to be bad link layer usage stats are not being
4005      * incremented and the buffered WifiLinkLayerStats get cleared.
4006      * @throws Exception
4007      */
4008     @Test
testWifiLinkLayerUsageStatsChipReset()4009     public void testWifiLinkLayerUsageStatsChipReset() throws Exception {
4010         WifiLinkLayerStats stat1 = nextRandomStats(createNewWifiLinkLayerStats());
4011         WifiLinkLayerStats stat2 = nextRandomStats(stat1);
4012         stat2.on_time = stat1.on_time - 1;
4013         WifiLinkLayerStats stat3 = nextRandomStats(stat2);
4014         WifiLinkLayerStats stat4 = nextRandomStats(stat3);
4015         mWifiMetrics.incrementWifiLinkLayerUsageStats(TEST_IFACE_NAME, stat1);
4016         mWifiMetrics.incrementWifiLinkLayerUsageStats(TEST_IFACE_NAME, stat2);
4017         mWifiMetrics.incrementWifiLinkLayerUsageStats(TEST_IFACE_NAME, stat3);
4018         mWifiMetrics.incrementWifiLinkLayerUsageStats(TEST_IFACE_NAME, stat4);
4019         dumpProtoAndDeserialize();
4020 
4021         // Should only count the difference between |stat3| and |stat4|
4022         assertWifiLinkLayerUsageHasDiff(stat3, stat4);
4023         assertPerRadioStatsUsageHasDiff(stat3, stat4);
4024     }
4025 
assertUsabilityStatsAssignment(WifiInfo info, WifiLinkLayerStats stats, WifiUsabilityStatsEntry usabilityStats)4026     private void assertUsabilityStatsAssignment(WifiInfo info, WifiLinkLayerStats stats,
4027             WifiUsabilityStatsEntry usabilityStats) {
4028         assertEquals(info.getRssi(), usabilityStats.rssi);
4029         assertEquals(info.getLinkSpeed(), usabilityStats.linkSpeedMbps);
4030         assertEquals(info.getRxLinkSpeedMbps(), usabilityStats.rxLinkSpeedMbps);
4031         assertEquals(stats.timeStampInMs, usabilityStats.timeStampMs);
4032         assertEquals(stats.txmpdu_be + stats.txmpdu_bk + stats.txmpdu_vi + stats.txmpdu_vo,
4033                 usabilityStats.totalTxSuccess);
4034         assertEquals(stats.retries_be + stats.retries_bk + stats.retries_vi + stats.retries_vo,
4035                 usabilityStats.totalTxRetries);
4036         assertEquals(stats.lostmpdu_be + stats.lostmpdu_bk + stats.lostmpdu_vi + stats.lostmpdu_vo,
4037                 usabilityStats.totalTxBad);
4038         assertEquals(stats.rxmpdu_be + stats.rxmpdu_bk + stats.rxmpdu_vi + stats.rxmpdu_vo,
4039                 usabilityStats.totalRxSuccess);
4040         assertEquals(stats.radioStats.length, usabilityStats.radioStats.length);
4041         for (int i = 0; i < stats.radioStats.length; i++) {
4042             RadioStat radio = stats.radioStats[i];
4043             RadioStats radioStats = usabilityStats.radioStats[i];
4044             assertEquals(radio.radio_id, radioStats.radioId);
4045             assertEquals(radio.on_time, radioStats.totalRadioOnTimeMs);
4046             assertEquals(radio.tx_time, radioStats.totalRadioTxTimeMs);
4047             assertEquals(radio.rx_time, radioStats.totalRadioRxTimeMs);
4048             assertEquals(radio.on_time_scan, radioStats.totalScanTimeMs);
4049             assertEquals(radio.on_time_nan_scan, radioStats.totalNanScanTimeMs);
4050             assertEquals(radio.on_time_background_scan, radioStats.totalBackgroundScanTimeMs);
4051             assertEquals(radio.on_time_roam_scan, radioStats.totalRoamScanTimeMs);
4052             assertEquals(radio.on_time_pno_scan, radioStats.totalPnoScanTimeMs);
4053             assertEquals(radio.on_time_hs20_scan, radioStats.totalHotspot2ScanTimeMs);
4054         }
4055         assertEquals(stats.on_time, usabilityStats.totalRadioOnTimeMs);
4056         assertEquals(stats.tx_time, usabilityStats.totalRadioTxTimeMs);
4057         assertEquals(stats.rx_time, usabilityStats.totalRadioRxTimeMs);
4058         assertEquals(stats.on_time_scan, usabilityStats.totalScanTimeMs);
4059         assertEquals(stats.on_time_nan_scan, usabilityStats.totalNanScanTimeMs);
4060         assertEquals(stats.on_time_background_scan, usabilityStats.totalBackgroundScanTimeMs);
4061         assertEquals(stats.on_time_roam_scan, usabilityStats.totalRoamScanTimeMs);
4062         assertEquals(stats.on_time_pno_scan, usabilityStats.totalPnoScanTimeMs);
4063         assertEquals(stats.on_time_hs20_scan, usabilityStats.totalHotspot2ScanTimeMs);
4064         assertEquals(stats.beacon_rx, usabilityStats.totalBeaconRx);
4065         assertEquals(stats.timeSliceDutyCycleInPercent, usabilityStats.timeSliceDutyCycleInPercent);
4066         assertEquals(stats.contentionTimeMinBeInUsec,
4067                 usabilityStats.contentionTimeStats[0].contentionTimeMinMicros);
4068         assertEquals(stats.contentionTimeMaxBeInUsec,
4069                 usabilityStats.contentionTimeStats[0].contentionTimeMaxMicros);
4070         assertEquals(stats.contentionTimeAvgBeInUsec,
4071                 usabilityStats.contentionTimeStats[0].contentionTimeAvgMicros);
4072         assertEquals(stats.contentionNumSamplesBe,
4073                 usabilityStats.contentionTimeStats[0].contentionNumSamples);
4074         assertEquals(stats.contentionTimeMinBkInUsec,
4075                 usabilityStats.contentionTimeStats[1].contentionTimeMinMicros);
4076         assertEquals(stats.contentionTimeMaxBkInUsec,
4077                 usabilityStats.contentionTimeStats[1].contentionTimeMaxMicros);
4078         assertEquals(stats.contentionTimeAvgBkInUsec,
4079                 usabilityStats.contentionTimeStats[1].contentionTimeAvgMicros);
4080         assertEquals(stats.contentionNumSamplesBk,
4081                 usabilityStats.contentionTimeStats[1].contentionNumSamples);
4082         assertEquals(stats.contentionTimeMinViInUsec,
4083                 usabilityStats.contentionTimeStats[2].contentionTimeMinMicros);
4084         assertEquals(stats.contentionTimeMaxViInUsec,
4085                 usabilityStats.contentionTimeStats[2].contentionTimeMaxMicros);
4086         assertEquals(stats.contentionTimeAvgViInUsec,
4087                 usabilityStats.contentionTimeStats[2].contentionTimeAvgMicros);
4088         assertEquals(stats.contentionNumSamplesVi,
4089                 usabilityStats.contentionTimeStats[2].contentionNumSamples);
4090         assertEquals(stats.contentionTimeMinVoInUsec,
4091                 usabilityStats.contentionTimeStats[3].contentionTimeMinMicros);
4092         assertEquals(stats.contentionTimeMaxVoInUsec,
4093                 usabilityStats.contentionTimeStats[3].contentionTimeMaxMicros);
4094         assertEquals(stats.contentionTimeAvgVoInUsec,
4095                 usabilityStats.contentionTimeStats[3].contentionTimeAvgMicros);
4096         assertEquals(stats.contentionNumSamplesVo,
4097                 usabilityStats.contentionTimeStats[3].contentionNumSamples);
4098         for (int i = 0; i < stats.peerInfo.length; i++) {
4099             PeerInfo curPeer = stats.peerInfo[i];
4100             assertEquals(curPeer.staCount, usabilityStats.staCount);
4101             assertEquals(curPeer.chanUtil, usabilityStats.channelUtilization);
4102             for (int j = 0; j < curPeer.rateStats.length; j++) {
4103                 RateStat rate = curPeer.rateStats[j];
4104                 RateStats usabilityRate = usabilityStats.rateStats[j];
4105                 assertEquals(rate.preamble, usabilityRate.preamble);
4106                 assertEquals(rate.nss, usabilityRate.nss);
4107                 assertEquals(rate.bw, usabilityRate.bw);
4108                 assertEquals(rate.rateMcsIdx, usabilityRate.rateMcsIdx);
4109                 assertEquals(rate.bitRateInKbps, usabilityRate.bitRateInKbps);
4110                 assertEquals(rate.txMpdu, usabilityRate.txMpdu);
4111                 assertEquals(rate.rxMpdu, usabilityRate.rxMpdu);
4112                 assertEquals(rate.mpduLost, usabilityRate.mpduLost);
4113                 assertEquals(rate.retries, usabilityRate.retries);
4114             }
4115         }
4116     }
4117 
4118     // Simulate adding a LABEL_GOOD WifiUsabilityStats
addGoodWifiUsabilityStats(WifiLinkLayerStats start)4119     private WifiLinkLayerStats addGoodWifiUsabilityStats(WifiLinkLayerStats start) {
4120         WifiInfo info = mock(WifiInfo.class);
4121         when(info.getRssi()).thenReturn(nextRandInt());
4122         when(info.getLinkSpeed()).thenReturn(nextRandInt());
4123         WifiLinkLayerStats stats = start;
4124         for (int i = 0; i < WifiMetrics.NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD; i++) {
4125             mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats);
4126             stats = nextRandomStats(stats);
4127         }
4128         return stats;
4129     }
4130 
4131     // Simulate adding a LABEL_BAD WifiUsabilityStats
addBadWifiUsabilityStats(WifiLinkLayerStats start)4132     private WifiLinkLayerStats addBadWifiUsabilityStats(WifiLinkLayerStats start) {
4133         WifiInfo info = mock(WifiInfo.class);
4134         when(info.getRssi()).thenReturn(nextRandInt());
4135         when(info.getLinkSpeed()).thenReturn(nextRandInt());
4136         WifiLinkLayerStats stats1 = start;
4137         WifiLinkLayerStats stats2 = nextRandomStats(stats1);
4138         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats1);
4139         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2);
4140         mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
4141                 WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
4142         return nextRandomStats(stats2);
4143     }
4144 
4145     /**
4146      * Verify that updateWifiUsabilityStatsEntries correctly converts the inputs into
4147      * a WifiUsabilityStatsEntry Object and then stores it.
4148      *
4149      * Verify that the converted metrics proto contains pairs of WifiUsabilityStats with
4150      * LABEL_GOOD and LABEL_BAD
4151      * @throws Exception
4152      */
4153     @Test
testUpdateWifiUsabilityStatsEntries()4154     public void testUpdateWifiUsabilityStatsEntries() throws Exception {
4155         WifiInfo info = mock(WifiInfo.class);
4156         when(info.getRssi()).thenReturn(nextRandInt());
4157         when(info.getLinkSpeed()).thenReturn(nextRandInt());
4158         when(info.getRxLinkSpeedMbps()).thenReturn(nextRandInt());
4159         when(info.getBSSID()).thenReturn("Wifi");
4160         when(info.getFrequency()).thenReturn(5745);
4161         when(mWifiDataStall.isCellularDataAvailable()).thenReturn(true);
4162         when(mWifiDataStall.isThroughputSufficient()).thenReturn(false);
4163         when(mWifiChannelUtilization.getUtilizationRatio(anyInt())).thenReturn(150);
4164         when(mWifiSettingsStore.isWifiScoringEnabled()).thenReturn(true);
4165 
4166         WifiLinkLayerStats stats1 = nextRandomStats(createNewWifiLinkLayerStats());
4167         WifiLinkLayerStats stats2 = nextRandomStats(stats1);
4168         mWifiMetrics.incrementWifiScoreCount(TEST_IFACE_NAME, 60);
4169         mWifiMetrics.incrementWifiUsabilityScoreCount(TEST_IFACE_NAME, 2, 55, 15);
4170         mWifiMetrics.logLinkProbeSuccess(
4171                 TEST_IFACE_NAME, nextRandInt(), nextRandInt(), nextRandInt(), 12);
4172         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats1);
4173         mWifiMetrics.incrementWifiScoreCount(TEST_IFACE_NAME, 58);
4174         mWifiMetrics.incrementWifiUsabilityScoreCount(TEST_IFACE_NAME, 3, 56, 15);
4175         mWifiMetrics.logLinkProbeFailure(TEST_IFACE_NAME, nextRandInt(), nextRandInt(),
4176                 nextRandInt(), nextRandInt());
4177         mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_HIGH_MVMT);
4178 
4179         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2);
4180         mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
4181                 WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
4182 
4183         // Add 2 LABEL_GOOD but only 1 should remain in the converted proto
4184         WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats2));
4185         statsGood.timeStampInMs += WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS;
4186         addGoodWifiUsabilityStats(statsGood);
4187 
4188         dumpProtoAndDeserialize();
4189         assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
4190         assertEquals(WifiUsabilityStats.LABEL_GOOD, mDecodedProto.wifiUsabilityStatsList[0].label);
4191         assertEquals(WifiUsabilityStats.LABEL_BAD, mDecodedProto.wifiUsabilityStatsList[1].label);
4192         assertUsabilityStatsAssignment(info, stats1,
4193                 mDecodedProto.wifiUsabilityStatsList[1].stats[0]);
4194         assertUsabilityStatsAssignment(info, stats2,
4195                 mDecodedProto.wifiUsabilityStatsList[1].stats[1]);
4196 
4197         assertEquals(2, mDecodedProto.wifiUsabilityStatsList[1].stats[0].seqNumToFramework);
4198         assertEquals(3, mDecodedProto.wifiUsabilityStatsList[1].stats[1].seqNumToFramework);
4199         assertEquals(0, mDecodedProto.wifiUsabilityStatsList[1].stats[0].seqNumInsideFramework);
4200         assertEquals(1, mDecodedProto.wifiUsabilityStatsList[1].stats[1].seqNumInsideFramework);
4201         assertEquals(60, mDecodedProto.wifiUsabilityStatsList[1].stats[0].wifiScore);
4202         assertEquals(58, mDecodedProto.wifiUsabilityStatsList[1].stats[1].wifiScore);
4203         assertEquals(55, mDecodedProto.wifiUsabilityStatsList[1].stats[0].wifiUsabilityScore);
4204         assertEquals(56, mDecodedProto.wifiUsabilityStatsList[1].stats[1].wifiUsabilityScore);
4205         assertEquals(15, mDecodedProto.wifiUsabilityStatsList[1].stats[0].predictionHorizonSec);
4206         assertEquals(true, mDecodedProto.wifiUsabilityStatsList[1].stats[0].isSameBssidAndFreq);
4207         assertEquals(android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS,
4208                 mDecodedProto.wifiUsabilityStatsList[1].stats[0].probeStatusSinceLastUpdate);
4209         assertEquals(android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE,
4210                 mDecodedProto.wifiUsabilityStatsList[1].stats[1].probeStatusSinceLastUpdate);
4211         assertEquals(android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE,
4212                 mDecodedProto.wifiUsabilityStatsList[0].stats[0].probeStatusSinceLastUpdate);
4213         assertEquals(12,
4214                 mDecodedProto.wifiUsabilityStatsList[1].stats[0].probeElapsedTimeSinceLastUpdateMs);
4215         assertEquals(Integer.MAX_VALUE, mDecodedProto.wifiUsabilityStatsList[1]
4216                 .stats[1].probeElapsedTimeSinceLastUpdateMs);
4217         assertEquals(-1, mDecodedProto.wifiUsabilityStatsList[0]
4218                 .stats[0].probeElapsedTimeSinceLastUpdateMs);
4219         assertEquals(DEVICE_MOBILITY_STATE_HIGH_MVMT, mDecodedProto.wifiUsabilityStatsList[1]
4220                 .stats[mDecodedProto.wifiUsabilityStatsList[1].stats.length - 1]
4221                 .deviceMobilityState);
4222         assertEquals(true, mDecodedProto.wifiUsabilityStatsList[0].stats[0].isWifiScoringEnabled);
4223         assertEquals(true,
4224                 mDecodedProto.wifiUsabilityStatsList[1].stats[0].isCellularDataAvailable);
4225         assertEquals(false,
4226                 mDecodedProto.wifiUsabilityStatsList[1].stats[1].isThroughputSufficient);
4227         assertEquals(150,
4228                 mDecodedProto.wifiUsabilityStatsList[0].stats[0].channelUtilizationRatio);
4229     }
4230 
createNewWifiLinkLayerStats()4231     private WifiLinkLayerStats createNewWifiLinkLayerStats() {
4232         WifiLinkLayerStats stats = new WifiLinkLayerStats();
4233         RateStat[] rateStats = new RateStat[1];
4234         rateStats[0] = new RateStat();
4235         rateStats[0].preamble = 1;
4236         rateStats[0].nss = 1;
4237         rateStats[0].bw = 2;
4238         rateStats[0].rateMcsIdx = 5;
4239         rateStats[0].bitRateInKbps = 2000;
4240         PeerInfo[] peerInfo = new PeerInfo[1];
4241         peerInfo[0] = new PeerInfo();
4242         peerInfo[0].rateStats = rateStats;
4243         stats.peerInfo = peerInfo;
4244         RadioStat[] radioStats = new RadioStat[2];
4245         for (int i = 0; i < 2; i++) {
4246             RadioStat radio = new RadioStat();
4247             radio.radio_id = i;
4248             radioStats[i] = radio;
4249         }
4250         stats.radioStats = radioStats;
4251         return stats;
4252     }
4253 
4254     /**
4255      * Verify that when there are no WifiUsability events the generated proto also contains no
4256      * such information.
4257      * @throws Exception
4258      */
4259     @Test
testWifiUsabilityStatsZeroEvents()4260     public void testWifiUsabilityStatsZeroEvents() throws Exception {
4261         dumpProtoAndDeserialize();
4262         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
4263     }
4264 
4265     /**
4266      * Verify that we discard a WifiUsabilityStats with LABEL_GOOD if there is no corresponding
4267      * LABEL_BAD
4268      * @throws Exception
4269      */
4270     @Test
testWifiUsabilityStatsIgnoreSingleLabelGood()4271     public void testWifiUsabilityStatsIgnoreSingleLabelGood() throws Exception {
4272         addGoodWifiUsabilityStats(new WifiLinkLayerStats());
4273         dumpProtoAndDeserialize();
4274         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
4275     }
4276 
4277     /**
4278      * Verify that we discard a WifiUsabilityStats with LABEL_BAD if there is no corresponding
4279      * LABEL_GOOD
4280      * @throws Exception
4281      */
4282     @Test
testWifiUsabilityStatsIgnoreSingleLabelBad()4283     public void testWifiUsabilityStatsIgnoreSingleLabelBad() throws Exception {
4284         addBadWifiUsabilityStats(new WifiLinkLayerStats());
4285         dumpProtoAndDeserialize();
4286         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
4287     }
4288 
4289     /**
4290      * Verify that the buffer for WifiUsabilityStats does not exceed the max length.
4291      * Do this by trying to add more WifiUsabilityStats than the max length and then
4292      * verifying that the decoded proto's length does not exceed the max length.
4293      *
4294      * Also verify that the length for the list of WifiUsabilityStatsEntry is capped.
4295      * @throws Exception
4296      */
4297     @Test
testWifiUsabilityStatsBufferSizeIsCapped()4298     public void testWifiUsabilityStatsBufferSizeIsCapped() throws Exception {
4299         // simulate adding LABEL_GOOD WifiUsabilityStats 1 time over the max limit
4300         WifiLinkLayerStats stats = new WifiLinkLayerStats();
4301         for (int j = 0; j < WifiMetrics.MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE + 1; j++) {
4302             stats = addGoodWifiUsabilityStats(stats);
4303             stats = addBadWifiUsabilityStats(stats);
4304             stats.timeStampInMs += WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS;
4305         }
4306         dumpProtoAndDeserialize();
4307         assertEquals(2 * WifiMetrics.MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD,
4308                 mDecodedProto.wifiUsabilityStatsList.length);
4309         for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD; i++) {
4310             assertEquals(WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE,
4311                     mDecodedProto.wifiUsabilityStatsList[2 * i].stats.length);
4312             assertEquals(2, mDecodedProto.wifiUsabilityStatsList[2 * i + 1].stats.length);
4313         }
4314     }
4315 
4316     /**
4317      * Verify that LABEL_GOOD stats are not generated more frequently than
4318      * |MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS|
4319      * @throws Exception
4320      */
4321     @Test
testWifiUsabilityStatsLabelGoodHasMinimumPeriod()4322     public void testWifiUsabilityStatsLabelGoodHasMinimumPeriod() throws Exception {
4323         // simulate adding LABEL_GOOD WifiUsabilityStats 1 time over the max limit
4324         WifiLinkLayerStats stats = new WifiLinkLayerStats();
4325         for (int j = 0; j < 2; j++) {
4326             stats = addGoodWifiUsabilityStats(stats);
4327             stats = addBadWifiUsabilityStats(stats);
4328         }
4329         dumpProtoAndDeserialize();
4330         assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
4331     }
4332 
4333     /**
4334      * Verify that LABEL_BAD stats are not generated more frequently than |MIN_DATA_STALL_WAIT_MS|
4335      * @throws Exception
4336      */
4337     @Test
testWifiUsabilityStatsLabelBadNotGeneratedGapLessThanMinimum()4338     public void testWifiUsabilityStatsLabelBadNotGeneratedGapLessThanMinimum() throws Exception {
4339         // simulate adding two LABEL_GOOD WifiUsabilityStats
4340         WifiInfo info = mock(WifiInfo.class);
4341         when(info.getRssi()).thenReturn(nextRandInt());
4342         when(info.getLinkSpeed()).thenReturn(nextRandInt());
4343         WifiLinkLayerStats stats1 = new WifiLinkLayerStats();
4344         WifiLinkLayerStats stats2 = new WifiLinkLayerStats();
4345         stats1 = addGoodWifiUsabilityStats(stats1);
4346         stats2.timeStampInMs = stats1.timeStampInMs
4347                 + WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS;
4348         addGoodWifiUsabilityStats(stats2);
4349 
4350         WifiLinkLayerStats stats3 = new WifiLinkLayerStats();
4351         WifiLinkLayerStats stats4 = new WifiLinkLayerStats();
4352         for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
4353             mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats3);
4354             stats3 = nextRandomStats(stats3);
4355         }
4356         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats3);
4357         mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
4358                 WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
4359         for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
4360             mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats4);
4361             stats4 = nextRandomStats(stats4);
4362         }
4363         stats4.timeStampInMs = stats3.timeStampInMs - 1 + WifiMetrics.MIN_DATA_STALL_WAIT_MS;
4364         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats4);
4365         mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
4366                 WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
4367         dumpProtoAndDeserialize();
4368         assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
4369     }
4370 
4371     /**
4372      * Verify that LABEL_BAD stats are generated if timestamp gap is larger than
4373      * |MIN_DATA_STALL_WAIT_MS|
4374      * @throws Exception
4375      */
4376     @Test
testWifiUsabilityStatsLabelBadGeneratedGapLargerThanMinimum()4377     public void testWifiUsabilityStatsLabelBadGeneratedGapLargerThanMinimum() throws Exception {
4378         // simulate adding two LABEL_GOOD WifiUsabilityStats
4379         WifiInfo info = mock(WifiInfo.class);
4380         when(info.getRssi()).thenReturn(nextRandInt());
4381         when(info.getLinkSpeed()).thenReturn(nextRandInt());
4382         WifiLinkLayerStats stats1 = new WifiLinkLayerStats();
4383         WifiLinkLayerStats stats2 = new WifiLinkLayerStats();
4384         stats1 = addGoodWifiUsabilityStats(stats1);
4385         stats2.timeStampInMs = stats1.timeStampInMs
4386                 + WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS;
4387         addGoodWifiUsabilityStats(stats2);
4388 
4389         WifiLinkLayerStats stats3 = new WifiLinkLayerStats();
4390         WifiLinkLayerStats stats4 = new WifiLinkLayerStats();
4391         for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
4392             mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats3);
4393             stats3 = nextRandomStats(stats3);
4394         }
4395         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats3);
4396         mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
4397                 WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
4398         for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
4399             mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats4);
4400             stats4 = nextRandomStats(stats4);
4401         }
4402         stats4.timeStampInMs = stats3.timeStampInMs + 1 + WifiMetrics.MIN_DATA_STALL_WAIT_MS;
4403         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats4);
4404         mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
4405                 WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
4406         dumpProtoAndDeserialize();
4407         assertEquals(4, mDecodedProto.wifiUsabilityStatsList.length);
4408     }
4409 
4410     /**
4411      * Tests device mobility state metrics as states are changed.
4412      */
4413     @Test
testDeviceMobilityStateMetrics_changeState()4414     public void testDeviceMobilityStateMetrics_changeState() throws Exception {
4415         // timeMs is initialized to 0 by the setUp() method
4416         long timeMs = 1000;
4417         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
4418         mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY);
4419 
4420         timeMs += 2000;
4421         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
4422         mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_LOW_MVMT);
4423 
4424         dumpProtoAndDeserialize();
4425 
4426         DeviceMobilityStatePnoScanStats[] expected = {
4427                 buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN, 1, 1000, 0),
4428                 buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_STATIONARY, 1, 2000, 0),
4429                 buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_LOW_MVMT, 1, 0, 0)
4430         };
4431 
4432         assertDeviceMobilityStatePnoScanStatsEqual(
4433                 expected, mDecodedProto.mobilityStatePnoStatsList);
4434     }
4435 
4436     /**
4437      * Tests device mobility state metrics as PNO scans are started and stopped.
4438      */
4439     @Test
testDeviceMobilityStateMetrics_startStopPnoScans()4440     public void testDeviceMobilityStateMetrics_startStopPnoScans() throws Exception {
4441         long timeMs = 1000;
4442         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
4443         mWifiMetrics.logPnoScanStart();
4444 
4445         timeMs += 2000;
4446         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
4447         mWifiMetrics.logPnoScanStop();
4448         mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY);
4449         mWifiMetrics.logPnoScanStart();
4450 
4451         timeMs += 4000;
4452         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
4453         mWifiMetrics.logPnoScanStop();
4454 
4455         timeMs += 8000;
4456         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
4457         mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_HIGH_MVMT);
4458 
4459         dumpProtoAndDeserialize();
4460 
4461         DeviceMobilityStatePnoScanStats[] expected = {
4462                 buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN,
4463                         1, 1000 + 2000, 2000),
4464                 buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_STATIONARY,
4465                         1, 4000 + 8000, 4000),
4466                 buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_HIGH_MVMT, 1, 0, 0)
4467         };
4468 
4469         assertDeviceMobilityStatePnoScanStatsEqual(
4470                 expected, mDecodedProto.mobilityStatePnoStatsList);
4471     }
4472 
4473     /**
4474      * Tests that the initial state is set up correctly.
4475      */
4476     @Test
testDeviceMobilityStateMetrics_initialState()4477     public void testDeviceMobilityStateMetrics_initialState() throws Exception {
4478         dumpProtoAndDeserialize();
4479 
4480         DeviceMobilityStatePnoScanStats[] expected = {
4481                 buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN, 1, 0, 0)
4482         };
4483 
4484         assertDeviceMobilityStatePnoScanStatsEqual(
4485                 expected, mDecodedProto.mobilityStatePnoStatsList);
4486     }
4487 
4488     /**
4489      * Tests that logPnoScanStart() updates the total duration in addition to the PNO duration.
4490      */
4491     @Test
testDeviceMobilityStateMetrics_startPnoScansUpdatesTotalDuration()4492     public void testDeviceMobilityStateMetrics_startPnoScansUpdatesTotalDuration()
4493             throws Exception {
4494         long timeMs = 1000;
4495         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
4496         mWifiMetrics.logPnoScanStart();
4497 
4498         dumpProtoAndDeserialize();
4499 
4500         DeviceMobilityStatePnoScanStats[] expected = {
4501                 buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN, 1, 1000, 0)
4502         };
4503 
4504         assertDeviceMobilityStatePnoScanStatsEqual(
4505                 expected, mDecodedProto.mobilityStatePnoStatsList);
4506     }
4507 
4508     /**
4509      * Tests that logPnoScanStop() updates the total duration in addition to the PNO duration.
4510      */
4511     @Test
testDeviceMobilityStateMetrics_stopPnoScansUpdatesTotalDuration()4512     public void testDeviceMobilityStateMetrics_stopPnoScansUpdatesTotalDuration()
4513             throws Exception {
4514         long timeMs = 1000;
4515         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
4516         mWifiMetrics.logPnoScanStart();
4517 
4518         timeMs += 2000;
4519         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
4520         mWifiMetrics.logPnoScanStop();
4521 
4522         dumpProtoAndDeserialize();
4523 
4524         DeviceMobilityStatePnoScanStats[] expected = {
4525                 buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN,
4526                         1, 1000 + 2000, 2000)
4527         };
4528 
4529         assertDeviceMobilityStatePnoScanStatsEqual(
4530                 expected, mDecodedProto.mobilityStatePnoStatsList);
4531     }
4532 
4533     /**
4534      * Verify that clients should be notified of activity in case Wifi stats get updated.
4535      */
4536     @Test
testClientNotification()4537     public void testClientNotification() throws RemoteException {
4538         // Register Client for verification.
4539         ArgumentCaptor<android.net.wifi.WifiUsabilityStatsEntry> usabilityStats =
4540                 ArgumentCaptor.forClass(android.net.wifi.WifiUsabilityStatsEntry.class);
4541         mWifiMetrics.addOnWifiUsabilityListener(mOnWifiUsabilityStatsListener);
4542         WifiInfo info = mock(WifiInfo.class);
4543         when(info.getRssi()).thenReturn(nextRandInt());
4544         when(info.getLinkSpeed()).thenReturn(nextRandInt());
4545 
4546         WifiLinkLayerStats linkLayerStats = nextRandomStats(new WifiLinkLayerStats());
4547         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, linkLayerStats);
4548 
4549         // Client should get the stats.
4550         verify(mOnWifiUsabilityStatsListener).onWifiUsabilityStats(anyInt(), anyBoolean(),
4551                 usabilityStats.capture());
4552         assertEquals(usabilityStats.getValue().getTotalRadioOnTimeMillis(), linkLayerStats.on_time);
4553         assertEquals(usabilityStats.getValue().getTotalTxBad(), linkLayerStats.lostmpdu_be
4554                 + linkLayerStats.lostmpdu_bk + linkLayerStats.lostmpdu_vi
4555                 + linkLayerStats.lostmpdu_vo);
4556         assertEquals(usabilityStats.getValue().getTimeStampMillis(), linkLayerStats.timeStampInMs);
4557         assertEquals(usabilityStats.getValue().getTotalRoamScanTimeMillis(),
4558                 linkLayerStats.on_time_roam_scan);
4559     }
4560 
4561     /**
4562      * Verify that remove client should be handled
4563      */
4564     @Test
testRemoveClient()4565     public void testRemoveClient() throws RemoteException {
4566         // Register Client for verification.
4567         mWifiMetrics.addOnWifiUsabilityListener(mOnWifiUsabilityStatsListener);
4568         mWifiMetrics.removeOnWifiUsabilityListener(mOnWifiUsabilityStatsListener);
4569         verify(mAppBinder).unlinkToDeath(any(), anyInt());
4570 
4571         WifiInfo info = mock(WifiInfo.class);
4572         when(info.getRssi()).thenReturn(nextRandInt());
4573         when(info.getLinkSpeed()).thenReturn(nextRandInt());
4574         WifiLinkLayerStats linkLayerStats = nextRandomStats(new WifiLinkLayerStats());
4575         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, linkLayerStats);
4576 
4577         verify(mOnWifiUsabilityStatsListener, never()).onWifiUsabilityStats(anyInt(),
4578                 anyBoolean(), any());
4579     }
4580 
4581     /**
4582      * Verify that WifiMetrics adds for death notification on adding client.
4583      */
4584     @Test
testAddsForBinderDeathOnAddClient()4585     public void testAddsForBinderDeathOnAddClient() throws Exception {
4586         mWifiMetrics.addOnWifiUsabilityListener(mOnWifiUsabilityStatsListener);
4587         verify(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt());
4588     }
4589 
4590     /**
4591      * Verify that client fails to get message when listener add failed.
4592      */
4593     @Test
testAddsListenerFailureOnLinkToDeath()4594     public void testAddsListenerFailureOnLinkToDeath() throws Exception {
4595         doThrow(new RemoteException())
4596                 .when(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt());
4597         mWifiMetrics.addOnWifiUsabilityListener(mOnWifiUsabilityStatsListener);
4598         verify(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt());
4599 
4600         WifiInfo info = mock(WifiInfo.class);
4601         when(info.getRssi()).thenReturn(nextRandInt());
4602         when(info.getLinkSpeed()).thenReturn(nextRandInt());
4603         WifiLinkLayerStats linkLayerStats = nextRandomStats(new WifiLinkLayerStats());
4604         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, linkLayerStats);
4605 
4606         // Client should not get any message listener add failed.
4607         verify(mOnWifiUsabilityStatsListener, never()).onWifiUsabilityStats(anyInt(),
4608                 anyBoolean(), any());
4609     }
4610 
4611     /**
4612      * Verify that the label and the triggerType of Wifi usability stats are saved correctly
4613      * during firmware alert is triggered.
4614      * @throws Exception
4615      */
4616     @Test
verifyFirmwareAlertUpdatesWifiUsabilityMetrics()4617     public void verifyFirmwareAlertUpdatesWifiUsabilityMetrics() throws Exception {
4618         WifiInfo info = mock(WifiInfo.class);
4619         when(info.getRssi()).thenReturn(nextRandInt());
4620         when(info.getLinkSpeed()).thenReturn(nextRandInt());
4621         long eventTimeMs = nextRandInt();
4622         when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTimeMs);
4623         WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats());
4624         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats1);
4625 
4626         // Add 1 LABEL_GOOD
4627         WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1));
4628         // Firmware alert occurs
4629         mWifiMetrics.logFirmwareAlert(TEST_IFACE_NAME, 2);
4630 
4631         dumpProtoAndDeserialize();
4632         assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
4633 
4634         WifiUsabilityStats[] statsList = mDecodedProto.wifiUsabilityStatsList;
4635         assertEquals(WifiUsabilityStats.LABEL_GOOD, statsList[0].label);
4636         assertEquals(WifiUsabilityStats.LABEL_BAD, statsList[1].label);
4637         assertEquals(WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT, statsList[1].triggerType);
4638         assertEquals(eventTimeMs, statsList[1].timeStampMs);
4639         assertEquals(2, statsList[1].firmwareAlertCode);
4640     }
4641 
4642     /**
4643      * Verify that the label and the triggerType of Wifi usability stats are saved correctly
4644      * during Wifi data stall is triggered.
4645      * @throws Exception
4646      */
4647     @Test
verifyWifiDataStallUpdatesWifiUsabilityMetrics()4648     public void verifyWifiDataStallUpdatesWifiUsabilityMetrics() throws Exception {
4649         WifiInfo info = mock(WifiInfo.class);
4650         when(info.getRssi()).thenReturn(nextRandInt());
4651         when(info.getLinkSpeed()).thenReturn(nextRandInt());
4652         long eventTimeMs = nextRandInt();
4653         when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTimeMs);
4654         WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats());
4655         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats1);
4656 
4657         // Add 1 LABEL_GOOD
4658         WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1));
4659         // Wifi data stall occurs
4660         mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
4661                 WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, -1);
4662 
4663         dumpProtoAndDeserialize();
4664         assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
4665         WifiUsabilityStats[] statsList = mDecodedProto.wifiUsabilityStatsList;
4666         assertEquals(WifiUsabilityStats.LABEL_BAD, statsList[1].label);
4667         assertEquals(WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, statsList[1].triggerType);
4668         assertEquals(-1, statsList[1].firmwareAlertCode);
4669         assertEquals(eventTimeMs, statsList[1].timeStampMs);
4670     }
4671 
4672     /**
4673      * Test the generation of 'WifiConfigStoreIODuration' read histograms.
4674      */
4675     @Test
testWifiConfigStoreReadDurationsHistogramGeneration()4676     public void testWifiConfigStoreReadDurationsHistogramGeneration() throws Exception {
4677         mWifiMetrics.noteWifiConfigStoreReadDuration(10);
4678         mWifiMetrics.noteWifiConfigStoreReadDuration(20);
4679         mWifiMetrics.noteWifiConfigStoreReadDuration(100);
4680         mWifiMetrics.noteWifiConfigStoreReadDuration(90);
4681         mWifiMetrics.noteWifiConfigStoreReadDuration(130);
4682         mWifiMetrics.noteWifiConfigStoreReadDuration(250);
4683         mWifiMetrics.noteWifiConfigStoreReadDuration(600);
4684 
4685         dumpProtoAndDeserialize();
4686 
4687         assertEquals(5, mDecodedProto.wifiConfigStoreIo.readDurations.length);
4688         assertEquals(0, mDecodedProto.wifiConfigStoreIo.writeDurations.length);
4689 
4690         assertEquals(Integer.MIN_VALUE,
4691                 mDecodedProto.wifiConfigStoreIo.readDurations[0].rangeStartMs);
4692         assertEquals(50, mDecodedProto.wifiConfigStoreIo.readDurations[0].rangeEndMs);
4693         assertEquals(2, mDecodedProto.wifiConfigStoreIo.readDurations[0].count);
4694 
4695         assertEquals(50, mDecodedProto.wifiConfigStoreIo.readDurations[1].rangeStartMs);
4696         assertEquals(100, mDecodedProto.wifiConfigStoreIo.readDurations[1].rangeEndMs);
4697         assertEquals(1, mDecodedProto.wifiConfigStoreIo.readDurations[1].count);
4698 
4699         assertEquals(100, mDecodedProto.wifiConfigStoreIo.readDurations[2].rangeStartMs);
4700         assertEquals(150, mDecodedProto.wifiConfigStoreIo.readDurations[2].rangeEndMs);
4701         assertEquals(2, mDecodedProto.wifiConfigStoreIo.readDurations[2].count);
4702 
4703         assertEquals(200, mDecodedProto.wifiConfigStoreIo.readDurations[3].rangeStartMs);
4704         assertEquals(300, mDecodedProto.wifiConfigStoreIo.readDurations[3].rangeEndMs);
4705         assertEquals(1, mDecodedProto.wifiConfigStoreIo.readDurations[3].count);
4706 
4707         assertEquals(300, mDecodedProto.wifiConfigStoreIo.readDurations[4].rangeStartMs);
4708         assertEquals(Integer.MAX_VALUE,
4709                 mDecodedProto.wifiConfigStoreIo.readDurations[4].rangeEndMs);
4710         assertEquals(1, mDecodedProto.wifiConfigStoreIo.readDurations[4].count);
4711     }
4712 
4713     /**
4714      * Test the generation of 'WifiConfigStoreIODuration' write histograms.
4715      */
4716     @Test
testWifiConfigStoreWriteDurationsHistogramGeneration()4717     public void testWifiConfigStoreWriteDurationsHistogramGeneration() throws Exception {
4718         mWifiMetrics.noteWifiConfigStoreWriteDuration(10);
4719         mWifiMetrics.noteWifiConfigStoreWriteDuration(40);
4720         mWifiMetrics.noteWifiConfigStoreWriteDuration(60);
4721         mWifiMetrics.noteWifiConfigStoreWriteDuration(90);
4722         mWifiMetrics.noteWifiConfigStoreWriteDuration(534);
4723         mWifiMetrics.noteWifiConfigStoreWriteDuration(345);
4724 
4725         dumpProtoAndDeserialize();
4726 
4727         assertEquals(0, mDecodedProto.wifiConfigStoreIo.readDurations.length);
4728         assertEquals(3, mDecodedProto.wifiConfigStoreIo.writeDurations.length);
4729 
4730         assertEquals(Integer.MIN_VALUE,
4731                 mDecodedProto.wifiConfigStoreIo.writeDurations[0].rangeStartMs);
4732         assertEquals(50, mDecodedProto.wifiConfigStoreIo.writeDurations[0].rangeEndMs);
4733         assertEquals(2, mDecodedProto.wifiConfigStoreIo.writeDurations[0].count);
4734 
4735         assertEquals(50, mDecodedProto.wifiConfigStoreIo.writeDurations[1].rangeStartMs);
4736         assertEquals(100, mDecodedProto.wifiConfigStoreIo.writeDurations[1].rangeEndMs);
4737         assertEquals(2, mDecodedProto.wifiConfigStoreIo.writeDurations[1].count);
4738 
4739         assertEquals(300, mDecodedProto.wifiConfigStoreIo.writeDurations[2].rangeStartMs);
4740         assertEquals(Integer.MAX_VALUE,
4741                 mDecodedProto.wifiConfigStoreIo.writeDurations[2].rangeEndMs);
4742         assertEquals(2, mDecodedProto.wifiConfigStoreIo.writeDurations[2].count);
4743     }
4744 
4745     /**
4746      * Test link probe metrics.
4747      */
4748     @Test
testLogLinkProbeMetrics()4749     public void testLogLinkProbeMetrics() throws Exception {
4750         mWifiMetrics.logLinkProbeSuccess(TEST_IFACE_NAME, 10000, -75, 50, 5);
4751         mWifiMetrics.logLinkProbeFailure(TEST_IFACE_NAME, 30000, -80, 10,
4752                 WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_NO_ACK);
4753         mWifiMetrics.logLinkProbeSuccess(TEST_IFACE_NAME, 3000, -71, 160, 12);
4754         mWifiMetrics.logLinkProbeFailure(TEST_IFACE_NAME, 40000, -80, 6,
4755                 WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_NO_ACK);
4756         mWifiMetrics.logLinkProbeSuccess(TEST_IFACE_NAME, 5000, -73, 160, 10);
4757         mWifiMetrics.logLinkProbeFailure(TEST_IFACE_NAME, 2000, -78, 6,
4758                 WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_TIMEOUT);
4759 
4760         dumpProtoAndDeserialize();
4761 
4762         StaEvent[] expected = {
4763                 buildLinkProbeSuccessStaEvent(5),
4764                 buildLinkProbeFailureStaEvent(LinkProbeStats.LINK_PROBE_FAILURE_REASON_NO_ACK),
4765                 buildLinkProbeSuccessStaEvent(12),
4766                 buildLinkProbeFailureStaEvent(LinkProbeStats.LINK_PROBE_FAILURE_REASON_NO_ACK),
4767                 buildLinkProbeSuccessStaEvent(10),
4768                 buildLinkProbeFailureStaEvent(LinkProbeStats.LINK_PROBE_FAILURE_REASON_TIMEOUT)
4769         };
4770         assertLinkProbeStaEventsEqual(expected, mDecodedProto.staEventList);
4771 
4772         LinkProbeStats linkProbeStats = mDecodedProto.linkProbeStats;
4773 
4774         Int32Count[] expectedSuccessRssiHistogram = {
4775                 buildInt32Count(-75, 1),
4776                 buildInt32Count(-73, 1),
4777                 buildInt32Count(-71, 1),
4778         };
4779         assertKeyCountsEqual(expectedSuccessRssiHistogram,
4780                 linkProbeStats.successRssiCounts);
4781 
4782         Int32Count[] expectedFailureRssiHistogram = {
4783                 buildInt32Count(-80, 2),
4784                 buildInt32Count(-78, 1),
4785         };
4786         assertKeyCountsEqual(expectedFailureRssiHistogram,
4787                 linkProbeStats.failureRssiCounts);
4788 
4789         Int32Count[] expectedSuccessLinkSpeedHistogram = {
4790                 buildInt32Count(50, 1),
4791                 buildInt32Count(160, 2)
4792         };
4793         assertKeyCountsEqual(expectedSuccessLinkSpeedHistogram,
4794                 linkProbeStats.successLinkSpeedCounts);
4795 
4796         Int32Count[] expectedFailureLinkSpeedHistogram = {
4797                 buildInt32Count(6, 2),
4798                 buildInt32Count(10, 1)
4799         };
4800         assertKeyCountsEqual(expectedFailureLinkSpeedHistogram,
4801                 linkProbeStats.failureLinkSpeedCounts);
4802 
4803         HistogramBucketInt32[] expectedSuccessTimeSinceLastTxSuccessSecondsHistogram = {
4804                 buildHistogramBucketInt32(Integer.MIN_VALUE, 5, 1),
4805                 buildHistogramBucketInt32(5, 15, 2)
4806         };
4807         assertHistogramBucketsEqual(expectedSuccessTimeSinceLastTxSuccessSecondsHistogram,
4808                 linkProbeStats.successSecondsSinceLastTxSuccessHistogram);
4809 
4810         HistogramBucketInt32[] expectedFailureTimeSinceLastTxSuccessSecondsHistogram = {
4811                 buildHistogramBucketInt32(Integer.MIN_VALUE, 5, 1),
4812                 buildHistogramBucketInt32(15, 45, 2)
4813         };
4814         assertHistogramBucketsEqual(expectedFailureTimeSinceLastTxSuccessSecondsHistogram,
4815                 linkProbeStats.failureSecondsSinceLastTxSuccessHistogram);
4816 
4817         HistogramBucketInt32[] expectedSuccessElapsedTimeMsHistogram = {
4818                 buildHistogramBucketInt32(5, 10, 1),
4819                 buildHistogramBucketInt32(10, 15, 2),
4820         };
4821         assertHistogramBucketsEqual(expectedSuccessElapsedTimeMsHistogram,
4822                 linkProbeStats.successElapsedTimeMsHistogram);
4823 
4824         LinkProbeFailureReasonCount[] expectedFailureReasonCount = {
4825                 buildLinkProbeFailureReasonCount(
4826                         LinkProbeStats.LINK_PROBE_FAILURE_REASON_NO_ACK, 2),
4827                 buildLinkProbeFailureReasonCount(
4828                         LinkProbeStats.LINK_PROBE_FAILURE_REASON_TIMEOUT, 1),
4829         };
4830         assertLinkProbeFailureReasonCountsEqual(expectedFailureReasonCount,
4831                 linkProbeStats.failureReasonCounts);
4832     }
4833 
4834     /**
4835      * Tests counting the number of link probes triggered per day for each experiment.
4836      */
4837     @Test
testIncrementLinkProbeExperimentProbeCount()4838     public void testIncrementLinkProbeExperimentProbeCount() throws Exception {
4839         String experimentId1 = "screenOnDelay=6000,noTxDelay=3000,delayBetweenProbes=9000,"
4840                 + "rssiThreshold=-70,linkSpeedThreshold=15,";
4841         mWifiMetrics.incrementLinkProbeExperimentProbeCount(experimentId1);
4842 
4843         String experimentId2 = "screenOnDelay=9000,noTxDelay=12000,delayBetweenProbes=15000,"
4844                 + "rssiThreshold=-72,linkSpeedThreshold=20,";
4845         mWifiMetrics.incrementLinkProbeExperimentProbeCount(experimentId2);
4846         mWifiMetrics.incrementLinkProbeExperimentProbeCount(experimentId2);
4847 
4848         dumpProtoAndDeserialize();
4849 
4850         ExperimentProbeCounts[] actual = mDecodedProto.linkProbeStats.experimentProbeCounts;
4851 
4852         ExperimentProbeCounts[] expected = {
4853                 buildExperimentProbeCounts(experimentId1, 1),
4854                 buildExperimentProbeCounts(experimentId2, 2)
4855         };
4856 
4857         assertExperimentProbeCountsEqual(expected, actual);
4858     }
4859 
4860     /**
4861      * Tests logNetworkSelectionDecision()
4862      */
4863     @Test
testLogNetworkSelectionDecision()4864     public void testLogNetworkSelectionDecision() throws Exception {
4865         mWifiMetrics.logNetworkSelectionDecision(1, 2, true, 6);
4866         mWifiMetrics.logNetworkSelectionDecision(1, 2, false, 1);
4867         mWifiMetrics.logNetworkSelectionDecision(1, 2, true, 6);
4868         mWifiMetrics.logNetworkSelectionDecision(1, 2, true, 2);
4869         mWifiMetrics.logNetworkSelectionDecision(3, 2, false, 15);
4870         mWifiMetrics.logNetworkSelectionDecision(1, 2, false, 6);
4871         mWifiMetrics.logNetworkSelectionDecision(1, 4, true, 2);
4872 
4873         dumpProtoAndDeserialize();
4874 
4875         assertEquals(3, mDecodedProto.networkSelectionExperimentDecisionsList.length);
4876 
4877         NetworkSelectionExperimentDecisions exp12 =
4878                 findUniqueNetworkSelectionExperimentDecisions(1, 2);
4879         Int32Count[] exp12SameExpected = {
4880                 buildInt32Count(2, 1),
4881                 buildInt32Count(6, 2)
4882         };
4883         assertKeyCountsEqual(exp12SameExpected, exp12.sameSelectionNumChoicesCounter);
4884         Int32Count[] exp12DiffExpected = {
4885                 buildInt32Count(1, 1),
4886                 buildInt32Count(6, 1)
4887         };
4888         assertKeyCountsEqual(exp12DiffExpected, exp12.differentSelectionNumChoicesCounter);
4889 
4890         NetworkSelectionExperimentDecisions exp32 =
4891                 findUniqueNetworkSelectionExperimentDecisions(3, 2);
4892         Int32Count[] exp32SameExpected = {};
4893         assertKeyCountsEqual(exp32SameExpected, exp32.sameSelectionNumChoicesCounter);
4894         Int32Count[] exp32DiffExpected = {
4895                 buildInt32Count(
4896                         WifiMetrics.NetworkSelectionExperimentResults.MAX_CHOICES, 1)
4897         };
4898         assertKeyCountsEqual(exp32DiffExpected, exp32.differentSelectionNumChoicesCounter);
4899 
4900         NetworkSelectionExperimentDecisions exp14 =
4901                 findUniqueNetworkSelectionExperimentDecisions(1, 4);
4902         Int32Count[] exp14SameExpected = {
4903                 buildInt32Count(2, 1)
4904         };
4905         assertKeyCountsEqual(exp14SameExpected, exp14.sameSelectionNumChoicesCounter);
4906         Int32Count[] exp14DiffExpected = {};
4907         assertKeyCountsEqual(exp14DiffExpected, exp14.differentSelectionNumChoicesCounter);
4908     }
4909 
4910     /**
4911      * Test the generation of 'WifiNetworkRequestApiLog' message.
4912      */
4913     @Test
testWifiNetworkRequestApiLog()4914     public void testWifiNetworkRequestApiLog() throws Exception {
4915         mWifiMetrics.incrementNetworkRequestApiNumRequest();
4916         mWifiMetrics.incrementNetworkRequestApiNumRequest();
4917         mWifiMetrics.incrementNetworkRequestApiNumRequest();
4918 
4919         mWifiMetrics.incrementNetworkRequestApiMatchSizeHistogram(7);
4920         mWifiMetrics.incrementNetworkRequestApiMatchSizeHistogram(0);
4921         mWifiMetrics.incrementNetworkRequestApiMatchSizeHistogram(1);
4922 
4923         mWifiMetrics.incrementNetworkRequestApiNumConnectSuccessOnPrimaryIface();
4924         mWifiMetrics.incrementNetworkRequestApiNumConnectSuccessOnPrimaryIface();
4925 
4926         mWifiMetrics.incrementNetworkRequestApiNumConnectSuccessOnSecondaryIface();
4927 
4928         mWifiMetrics.incrementNetworkRequestApiNumConnectOnPrimaryIface();
4929         mWifiMetrics.incrementNetworkRequestApiNumConnectOnPrimaryIface();
4930 
4931         mWifiMetrics.incrementNetworkRequestApiNumConnectOnSecondaryIface();
4932         mWifiMetrics.incrementNetworkRequestApiNumConnectOnSecondaryIface();
4933         mWifiMetrics.incrementNetworkRequestApiNumConnectOnSecondaryIface();
4934 
4935         mWifiMetrics.incrementNetworkRequestApiNumUserApprovalBypass();
4936         mWifiMetrics.incrementNetworkRequestApiNumUserApprovalBypass();
4937 
4938         mWifiMetrics.incrementNetworkRequestApiNumUserReject();
4939 
4940         mWifiMetrics.incrementNetworkRequestApiNumApps();
4941 
4942         mWifiMetrics.incrementNetworkRequestApiConnectionDurationSecOnPrimaryIfaceHistogram(40);
4943         mWifiMetrics.incrementNetworkRequestApiConnectionDurationSecOnPrimaryIfaceHistogram(670);
4944         mWifiMetrics.incrementNetworkRequestApiConnectionDurationSecOnPrimaryIfaceHistogram(1801);
4945 
4946         mWifiMetrics.incrementNetworkRequestApiConnectionDurationSecOnSecondaryIfaceHistogram(100);
4947         mWifiMetrics.incrementNetworkRequestApiConnectionDurationSecOnSecondaryIfaceHistogram(350);
4948         mWifiMetrics.incrementNetworkRequestApiConnectionDurationSecOnSecondaryIfaceHistogram(750);
4949 
4950         mWifiMetrics.incrementNetworkRequestApiConcurrentConnectionDurationSecHistogram(10);
4951         mWifiMetrics.incrementNetworkRequestApiConcurrentConnectionDurationSecHistogram(589);
4952         mWifiMetrics.incrementNetworkRequestApiConcurrentConnectionDurationSecHistogram(2900);
4953         mWifiMetrics.incrementNetworkRequestApiConcurrentConnectionDurationSecHistogram(145);
4954 
4955         dumpProtoAndDeserialize();
4956 
4957         assertEquals(3, mDecodedProto.wifiNetworkRequestApiLog.numRequest);
4958         assertEquals(2, mDecodedProto.wifiNetworkRequestApiLog.numConnectSuccessOnPrimaryIface);
4959         assertEquals(1, mDecodedProto.wifiNetworkRequestApiLog.numConnectSuccessOnSecondaryIface);
4960         assertEquals(2, mDecodedProto.wifiNetworkRequestApiLog.numConnectOnPrimaryIface);
4961         assertEquals(3, mDecodedProto.wifiNetworkRequestApiLog.numConnectOnSecondaryIface);
4962         assertEquals(2, mDecodedProto.wifiNetworkRequestApiLog.numUserApprovalBypass);
4963         assertEquals(1, mDecodedProto.wifiNetworkRequestApiLog.numUserReject);
4964         assertEquals(1, mDecodedProto.wifiNetworkRequestApiLog.numApps);
4965 
4966         HistogramBucketInt32[] expectedNetworkMatchSizeHistogram = {
4967                 buildHistogramBucketInt32(0, 1, 1),
4968                 buildHistogramBucketInt32(1, 5, 1),
4969                 buildHistogramBucketInt32(5, 10, 1)
4970         };
4971         assertHistogramBucketsEqual(expectedNetworkMatchSizeHistogram,
4972                 mDecodedProto.wifiNetworkRequestApiLog.networkMatchSizeHistogram);
4973 
4974         HistogramBucketInt32[] expectedConnectionDurationOnPrimarySec = {
4975                 buildHistogramBucketInt32(0, toIntExact(Duration.ofMinutes(3).getSeconds()), 1),
4976                 buildHistogramBucketInt32(toIntExact(Duration.ofMinutes(10).getSeconds()),
4977                         toIntExact(Duration.ofMinutes(30).getSeconds()), 1),
4978                 buildHistogramBucketInt32(toIntExact(Duration.ofMinutes(30).getSeconds()),
4979                         toIntExact(Duration.ofHours(1).getSeconds()), 1)
4980         };
4981         assertHistogramBucketsEqual(expectedConnectionDurationOnPrimarySec,
4982                 mDecodedProto.wifiNetworkRequestApiLog
4983                         .connectionDurationSecOnPrimaryIfaceHistogram);
4984 
4985         HistogramBucketInt32[] expectedConnectionDurationOnSecondarySec = {
4986                 buildHistogramBucketInt32(0, toIntExact(Duration.ofMinutes(3).getSeconds()), 1),
4987                 buildHistogramBucketInt32(toIntExact(Duration.ofMinutes(3).getSeconds()),
4988                         toIntExact(Duration.ofMinutes(10).getSeconds()), 1),
4989                 buildHistogramBucketInt32(toIntExact(Duration.ofMinutes(10).getSeconds()),
4990                         toIntExact(Duration.ofMinutes(30).getSeconds()), 1),
4991         };
4992         assertHistogramBucketsEqual(expectedConnectionDurationOnSecondarySec,
4993                 mDecodedProto.wifiNetworkRequestApiLog
4994                         .connectionDurationSecOnSecondaryIfaceHistogram);
4995 
4996         HistogramBucketInt32[] expectedConcurrentConnectionDuration = {
4997                 buildHistogramBucketInt32(0, toIntExact(Duration.ofMinutes(3).getSeconds()), 2),
4998                 buildHistogramBucketInt32(toIntExact(Duration.ofMinutes(3).getSeconds()),
4999                         toIntExact(Duration.ofMinutes(10).getSeconds()), 1),
5000                 buildHistogramBucketInt32(toIntExact(Duration.ofMinutes(30).getSeconds()),
5001                         toIntExact(Duration.ofHours(1).getSeconds()), 1)
5002         };
5003         assertHistogramBucketsEqual(expectedConcurrentConnectionDuration,
5004                 mDecodedProto.wifiNetworkRequestApiLog.concurrentConnectionDurationSecHistogram);
5005     }
5006 
5007     /**
5008      * Test the generation of 'WifiNetworkSuggestionApiLog' message.
5009      */
5010     @Test
testWifiNetworkSuggestionApiLog()5011     public void testWifiNetworkSuggestionApiLog() throws Exception {
5012         mWifiMetrics.incrementNetworkSuggestionApiNumModification();
5013         mWifiMetrics.incrementNetworkSuggestionApiNumModification();
5014         mWifiMetrics.incrementNetworkSuggestionApiNumModification();
5015         mWifiMetrics.incrementNetworkSuggestionApiNumModification();
5016 
5017         mWifiMetrics.incrementNetworkSuggestionApiNumConnectSuccess();
5018         mWifiMetrics.incrementNetworkSuggestionApiNumConnectSuccess();
5019 
5020         mWifiMetrics.incrementNetworkSuggestionApiNumConnectFailure();
5021 
5022         mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType(
5023                 WifiNetworkSuggestionsManager.APP_TYPE_NON_PRIVILEGED);
5024         mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType(
5025                 WifiNetworkSuggestionsManager.APP_TYPE_NON_PRIVILEGED);
5026         mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType(
5027                 WifiNetworkSuggestionsManager.APP_TYPE_NON_PRIVILEGED);
5028         mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType(
5029                 WifiNetworkSuggestionsManager.APP_TYPE_CARRIER_PRIVILEGED);
5030         mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType(
5031                 WifiNetworkSuggestionsManager.APP_TYPE_CARRIER_PRIVILEGED);
5032         mWifiMetrics.incrementNetworkSuggestionApiUsageNumOfAppInType(
5033                 WifiNetworkSuggestionsManager.APP_TYPE_NETWORK_PROVISIONING);
5034 
5035 
5036         mWifiMetrics.noteNetworkSuggestionApiListSizeHistogram(new ArrayList<Integer>() {{
5037                 add(5);
5038                 add(100);
5039                 add(50);
5040                 add(120);
5041             }});
5042         // Second update should overwrite the prevous write.
5043         mWifiMetrics.noteNetworkSuggestionApiListSizeHistogram(new ArrayList<Integer>() {{
5044                 add(7);
5045                 add(110);
5046                 add(40);
5047                 add(60);
5048             }});
5049 
5050         mWifiMetrics.incrementNetworkSuggestionUserRevokePermission();
5051         mWifiMetrics.incrementNetworkSuggestionUserRevokePermission();
5052 
5053         mWifiMetrics.addSuggestionExistsForSavedNetwork("savedNetwork");
5054         mWifiMetrics.incrementNetworkSuggestionMoreThanOneSuggestionForSingleScanResult();
5055         mWifiMetrics.addNetworkSuggestionPriorityGroup(0);
5056         mWifiMetrics.addNetworkSuggestionPriorityGroup(1);
5057         mWifiMetrics.addNetworkSuggestionPriorityGroup(1);
5058 
5059         dumpProtoAndDeserialize();
5060 
5061         assertEquals(4, mDecodedProto.wifiNetworkSuggestionApiLog.numModification);
5062         assertEquals(2, mDecodedProto.wifiNetworkSuggestionApiLog.numConnectSuccess);
5063         assertEquals(1, mDecodedProto.wifiNetworkSuggestionApiLog.numConnectFailure);
5064 
5065         HistogramBucketInt32[] expectedNetworkListSizeHistogram = {
5066                 buildHistogramBucketInt32(5, 20, 1),
5067                 buildHistogramBucketInt32(20, 50, 1),
5068                 buildHistogramBucketInt32(50, 100, 1),
5069                 buildHistogramBucketInt32(100, 500, 1),
5070         };
5071         assertHistogramBucketsEqual(expectedNetworkListSizeHistogram,
5072                 mDecodedProto.wifiNetworkSuggestionApiLog.networkListSizeHistogram);
5073 
5074         assertEquals(3, mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType.length);
5075         assertEquals(WifiMetricsProto.WifiNetworkSuggestionApiLog.TYPE_CARRIER_PRIVILEGED,
5076                 mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType[0].appType);
5077         assertEquals(2, mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType[0].count);
5078         assertEquals(WifiMetricsProto.WifiNetworkSuggestionApiLog.TYPE_NETWORK_PROVISIONING,
5079                 mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType[1].appType);
5080         assertEquals(1, mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType[1].count);
5081         assertEquals(WifiMetricsProto.WifiNetworkSuggestionApiLog.TYPE_NON_PRIVILEGED,
5082                 mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType[2].appType);
5083         assertEquals(3, mDecodedProto.wifiNetworkSuggestionApiLog.appCountPerType[2].count);
5084         assertEquals(1, mDecodedProto.wifiNetworkSuggestionApiLog.numMultipleSuggestions);
5085         assertEquals(1, mDecodedProto.wifiNetworkSuggestionApiLog
5086                 .numSavedNetworksWithConfiguredSuggestion);
5087         assertEquals(1, mDecodedProto.wifiNetworkSuggestionApiLog.numPriorityGroups);
5088     }
5089 
5090     /**
5091      * Test the generation of 'UserReactionToApprovalUiEvent' message.
5092      */
5093     @Test
testUserReactionToApprovalUiEvent()5094     public void testUserReactionToApprovalUiEvent() throws Exception {
5095         mWifiMetrics.addUserApprovalSuggestionAppUiReaction(1,  true);
5096         mWifiMetrics.addUserApprovalSuggestionAppUiReaction(2,  false);
5097 
5098         mWifiMetrics.addUserApprovalCarrierUiReaction(
5099                 WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER, true);
5100         mWifiMetrics.addUserApprovalCarrierUiReaction(
5101                 WifiCarrierInfoManager.ACTION_USER_DISMISS, false);
5102         mWifiMetrics.addUserApprovalCarrierUiReaction(
5103                 WifiCarrierInfoManager.ACTION_USER_DISALLOWED_CARRIER, false);
5104 
5105         dumpProtoAndDeserialize();
5106 
5107         assertEquals(2,
5108                 mDecodedProto.userReactionToApprovalUiEvent.userApprovalAppUiReaction.length);
5109         assertEquals(WifiMetricsProto.UserReactionToApprovalUiEvent.ACTION_ALLOWED,
5110                 mDecodedProto.userReactionToApprovalUiEvent.userApprovalAppUiReaction[0]
5111                         .userAction);
5112         assertEquals(true,
5113                 mDecodedProto.userReactionToApprovalUiEvent.userApprovalAppUiReaction[0]
5114                         .isDialog);
5115         assertEquals(WifiMetricsProto.UserReactionToApprovalUiEvent.ACTION_DISALLOWED,
5116                 mDecodedProto.userReactionToApprovalUiEvent.userApprovalAppUiReaction[1]
5117                         .userAction);
5118         assertEquals(false,
5119                 mDecodedProto.userReactionToApprovalUiEvent.userApprovalAppUiReaction[1]
5120                         .isDialog);
5121 
5122         assertEquals(3,
5123                 mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction.length);
5124         assertEquals(WifiMetricsProto.UserReactionToApprovalUiEvent.ACTION_ALLOWED,
5125                 mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction[0]
5126                         .userAction);
5127         assertEquals(true,
5128                 mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction[0]
5129                         .isDialog);
5130         assertEquals(WifiMetricsProto.UserReactionToApprovalUiEvent.ACTION_DISMISS,
5131                 mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction[1]
5132                         .userAction);
5133         assertEquals(false,
5134                 mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction[1]
5135                         .isDialog);
5136         assertEquals(WifiMetricsProto.UserReactionToApprovalUiEvent.ACTION_DISALLOWED,
5137                 mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction[2]
5138                         .userAction);
5139         assertEquals(false,
5140                 mDecodedProto.userReactionToApprovalUiEvent.userApprovalCarrierUiReaction[2]
5141                         .isDialog);
5142     }
5143 
findUniqueNetworkSelectionExperimentDecisions( int experiment1Id, int experiment2Id)5144     private NetworkSelectionExperimentDecisions findUniqueNetworkSelectionExperimentDecisions(
5145             int experiment1Id, int experiment2Id) {
5146         NetworkSelectionExperimentDecisions result = null;
5147         for (NetworkSelectionExperimentDecisions d
5148                 : mDecodedProto.networkSelectionExperimentDecisionsList) {
5149             if (d.experiment1Id == experiment1Id && d.experiment2Id == experiment2Id) {
5150                 assertNull("duplicate found!", result);
5151                 result = d;
5152             }
5153         }
5154         assertNotNull("not found!", result);
5155         return result;
5156     }
5157 
5158     /**
5159      * Verify that the label and the triggerType of Wifi usability stats are saved correctly
5160      * during IP reachability lost message is received.
5161      * @throws Exception
5162      */
5163     @Test
verifyIpReachabilityLostUpdatesWifiUsabilityMetrics()5164     public void verifyIpReachabilityLostUpdatesWifiUsabilityMetrics() throws Exception {
5165         WifiInfo info = mock(WifiInfo.class);
5166         when(info.getRssi()).thenReturn(nextRandInt());
5167         when(info.getLinkSpeed()).thenReturn(nextRandInt());
5168         long eventTimeMs = nextRandInt();
5169         when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTimeMs);
5170         WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats());
5171         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats1);
5172 
5173         // Add 1 LABEL_GOOD
5174         WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1));
5175         // IP reachability lost occurs
5176         mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
5177                 WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1);
5178 
5179         dumpProtoAndDeserialize();
5180         assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
5181         WifiUsabilityStats[] statsList = mDecodedProto.wifiUsabilityStatsList;
5182         assertEquals(WifiUsabilityStats.LABEL_BAD, statsList[1].label);
5183         assertEquals(WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, statsList[1].triggerType);
5184         assertEquals(eventTimeMs, statsList[1].timeStampMs);
5185     }
5186 
5187     /**
5188      * Test the WifiLock active session statistics
5189      */
5190     @Test
testWifiLockActiveSession()5191     public void testWifiLockActiveSession() throws Exception {
5192         mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 100000);
5193         mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 10000);
5194         mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 10000000);
5195         mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 1000);
5196 
5197         mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 90000);
5198         mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 900000);
5199         mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 9000);
5200         mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 20000000);
5201 
5202         dumpProtoAndDeserialize();
5203 
5204         assertEquals(10111000, mDecodedProto.wifiLockStats.highPerfActiveTimeMs);
5205         assertEquals(20999000, mDecodedProto.wifiLockStats.lowLatencyActiveTimeMs);
5206 
5207         HistogramBucketInt32[] expectedHighPerfHistogram = {
5208                 buildHistogramBucketInt32(1, 10, 1),
5209                 buildHistogramBucketInt32(10, 60, 1),
5210                 buildHistogramBucketInt32(60, 600, 1),
5211                 buildHistogramBucketInt32(3600, Integer.MAX_VALUE, 1),
5212         };
5213 
5214         HistogramBucketInt32[] expectedLowLatencyHistogram = {
5215                 buildHistogramBucketInt32(1, 10, 1),
5216                 buildHistogramBucketInt32(60, 600, 1),
5217                 buildHistogramBucketInt32(600, 3600, 1),
5218                 buildHistogramBucketInt32(3600, Integer.MAX_VALUE, 1),
5219         };
5220 
5221         assertHistogramBucketsEqual(expectedHighPerfHistogram,
5222                 mDecodedProto.wifiLockStats.highPerfActiveSessionDurationSecHistogram);
5223 
5224         assertHistogramBucketsEqual(expectedLowLatencyHistogram,
5225                 mDecodedProto.wifiLockStats.lowLatencyActiveSessionDurationSecHistogram);
5226     }
5227 
5228     /**
5229      * Test the WifiLock acquisition session statistics
5230      */
5231     @Test
testWifiLockAcqSession()5232     public void testWifiLockAcqSession() throws Exception {
5233         mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 100000);
5234         mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 10000);
5235         mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 10000000);
5236         mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 1000);
5237 
5238         mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 90000);
5239         mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 900000);
5240         mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 9000);
5241         mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 20000000);
5242 
5243         dumpProtoAndDeserialize();
5244 
5245         HistogramBucketInt32[] expectedHighPerfHistogram = {
5246                 buildHistogramBucketInt32(1, 10, 1),
5247                 buildHistogramBucketInt32(10, 60, 1),
5248                 buildHistogramBucketInt32(60, 600, 1),
5249                 buildHistogramBucketInt32(3600, Integer.MAX_VALUE, 1),
5250         };
5251 
5252         HistogramBucketInt32[] expectedLowLatencyHistogram = {
5253                 buildHistogramBucketInt32(1, 10, 1),
5254                 buildHistogramBucketInt32(60, 600, 1),
5255                 buildHistogramBucketInt32(600, 3600, 1),
5256                 buildHistogramBucketInt32(3600, Integer.MAX_VALUE, 1),
5257         };
5258 
5259         assertHistogramBucketsEqual(expectedHighPerfHistogram,
5260                 mDecodedProto.wifiLockStats.highPerfLockAcqDurationSecHistogram);
5261 
5262         assertHistogramBucketsEqual(expectedLowLatencyHistogram,
5263                 mDecodedProto.wifiLockStats.lowLatencyLockAcqDurationSecHistogram);
5264     }
5265 
5266     /**
5267      * Verify that LABEL_GOOD stats are generated if Wifi score breaches low and there
5268      * is no WifiIsUnusableEvent in MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
5269      * @throws Exception
5270      */
5271     @Test
testGoodStatsAreGeneratedByWifiScoreBreachLow()5272     public void testGoodStatsAreGeneratedByWifiScoreBreachLow() throws Exception {
5273         // The elapsed time falls into the interval for adding good stats
5274         createTestForDataCollectionByScoreBreach(
5275                 WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS + 1,
5276                 false, true);
5277         dumpProtoAndDeserialize();
5278         assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
5279     }
5280 
5281     /**
5282      * Verify that LABEL_GOOD stats are not generated if Wifi score breaches low and the checking
5283      * time is less than MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
5284      * @throws Exception
5285      */
5286     @Test
testGoodStatsAreNotGeneratedByWifiScoreBreachLow()5287     public void testGoodStatsAreNotGeneratedByWifiScoreBreachLow() throws Exception {
5288         // The elapsed time is shorter than necessary to add good stats
5289         createTestForDataCollectionByScoreBreach(
5290                 WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS - 1,
5291                 false, true);
5292         dumpProtoAndDeserialize();
5293         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
5294     }
5295 
5296     /**
5297      * Verify that LABEL_GOOD stats are not generated if Wifi score breaches low and the checking
5298      * time is greater than VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS
5299      * @throws Exception
5300      */
5301     @Test
testGoodStatsAreNotGeneratedIfWifiScoreBreachExpires()5302     public void testGoodStatsAreNotGeneratedIfWifiScoreBreachExpires() throws Exception {
5303         // The Wifi score breaching expires for adding good stats
5304         createTestForDataCollectionByScoreBreach(
5305                 WifiMetrics.VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS + 1,
5306                 false, true);
5307         dumpProtoAndDeserialize();
5308         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
5309     }
5310 
5311     /**
5312      * Verify that LABEL_GOOD stats are not generated if Wifi score breaches low and there is
5313      * WifiIsUnusableEvent occured within MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
5314      * @throws Exception
5315      */
5316     @Test
testGoodStatsAreNotGeneratedIfBadEventOccured()5317     public void testGoodStatsAreNotGeneratedIfBadEventOccured() throws Exception {
5318         // The elapsed time falls into the interval for adding good stats and bad event occurs
5319         createTestForDataCollectionByScoreBreach(
5320                 WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS + 1,
5321                 true, true);
5322         dumpProtoAndDeserialize();
5323         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
5324     }
5325 
5326     /**
5327      * Verify that LABEL_GOOD stats are generated if Wifi usability score breaches low and there
5328      * is no WifiIsUnusableEvent in MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
5329      * @throws Exception
5330      */
5331     @Test
testGoodStatsAreGeneratedByWifiUsabilityScoreBreachLow()5332     public void testGoodStatsAreGeneratedByWifiUsabilityScoreBreachLow() throws Exception {
5333         // The elapsed time falls into the interval for adding good stats
5334         createTestForDataCollectionByScoreBreach(
5335                 WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS + 1,
5336                 false, false);
5337         dumpProtoAndDeserialize();
5338         assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
5339     }
5340 
5341     /**
5342      * Verify that LABEL_GOOD stats are not generated if Wifi usability score breaches low and
5343      * the checking time is less than MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
5344      * @throws Exception
5345      */
5346     @Test
testGoodStatsAreNotGeneratedByWifiUsabilityScoreBreachLow()5347     public void testGoodStatsAreNotGeneratedByWifiUsabilityScoreBreachLow() throws Exception {
5348         // The elapsed time is shorter than necessary to add good stats
5349         createTestForDataCollectionByScoreBreach(
5350                 WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS - 1,
5351                 false, false);
5352         dumpProtoAndDeserialize();
5353         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
5354     }
5355 
5356     /**
5357      * Verify that LABEL_GOOD stats are not generated if Wifi usability score breaches low and
5358      * the checking time is greater than VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS
5359      * @throws Exception
5360      */
5361     @Test
testGoodStatsAreNotGeneratedIfWifiUsabilityScoreBreachExpires()5362     public void testGoodStatsAreNotGeneratedIfWifiUsabilityScoreBreachExpires() throws Exception {
5363         // The Wifi usability score breaching expires for adding good stats
5364         createTestForDataCollectionByScoreBreach(
5365                 WifiMetrics.VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS + 1,
5366                 false, false);
5367         dumpProtoAndDeserialize();
5368         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
5369     }
5370 
5371     /**
5372      * Verify that LABEL_GOOD stats are not generated if Wifi usability score breaches low and there
5373      * is WifiIsUnusableEvent occured within MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
5374      * @throws Exception
5375      */
5376     @Test
testGoodStatsAreNotGeneratedIfBadEventOccuredForUsabilityScore()5377     public void testGoodStatsAreNotGeneratedIfBadEventOccuredForUsabilityScore() throws Exception {
5378         // The elapsed time falls into the interval for adding good stats and bad event occurs
5379         createTestForDataCollectionByScoreBreach(
5380                 WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS + 1,
5381                 true, false);
5382         dumpProtoAndDeserialize();
5383         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
5384     }
5385 
5386     /**
5387      * Verify that incrementNumWifiToggles increments the corrects fields based on input.
5388      */
5389     @Test
testIncrementNumWifiToggles()5390     public void testIncrementNumWifiToggles() throws Exception {
5391         mWifiMetrics.incrementNumWifiToggles(true, true);
5392         for (int i = 0; i < 2; i++) {
5393             mWifiMetrics.incrementNumWifiToggles(true, false);
5394         }
5395         for (int i = 0; i < 3; i++) {
5396             mWifiMetrics.incrementNumWifiToggles(false, true);
5397         }
5398         for (int i = 0; i < 4; i++) {
5399             mWifiMetrics.incrementNumWifiToggles(false, false);
5400         }
5401         dumpProtoAndDeserialize();
5402         assertEquals(1, mDecodedProto.wifiToggleStats.numToggleOnPrivileged);
5403         assertEquals(2, mDecodedProto.wifiToggleStats.numToggleOffPrivileged);
5404         assertEquals(3, mDecodedProto.wifiToggleStats.numToggleOnNormal);
5405         assertEquals(4, mDecodedProto.wifiToggleStats.numToggleOffNormal);
5406     }
5407 
5408     /**
5409      * Verify metered stats are counted properly for saved and ephemeral networks.
5410      */
5411     @Test
testMeteredNetworkMetrics()5412     public void testMeteredNetworkMetrics() throws Exception {
5413         // Test without metered override
5414         WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork();
5415         WifiConfiguration config1 = WifiConfigurationTestUtil.createPskNetwork();
5416         config.fromWifiNetworkSuggestion = false;
5417         config1.fromWifiNetworkSuggestion = true;
5418         mWifiMetrics.addMeteredStat(config, false);
5419         mWifiMetrics.addMeteredStat(config1, true);
5420         dumpProtoAndDeserialize();
5421         assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numMetered);
5422         assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numUnmetered);
5423         assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numOverrideMetered);
5424         assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numOverrideUnmetered);
5425         assertEquals(1, mDecodedProto.meteredNetworkStatsSuggestion.numMetered);
5426         assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numUnmetered);
5427         assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideMetered);
5428         assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideUnmetered);
5429 
5430         // Test with metered override
5431         config = WifiConfigurationTestUtil.createPskNetwork();
5432         config1 = WifiConfigurationTestUtil.createPskNetwork();
5433         config.meteredOverride = WifiConfiguration.METERED_OVERRIDE_METERED;
5434         config1.meteredOverride = WifiConfiguration.METERED_OVERRIDE_NOT_METERED;
5435         mWifiMetrics.addMeteredStat(config, true);
5436         mWifiMetrics.addMeteredStat(config1, true);
5437         dumpProtoAndDeserialize();
5438         assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numMetered);
5439         assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numUnmetered);
5440         assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numOverrideMetered);
5441         assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numOverrideUnmetered);
5442         assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numMetered);
5443         assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numUnmetered);
5444         assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideMetered);
5445         assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideUnmetered);
5446     }
5447 
5448     /**
5449      * Verify that the same network does not get counted twice
5450      */
5451     @Test
testMeteredNetworkMetricsNoDoubleCount()5452     public void testMeteredNetworkMetricsNoDoubleCount() throws Exception {
5453         WifiConfiguration config = new WifiConfiguration();
5454         config.ephemeral = false;
5455         mWifiMetrics.addMeteredStat(config, false);
5456         mWifiMetrics.addMeteredStat(config, true);
5457         mWifiMetrics.addMeteredStat(config, true);
5458         dumpProtoAndDeserialize();
5459         assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numMetered);
5460         assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numUnmetered);
5461         assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numOverrideMetered);
5462         assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numOverrideUnmetered);
5463         assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numMetered);
5464         assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numUnmetered);
5465         assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideMetered);
5466         assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideUnmetered);
5467     }
5468 
5469     /**
5470      * Create a test to verify data collection logic triggered by score breaching low
5471      * @param elapsedTimeAfterBreach The elapsed time after score breaches low
5472      * @param isThereBadEvent Whether there is a bad event happened after score breaches low
5473      * @param isWifiScore Whether it is Wifi score or not that breaches the threshold
5474      */
createTestForDataCollectionByScoreBreach( long elapsedTimeAfterBreach, boolean isThereBadEvent, boolean isWifiScore)5475     private void createTestForDataCollectionByScoreBreach(
5476             long elapsedTimeAfterBreach, boolean isThereBadEvent, boolean isWifiScore) {
5477         WifiInfo info = mock(WifiInfo.class);
5478         when(info.getRssi()).thenReturn(nextRandInt());
5479         when(info.getLinkSpeed()).thenReturn(nextRandInt());
5480         WifiLinkLayerStats stats2 = new WifiLinkLayerStats();
5481         mWifiMetrics.setWifiState(TEST_IFACE_NAME, WifiMetricsProto.WifiLog.WIFI_ASSOCIATED);
5482 
5483         addOneBadWifiUsabilityStats(info);
5484         if (isWifiScore) {
5485             stats2 = wifiScoreBreachesLow(info, stats2);
5486         } else {
5487             stats2 = wifiUsabilityScoreBreachesLow(info, stats2);
5488         }
5489         if (isThereBadEvent) {
5490             mWifiMetrics.logWifiIsUnusableEvent(TEST_IFACE_NAME,
5491                     WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, -1);
5492         }
5493         when(mClock.getElapsedSinceBootMillis()).thenReturn(elapsedTimeAfterBreach);
5494         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2);
5495     }
5496 
5497     // Simulate adding one LABEL_BAD WifiUsabilityStats
addOneBadWifiUsabilityStats(WifiInfo info)5498     private void addOneBadWifiUsabilityStats(WifiInfo info) {
5499         WifiLinkLayerStats stats1 = new WifiLinkLayerStats();
5500         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats1);
5501         mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
5502                 WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
5503     }
5504 
5505     // Simulate that Wifi score breaches low
wifiScoreBreachesLow(WifiInfo info, WifiLinkLayerStats stats2)5506     private WifiLinkLayerStats wifiScoreBreachesLow(WifiInfo info, WifiLinkLayerStats stats2) {
5507         int upper = WifiMetrics.LOW_WIFI_SCORE + 7;
5508         int lower = WifiMetrics.LOW_WIFI_SCORE - 8;
5509         mWifiMetrics.incrementWifiScoreCount(TEST_IFACE_NAME, upper);
5510         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2);
5511         stats2 = nextRandomStats(stats2);
5512         long timeMs = 0;
5513         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
5514         // Wifi score breaches low
5515         mWifiMetrics.incrementWifiScoreCount(TEST_IFACE_NAME, lower);
5516         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2);
5517         stats2 = nextRandomStats(stats2);
5518         return stats2;
5519     }
5520 
5521     // Simulate that Wifi usability score breaches low
wifiUsabilityScoreBreachesLow(WifiInfo info, WifiLinkLayerStats stats2)5522     private WifiLinkLayerStats wifiUsabilityScoreBreachesLow(WifiInfo info,
5523             WifiLinkLayerStats stats2) {
5524         int upper = WifiMetrics.LOW_WIFI_USABILITY_SCORE + 7;
5525         int lower = WifiMetrics.LOW_WIFI_USABILITY_SCORE - 8;
5526         mWifiMetrics.incrementWifiUsabilityScoreCount(TEST_IFACE_NAME, 1, upper, 30);
5527         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2);
5528         stats2 = nextRandomStats(stats2);
5529         long timeMs = 0;
5530         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
5531         // Wifi usability score breaches low
5532         mWifiMetrics.incrementWifiUsabilityScoreCount(TEST_IFACE_NAME, 2, lower, 30);
5533         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2);
5534         stats2 = nextRandomStats(stats2);
5535         return stats2;
5536     }
5537 
5538     /**
5539      * Verify the counts of passpoint profile type are correct.
5540      * @param profileTypes type and count of installed passpoint profiles
5541      */
assertPasspointProfileTypeCount(PasspointProfileTypeCount[] profileTypes)5542     private void assertPasspointProfileTypeCount(PasspointProfileTypeCount[] profileTypes) {
5543         for (PasspointProfileTypeCount passpointProfileType : profileTypes) {
5544             switch(passpointProfileType.eapMethodType) {
5545                 case PasspointProfileTypeCount.TYPE_EAP_AKA:
5546                     assertEquals(NUM_EAP_AKA_TYPE, passpointProfileType.count);
5547                     break;
5548                 case PasspointProfileTypeCount.TYPE_EAP_AKA_PRIME:
5549                     assertEquals(NUM_EAP_AKA_PRIME_TYPE, passpointProfileType.count);
5550                     break;
5551                 case PasspointProfileTypeCount.TYPE_EAP_SIM:
5552                     assertEquals(NUM_EAP_SIM_TYPE, passpointProfileType.count);
5553                     break;
5554                 case PasspointProfileTypeCount.TYPE_EAP_TLS:
5555                     assertEquals(NUM_EAP_TLS_TYPE, passpointProfileType.count);
5556                     break;
5557                 case PasspointProfileTypeCount.TYPE_EAP_TTLS:
5558                     assertEquals(NUM_EAP_TTLS_TYPE, passpointProfileType.count);
5559                     break;
5560                 default:
5561                     fail("unknown type counted");
5562             }
5563         }
5564     }
5565 
5566     /**
5567      * Verify that the LABEL_BAD Wifi usability stats are not saved if screen state is off.
5568      * @throws Exception
5569      */
5570     @Test
verifyLabelBadStatsAreNotSavedIfScreenIsOff()5571     public void verifyLabelBadStatsAreNotSavedIfScreenIsOff() throws Exception {
5572         setScreenState(false);
5573         WifiInfo info = mock(WifiInfo.class);
5574         when(info.getRssi()).thenReturn(nextRandInt());
5575         when(info.getLinkSpeed()).thenReturn(nextRandInt());
5576         WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats());
5577         mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats1);
5578 
5579         // Add 1 LABEL_GOOD
5580         WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1));
5581         // IP reachability lost occurs
5582         mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
5583                 WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1);
5584         // Wifi data stall occurs
5585         mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
5586                 WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, -1);
5587         // Firmware alert occurs
5588         mWifiMetrics.logFirmwareAlert(TEST_IFACE_NAME, 2);
5589 
5590         dumpProtoAndDeserialize();
5591         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
5592     }
5593 
5594     /**
5595      * Test the logging of connection duration stats
5596      */
5597     @Test
testConnectionDurationStats()5598     public void testConnectionDurationStats() throws Exception {
5599         for (int i = 0; i < 2; i++) {
5600             mWifiMetrics.incrementWifiScoreCount(TEST_IFACE_NAME, 52);
5601             mWifiMetrics.incrementConnectionDuration(5000, false, true);
5602             mWifiMetrics.incrementWifiScoreCount(TEST_IFACE_NAME, 40);
5603             mWifiMetrics.incrementConnectionDuration(5000, false, true);
5604             mWifiMetrics.incrementConnectionDuration(3000, true, true);
5605             mWifiMetrics.incrementConnectionDuration(1000, false, false);
5606             mWifiMetrics.incrementConnectionDuration(500, true, false);
5607         }
5608         dumpProtoAndDeserialize();
5609 
5610         assertEquals(6000,
5611                 mDecodedProto.connectionDurationStats.totalTimeSufficientThroughputMs);
5612         assertEquals(20000,
5613                 mDecodedProto.connectionDurationStats.totalTimeInsufficientThroughputMs);
5614         assertEquals(10000,
5615                 mDecodedProto.connectionDurationStats.totalTimeInsufficientThroughputDefaultWifiMs);
5616         assertEquals(3000,
5617                 mDecodedProto.connectionDurationStats.totalTimeCellularDataOffMs);
5618     }
5619 
5620     /**
5621      * Test the logging of isExternalWifiScorerOn
5622      */
5623     @Test
testIsExternalWifiScorerOn()5624     public void testIsExternalWifiScorerOn() throws Exception {
5625         mWifiMetrics.setIsExternalWifiScorerOn(true);
5626         dumpProtoAndDeserialize();
5627         assertEquals(true, mDecodedProto.isExternalWifiScorerOn);
5628     }
5629 
5630     /*
5631      * Test the logging of Wi-Fi off
5632      */
5633     @Test
testWifiOff()5634     public void testWifiOff() throws Exception {
5635         // if not deferred, timeout and duration should be ignored.
5636         mWifiMetrics.noteWifiOff(false, false, 0);
5637         mWifiMetrics.noteWifiOff(false, true, 999);
5638 
5639         // deferred, not timed out
5640         mWifiMetrics.noteWifiOff(true, false, 0);
5641         mWifiMetrics.noteWifiOff(true, false, 1000);
5642 
5643         // deferred and timed out
5644         mWifiMetrics.noteWifiOff(true, true, 2000);
5645         mWifiMetrics.noteWifiOff(true, true, 2000);
5646         mWifiMetrics.noteWifiOff(true, true, 4000);
5647 
5648         dumpProtoAndDeserialize();
5649 
5650         assertEquals(7,
5651                 mDecodedProto.wifiOffMetrics.numWifiOff);
5652         assertEquals(5,
5653                 mDecodedProto.wifiOffMetrics.numWifiOffDeferring);
5654         assertEquals(3,
5655                 mDecodedProto.wifiOffMetrics.numWifiOffDeferringTimeout);
5656 
5657         Int32Count[] expectedHistogram = {
5658                 buildInt32Count(0, 1),
5659                 buildInt32Count(1000, 1),
5660                 buildInt32Count(2000, 2),
5661                 buildInt32Count(4000, 1),
5662         };
5663         assertKeyCountsEqual(expectedHistogram,
5664                 mDecodedProto.wifiOffMetrics.wifiOffDeferringTimeHistogram);
5665     }
5666 
5667     /*
5668      * Test the logging of Wi-Fi off
5669      */
5670     @Test
testSoftApConfigLimitationMetrics()5671     public void testSoftApConfigLimitationMetrics() throws Exception {
5672         SoftApConfiguration originalConfig = new SoftApConfiguration.Builder()
5673                 .setSsid("TestSSID").build();
5674         SoftApConfiguration needToResetCongig = new SoftApConfiguration.Builder(originalConfig)
5675                 .setPassphrase("TestPassphreas", SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)
5676                 .setClientControlByUserEnabled(true)
5677                 .setMaxNumberOfClients(10)
5678                 .build();
5679         mWifiMetrics.noteSoftApConfigReset(originalConfig, needToResetCongig);
5680 
5681         mWifiMetrics.noteSoftApClientBlocked(5);
5682         mWifiMetrics.noteSoftApClientBlocked(5);
5683         mWifiMetrics.noteSoftApClientBlocked(5);
5684         mWifiMetrics.noteSoftApClientBlocked(8);
5685 
5686         dumpProtoAndDeserialize();
5687 
5688         assertEquals(1,
5689                 mDecodedProto.softApConfigLimitationMetrics.numSecurityTypeResetToDefault);
5690         assertEquals(1,
5691                 mDecodedProto.softApConfigLimitationMetrics.numMaxClientSettingResetToDefault);
5692         assertEquals(1,
5693                 mDecodedProto.softApConfigLimitationMetrics.numClientControlByUserResetToDefault);
5694 
5695         Int32Count[] expectedHistogram = {
5696                 buildInt32Count(5, 3),
5697                 buildInt32Count(8, 1),
5698         };
5699         assertKeyCountsEqual(expectedHistogram,
5700                 mDecodedProto.softApConfigLimitationMetrics.maxClientSettingWhenReachHistogram);
5701     }
5702 
5703     /**
5704      * Test the logging of channel utilization
5705      */
5706     @Test
testChannelUtilization()5707     public void testChannelUtilization() throws Exception {
5708         mWifiMetrics.incrementChannelUtilizationCount(180, 2412);
5709         mWifiMetrics.incrementChannelUtilizationCount(150, 2412);
5710         mWifiMetrics.incrementChannelUtilizationCount(230, 2412);
5711         mWifiMetrics.incrementChannelUtilizationCount(20, 5510);
5712         mWifiMetrics.incrementChannelUtilizationCount(50, 5510);
5713 
5714         dumpProtoAndDeserialize();
5715 
5716         HistogramBucketInt32[] expected2GHistogram = {
5717                 buildHistogramBucketInt32(150, 175, 1),
5718                 buildHistogramBucketInt32(175, 200, 1),
5719                 buildHistogramBucketInt32(225, Integer.MAX_VALUE, 1),
5720         };
5721 
5722         HistogramBucketInt32[] expectedAbove2GHistogram = {
5723                 buildHistogramBucketInt32(Integer.MIN_VALUE, 25, 1),
5724                 buildHistogramBucketInt32(50, 75, 1),
5725         };
5726 
5727         assertHistogramBucketsEqual(expected2GHistogram,
5728                 mDecodedProto.channelUtilizationHistogram.utilization2G);
5729         assertHistogramBucketsEqual(expectedAbove2GHistogram,
5730                 mDecodedProto.channelUtilizationHistogram.utilizationAbove2G);
5731     }
5732 
5733     /**
5734      * Test the logging of Tx and Rx throughput
5735      */
5736     @Test
testThroughput()5737     public void testThroughput() throws Exception {
5738         mWifiMetrics.incrementThroughputKbpsCount(500, 800, 2412);
5739         mWifiMetrics.incrementThroughputKbpsCount(5_000, 4_000, 2412);
5740         mWifiMetrics.incrementThroughputKbpsCount(54_000, 48_000, 2412);
5741         mWifiMetrics.incrementThroughputKbpsCount(50_000, 49_000, 5510);
5742         mWifiMetrics.incrementThroughputKbpsCount(801_000, 790_000, 5510);
5743         mWifiMetrics.incrementThroughputKbpsCount(1100_000, 1200_000, 5510);
5744         mWifiMetrics.incrementThroughputKbpsCount(1599_000, 1800_000, 6120);
5745         dumpProtoAndDeserialize();
5746 
5747         HistogramBucketInt32[] expectedTx2GHistogramMbps = {
5748                 buildHistogramBucketInt32(Integer.MIN_VALUE, 1, 1),
5749                 buildHistogramBucketInt32(5, 10, 1),
5750                 buildHistogramBucketInt32(50, 100, 1),
5751         };
5752 
5753         HistogramBucketInt32[] expectedRx2GHistogramMbps = {
5754                 buildHistogramBucketInt32(Integer.MIN_VALUE, 1, 1),
5755                 buildHistogramBucketInt32(1, 5, 1),
5756                 buildHistogramBucketInt32(25, 50, 1),
5757         };
5758 
5759         HistogramBucketInt32[] expectedTxAbove2GHistogramMbps = {
5760                 buildHistogramBucketInt32(50, 100, 1),
5761                 buildHistogramBucketInt32(800, 1200, 2),
5762                 buildHistogramBucketInt32(1200, 1600, 1),
5763         };
5764 
5765         HistogramBucketInt32[] expectedRxAbove2GHistogramMbps = {
5766                 buildHistogramBucketInt32(25, 50, 1),
5767                 buildHistogramBucketInt32(600, 800, 1),
5768                 buildHistogramBucketInt32(1200, 1600, 1),
5769                 buildHistogramBucketInt32(1600, Integer.MAX_VALUE, 1),
5770         };
5771 
5772         assertHistogramBucketsEqual(expectedTx2GHistogramMbps,
5773                 mDecodedProto.throughputMbpsHistogram.tx2G);
5774         assertHistogramBucketsEqual(expectedTxAbove2GHistogramMbps,
5775                 mDecodedProto.throughputMbpsHistogram.txAbove2G);
5776         assertHistogramBucketsEqual(expectedRx2GHistogramMbps,
5777                 mDecodedProto.throughputMbpsHistogram.rx2G);
5778         assertHistogramBucketsEqual(expectedRxAbove2GHistogramMbps,
5779                 mDecodedProto.throughputMbpsHistogram.rxAbove2G);
5780     }
5781 
5782     /**
5783      * Test the Initial partial scan statistics
5784      */
5785     @Test
testInitPartialScan()5786     public void testInitPartialScan() throws Exception {
5787         mWifiMetrics.incrementInitialPartialScanCount();
5788         mWifiMetrics.reportInitialPartialScan(4, true);
5789         mWifiMetrics.incrementInitialPartialScanCount();
5790         mWifiMetrics.reportInitialPartialScan(2, false);
5791         mWifiMetrics.incrementInitialPartialScanCount();
5792         mWifiMetrics.incrementInitialPartialScanCount();
5793         mWifiMetrics.reportInitialPartialScan(1, false);
5794         mWifiMetrics.incrementInitialPartialScanCount();
5795         mWifiMetrics.reportInitialPartialScan(7, true);
5796         mWifiMetrics.incrementInitialPartialScanCount();
5797         mWifiMetrics.incrementInitialPartialScanCount();
5798         mWifiMetrics.reportInitialPartialScan(15, false);
5799         mWifiMetrics.incrementInitialPartialScanCount();
5800         mWifiMetrics.reportInitialPartialScan(2, true);
5801         mWifiMetrics.incrementInitialPartialScanCount();
5802         mWifiMetrics.reportInitialPartialScan(10, true);
5803 
5804         dumpProtoAndDeserialize();
5805 
5806         assertEquals(9, mDecodedProto.initPartialScanStats.numScans);
5807         assertEquals(4, mDecodedProto.initPartialScanStats.numSuccessScans);
5808         assertEquals(3, mDecodedProto.initPartialScanStats.numFailureScans);
5809 
5810         HistogramBucketInt32[] expectedSuccessScanHistogram = {
5811                 buildHistogramBucketInt32(1, 3, 1),
5812                 buildHistogramBucketInt32(3, 5, 1),
5813                 buildHistogramBucketInt32(5, 10, 1),
5814                 buildHistogramBucketInt32(10, Integer.MAX_VALUE, 1),
5815         };
5816 
5817         HistogramBucketInt32[] expectedFailureScanHistogram = {
5818                 buildHistogramBucketInt32(1, 3, 2),
5819                 buildHistogramBucketInt32(10, Integer.MAX_VALUE, 1),
5820         };
5821 
5822         assertHistogramBucketsEqual(expectedSuccessScanHistogram,
5823                 mDecodedProto.initPartialScanStats.successfulScanChannelCountHistogram);
5824 
5825         assertHistogramBucketsEqual(expectedFailureScanHistogram,
5826                 mDecodedProto.initPartialScanStats.failedScanChannelCountHistogram);
5827     }
5828 
5829     /**
5830      * Test overlapping and non-overlapping connection events return overlapping duration correctly
5831      */
5832     @Test
testOverlappingConnectionEvent()5833     public void testOverlappingConnectionEvent() throws Exception {
5834         // Connection event 1
5835         when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 0);
5836         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, mTestWifiConfig,
5837                 "TestNetwork", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
5838         when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 1000);
5839         // Connection event 2 overlaps with 1
5840         assertEquals(1000, mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, mTestWifiConfig,
5841                 "TestNetwork", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE));
5842 
5843         // Connection event 2 ends
5844         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
5845                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
5846                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
5847                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
5848         when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 2000);
5849         // Connection event 3 doesn't overlap with 2
5850         assertEquals(0, mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, mTestWifiConfig,
5851                 "TestNetwork", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE));
5852     }
5853 
5854     @Test
testCarrierWifiConnectionEvent()5855     public void testCarrierWifiConnectionEvent() throws Exception {
5856         mWifiMetrics.incrementNumOfCarrierWifiConnectionSuccess();
5857         for (int i = 0; i < 2; i++) {
5858             mWifiMetrics.incrementNumOfCarrierWifiConnectionAuthFailure();
5859         }
5860         for (int i = 0; i < 3; i++) {
5861             mWifiMetrics.incrementNumOfCarrierWifiConnectionNonAuthFailure();
5862         }
5863 
5864         dumpProtoAndDeserialize();
5865 
5866         assertEquals(1, mDecodedProto.carrierWifiMetrics.numConnectionSuccess);
5867         assertEquals(2, mDecodedProto.carrierWifiMetrics.numConnectionAuthFailure);
5868         assertEquals(3, mDecodedProto.carrierWifiMetrics.numConnectionNonAuthFailure);
5869     }
5870 
5871     /**
5872      * Verify the ConnectionEvent is labeled with networkType Passpoint correctly and that the OSU
5873      * provisioned flag is set to true.
5874      */
5875     @Test
testConnectionNetworkTypePasspointFromOsu()5876     public void testConnectionNetworkTypePasspointFromOsu() throws Exception {
5877         WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork();
5878         config.updateIdentifier = "7";
5879         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, config,
5880                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_NONE);
5881         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
5882                 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
5883                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
5884                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
5885         dumpProtoAndDeserialize();
5886 
5887         assertEquals(1, mDecodedProto.connectionEvent.length);
5888         assertEquals(WifiMetricsProto.ConnectionEvent.TYPE_PASSPOINT,
5889                 mDecodedProto.connectionEvent[0].networkType);
5890         assertTrue(mDecodedProto.connectionEvent[0].isOsuProvisioned);
5891     }
5892 
5893     @Test
testFirstConnectAfterBootStats()5894     public void testFirstConnectAfterBootStats() throws Exception {
5895         when(mClock.getElapsedSinceBootMillis()).thenReturn(1000L);
5896         mWifiMetrics.noteWifiEnabledDuringBoot(true);
5897 
5898         when(mClock.getElapsedSinceBootMillis()).thenReturn(2000L);
5899         mWifiMetrics.noteFirstNetworkSelectionAfterBoot(true);
5900 
5901         when(mClock.getElapsedSinceBootMillis()).thenReturn(3000L);
5902         mWifiMetrics.noteFirstL2ConnectionAfterBoot(true);
5903 
5904         when(mClock.getElapsedSinceBootMillis()).thenReturn(4000L);
5905         mWifiMetrics.noteFirstL3ConnectionAfterBoot(true);
5906 
5907         dumpProtoAndDeserialize();
5908 
5909         assertEquals(1000, mDecodedProto
5910                 .firstConnectAfterBootStats.wifiEnabledAtBoot.timestampSinceBootMillis);
5911         assertTrue(mDecodedProto.firstConnectAfterBootStats.wifiEnabledAtBoot.isSuccess);
5912         assertEquals(2000, mDecodedProto
5913                 .firstConnectAfterBootStats.firstNetworkSelection.timestampSinceBootMillis);
5914         assertTrue(mDecodedProto.firstConnectAfterBootStats.firstNetworkSelection.isSuccess);
5915         assertEquals(3000, mDecodedProto
5916                 .firstConnectAfterBootStats.firstL2Connection.timestampSinceBootMillis);
5917         assertTrue(mDecodedProto.firstConnectAfterBootStats.firstL2Connection.isSuccess);
5918         assertEquals(4000, mDecodedProto
5919                 .firstConnectAfterBootStats.firstL3Connection.timestampSinceBootMillis);
5920         assertTrue(mDecodedProto.firstConnectAfterBootStats.firstL3Connection.isSuccess);
5921     }
5922 
5923     @Test
testFirstConnectAfterBootStats_firstCallWins()5924     public void testFirstConnectAfterBootStats_firstCallWins() throws Exception {
5925         when(mClock.getElapsedSinceBootMillis()).thenReturn(1000L);
5926         mWifiMetrics.noteWifiEnabledDuringBoot(true);
5927 
5928         when(mClock.getElapsedSinceBootMillis()).thenReturn(2000L);
5929         mWifiMetrics.noteWifiEnabledDuringBoot(false);
5930 
5931         dumpProtoAndDeserialize();
5932 
5933         assertEquals(1000, mDecodedProto
5934                 .firstConnectAfterBootStats.wifiEnabledAtBoot.timestampSinceBootMillis);
5935         assertTrue(mDecodedProto.firstConnectAfterBootStats.wifiEnabledAtBoot.isSuccess);
5936     }
5937 
5938     @Test
testFirstConnectAfterBootStats_secondDumpNull()5939     public void testFirstConnectAfterBootStats_secondDumpNull() throws Exception {
5940         when(mClock.getElapsedSinceBootMillis()).thenReturn(1000L);
5941         mWifiMetrics.noteWifiEnabledDuringBoot(true);
5942 
5943         dumpProtoAndDeserialize();
5944 
5945         when(mClock.getElapsedSinceBootMillis()).thenReturn(2000L);
5946         mWifiMetrics.noteWifiEnabledDuringBoot(false);
5947 
5948         dumpProtoAndDeserialize();
5949 
5950         assertNull(mDecodedProto.firstConnectAfterBootStats);
5951     }
5952 
5953     @Test
testFirstConnectAfterBootStats_falseInvalidatesSubsequentCalls()5954     public void testFirstConnectAfterBootStats_falseInvalidatesSubsequentCalls() throws Exception {
5955         when(mClock.getElapsedSinceBootMillis()).thenReturn(1000L);
5956         mWifiMetrics.noteWifiEnabledDuringBoot(false);
5957 
5958         when(mClock.getElapsedSinceBootMillis()).thenReturn(2000L);
5959         mWifiMetrics.noteFirstNetworkSelectionAfterBoot(true);
5960 
5961         when(mClock.getElapsedSinceBootMillis()).thenReturn(3000L);
5962         mWifiMetrics.noteFirstL2ConnectionAfterBoot(true);
5963 
5964         when(mClock.getElapsedSinceBootMillis()).thenReturn(4000L);
5965         mWifiMetrics.noteFirstL3ConnectionAfterBoot(true);
5966 
5967         dumpProtoAndDeserialize();
5968 
5969         assertEquals(1000, mDecodedProto
5970                 .firstConnectAfterBootStats.wifiEnabledAtBoot.timestampSinceBootMillis);
5971         assertFalse(mDecodedProto.firstConnectAfterBootStats.wifiEnabledAtBoot.isSuccess);
5972         assertNull(mDecodedProto.firstConnectAfterBootStats.firstNetworkSelection);
5973         assertNull(mDecodedProto.firstConnectAfterBootStats.firstL2Connection);
5974         assertNull(mDecodedProto.firstConnectAfterBootStats.firstL3Connection);
5975     }
5976 
5977     @Test
testWifiConnectionResultAtomNotEmittedWithNoConnectionEndEvent()5978     public void testWifiConnectionResultAtomNotEmittedWithNoConnectionEndEvent() {
5979         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, createComplexWifiConfig(),
5980                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
5981 
5982         ExtendedMockito.verify(() -> WifiStatsLog.write(
5983                 anyInt(), anyBoolean(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt(),
5984                 anyBoolean(), anyInt()),
5985                 times(0));
5986     }
5987 
5988     @Test
testWifiConnectionResultAtomNotEmittedWithNoConnectionStartEvent()5989     public void testWifiConnectionResultAtomNotEmittedWithNoConnectionStartEvent() {
5990         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
5991                 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
5992                 WifiMetricsProto.ConnectionEvent.HLF_DHCP,
5993                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, TEST_CANDIDATE_FREQ);
5994 
5995         ExtendedMockito.verify(() -> WifiStatsLog.write(
5996                 anyInt(), anyBoolean(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt(),
5997                 anyBoolean(), anyInt()),
5998                 times(0));
5999     }
6000 
6001     @Test
testWifiConnectionResultAtomEmittedOnlyOnceWithMultipleConnectionEndEvents()6002     public void testWifiConnectionResultAtomEmittedOnlyOnceWithMultipleConnectionEndEvents() {
6003         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, createComplexWifiConfig(),
6004                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
6005 
6006         for (int i = 0; i < 5; i++) {
6007             mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
6008                     WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
6009                     WifiMetricsProto.ConnectionEvent.HLF_DHCP,
6010                     WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, TEST_CANDIDATE_FREQ);
6011         }
6012 
6013         ExtendedMockito.verify(() -> WifiStatsLog.write(
6014                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED, false,
6015                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_AUTHENTICATION_GENERAL,
6016                 -80, 0,
6017                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__BAND__BAND_2G,
6018                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__AUTH_TYPE__AUTH_TYPE_WPA2_PSK,
6019                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__TRIGGER__AUTOCONNECT_BOOT,
6020                 true,
6021                 0),
6022                 times(1));
6023     }
6024 
6025     @Test
testWifiConnectionResultAtomNewSessionOverwritesPreviousSession()6026     public void testWifiConnectionResultAtomNewSessionOverwritesPreviousSession() {
6027 
6028         WifiConfiguration config1 = createComplexWifiConfig();
6029         config1.getNetworkSelectionStatus().getCandidate().level = -50;
6030 
6031         WifiConfiguration config2 = createComplexWifiConfig();
6032         config2.getNetworkSelectionStatus().getCandidate().level = -60;
6033 
6034         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, config1,
6035                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
6036 
6037         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, config2,
6038                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
6039 
6040         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
6041                 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
6042                 WifiMetricsProto.ConnectionEvent.HLF_DHCP,
6043                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, TEST_CANDIDATE_FREQ);
6044 
6045         ExtendedMockito.verify(() -> WifiStatsLog.write(
6046                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED, false,
6047                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__FAILURE_CODE__FAILURE_AUTHENTICATION_GENERAL,
6048                 -60, 0,
6049                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__BAND__BAND_2G,
6050                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__AUTH_TYPE__AUTH_TYPE_WPA2_PSK,
6051                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__TRIGGER__AUTOCONNECT_BOOT,
6052                 true,
6053                 0),
6054                 times(1));
6055     }
6056 
6057     @Test
testWifiConnectionResultAtomHasCorrectTriggers()6058     public void testWifiConnectionResultAtomHasCorrectTriggers() {
6059         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, createComplexWifiConfig(),
6060                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
6061 
6062         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
6063                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
6064                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
6065                 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE, TEST_CANDIDATE_FREQ);
6066 
6067         mWifiMetrics.reportNetworkDisconnect(TEST_IFACE_NAME, 0, 0, 0);
6068 
6069         ExtendedMockito.verify(() -> WifiStatsLog.write(
6070                 eq(WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED), anyBoolean(),
6071                 anyInt(), anyInt(), anyInt(), anyInt(), anyInt(),
6072                 eq(WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__TRIGGER__AUTOCONNECT_BOOT),
6073                 anyBoolean(), anyInt()));
6074 
6075         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, createComplexWifiConfig(),
6076                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
6077 
6078         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
6079                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
6080                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
6081                 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE, TEST_CANDIDATE_FREQ);
6082 
6083         mWifiMetrics.reportNetworkDisconnect(TEST_IFACE_NAME, 0, 0, 0);
6084 
6085         ExtendedMockito.verify(() -> WifiStatsLog.write(
6086                 eq(WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED), anyBoolean(),
6087                 anyInt(), anyInt(), anyInt(), anyInt(), anyInt(),
6088                 eq(WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__TRIGGER__RECONNECT_SAME_NETWORK),
6089                 anyBoolean(), anyInt()));
6090 
6091         WifiConfiguration configOtherNetwork = createComplexWifiConfig();
6092         configOtherNetwork.networkId = 21;
6093         configOtherNetwork.SSID = "OtherNetwork";
6094         mWifiMetrics.setNominatorForNetwork(configOtherNetwork.networkId,
6095                 WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED);
6096 
6097         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, configOtherNetwork,
6098                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
6099 
6100         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
6101                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
6102                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
6103                 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE, TEST_CANDIDATE_FREQ);
6104 
6105         mWifiMetrics.reportNetworkDisconnect(TEST_IFACE_NAME, 0, 0, 0);
6106 
6107         ExtendedMockito.verify(() -> WifiStatsLog.write(
6108                 eq(WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED), anyBoolean(),
6109                 anyInt(), anyInt(), anyInt(), anyInt(), anyInt(),
6110                 eq(WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__TRIGGER__AUTOCONNECT_CONFIGURED_NETWORK),
6111                 anyBoolean(), anyInt()));
6112 
6113         WifiConfiguration config = createComplexWifiConfig();
6114         config.networkId = 42;
6115         mWifiMetrics.setNominatorForNetwork(config.networkId,
6116                 WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL);
6117 
6118         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, config,
6119                 "GREEN", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
6120 
6121         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
6122                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
6123                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
6124                 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE, TEST_CANDIDATE_FREQ);
6125 
6126         ExtendedMockito.verify(() -> WifiStatsLog.write(
6127                 eq(WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED), anyBoolean(),
6128                 anyInt(), anyInt(), anyInt(), anyInt(), anyInt(),
6129                 eq(WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__TRIGGER__MANUAL),
6130                 anyBoolean(), anyInt()));
6131     }
6132 
6133     @Test
testWifiDisconnectAtomEmittedOnDisconnectFromSuccessfulSession()6134     public void testWifiDisconnectAtomEmittedOnDisconnectFromSuccessfulSession() {
6135         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, createComplexWifiConfig(),
6136                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
6137 
6138         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
6139                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
6140                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
6141                 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE, TEST_CANDIDATE_FREQ);
6142 
6143         int linkSpeed = 100;
6144         int reason = 42;
6145         mWifiMetrics.reportNetworkDisconnect(TEST_IFACE_NAME, reason, TEST_CANDIDATE_LEVEL,
6146                 linkSpeed);
6147 
6148         ExtendedMockito.verify(() -> WifiStatsLog.write(
6149                 WifiStatsLog.WIFI_DISCONNECT_REPORTED,
6150                 0,
6151                 reason,
6152                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__BAND__BAND_2G,
6153                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__AUTH_TYPE__AUTH_TYPE_WPA2_PSK,
6154                 TEST_CANDIDATE_LEVEL,
6155                 linkSpeed));
6156     }
6157 
6158     @Test
testWifiDisconnectAtomNotEmittedOnDisconnectFromNotConnectedSession()6159     public void testWifiDisconnectAtomNotEmittedOnDisconnectFromNotConnectedSession() {
6160         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, createComplexWifiConfig(),
6161                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
6162 
6163         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
6164                 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
6165                 WifiMetricsProto.ConnectionEvent.HLF_DHCP,
6166                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, TEST_CANDIDATE_FREQ);
6167 
6168 
6169         int linkSpeed = 100;
6170         int reason = 42;
6171         mWifiMetrics.reportNetworkDisconnect(TEST_IFACE_NAME, reason, TEST_CANDIDATE_LEVEL,
6172                 linkSpeed);
6173 
6174         ExtendedMockito.verify(() -> WifiStatsLog.write(
6175                 eq(WifiStatsLog.WIFI_DISCONNECT_REPORTED),
6176                 anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt()),
6177                 times(0));
6178     }
6179 
6180     @Test
testWifiDisconnectAtomNotEmittedWithNoSession()6181     public void testWifiDisconnectAtomNotEmittedWithNoSession() {
6182         mWifiMetrics.reportNetworkDisconnect(TEST_IFACE_NAME, 0, TEST_CANDIDATE_LEVEL, 0);
6183 
6184         ExtendedMockito.verify(() -> WifiStatsLog.write(
6185                 eq(WifiStatsLog.WIFI_DISCONNECT_REPORTED),
6186                 anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt()),
6187                 times(0));
6188     }
6189 
6190     @Test
testWifiStateChangedAtomEmittedOnSuccessfulConnectAndDisconnect()6191     public void testWifiStateChangedAtomEmittedOnSuccessfulConnectAndDisconnect() {
6192         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, createComplexWifiConfig(),
6193                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
6194 
6195         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
6196                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
6197                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
6198                 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE, TEST_CANDIDATE_FREQ);
6199 
6200         // TRUE must be emitted
6201         ExtendedMockito.verify(() -> WifiStatsLog.write(
6202                 WifiStatsLog.WIFI_CONNECTION_STATE_CHANGED,
6203                 true,
6204                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__BAND__BAND_2G,
6205                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__AUTH_TYPE__AUTH_TYPE_WPA2_PSK));
6206 
6207         int linkSpeed = 100;
6208         int reason = 42;
6209         mWifiMetrics.reportNetworkDisconnect(TEST_IFACE_NAME, reason, TEST_CANDIDATE_LEVEL,
6210                 linkSpeed);
6211 
6212         // FALSE must be emitted
6213         ExtendedMockito.verify(() -> WifiStatsLog.write(
6214                 WifiStatsLog.WIFI_CONNECTION_STATE_CHANGED,
6215                 false,
6216                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__BAND__BAND_2G,
6217                 WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__AUTH_TYPE__AUTH_TYPE_WPA2_PSK));
6218     }
6219 
6220     @Test
testWifiStateChangedAtomNotEmittedOnNotSuccessfulConnectAndDisconnect()6221     public void testWifiStateChangedAtomNotEmittedOnNotSuccessfulConnectAndDisconnect() {
6222         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, createComplexWifiConfig(),
6223                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
6224 
6225         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
6226                 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
6227                 WifiMetricsProto.ConnectionEvent.HLF_DHCP,
6228                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, TEST_CANDIDATE_FREQ);
6229 
6230         // TRUE must not be emitted
6231         ExtendedMockito.verify(() -> WifiStatsLog.write(
6232                 eq(WifiStatsLog.WIFI_CONNECTION_STATE_CHANGED),
6233                 anyBoolean(), anyInt(), anyInt()),
6234                 times(0));
6235 
6236         int linkSpeed = 100;
6237         int reason = 42;
6238         mWifiMetrics.reportNetworkDisconnect(TEST_IFACE_NAME, reason, TEST_CANDIDATE_LEVEL,
6239                 linkSpeed);
6240 
6241         // But we still expect FALSE to be emitted
6242         ExtendedMockito.verify(() -> WifiStatsLog.write(
6243                 WifiStatsLog.WIFI_CONNECTION_STATE_CHANGED,
6244                 false,
6245                 0,
6246                 0));
6247     }
6248 
6249     @Test
testWifiConnectionResultTimeSinceLastConnectionCorrect()6250     public void testWifiConnectionResultTimeSinceLastConnectionCorrect() {
6251         when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 10 * 1000);
6252 
6253         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, createComplexWifiConfig(),
6254                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
6255 
6256         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
6257                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
6258                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
6259                 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE, TEST_CANDIDATE_FREQ);
6260 
6261         ExtendedMockito.verify(() -> WifiStatsLog.write(
6262                 eq(WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED), anyBoolean(),
6263                 anyInt(), anyInt(), anyInt(), anyInt(), anyInt(),
6264                 eq(WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__TRIGGER__AUTOCONNECT_BOOT),
6265                 anyBoolean(), eq(10)));
6266 
6267         mWifiMetrics.reportNetworkDisconnect(TEST_IFACE_NAME, 0, 0, 0);
6268 
6269         when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 30 * 1000);
6270 
6271         mWifiMetrics.startConnectionEvent(TEST_IFACE_NAME, createComplexWifiConfig(),
6272                 "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
6273 
6274         mWifiMetrics.endConnectionEvent(TEST_IFACE_NAME,
6275                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
6276                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
6277                 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE, TEST_CANDIDATE_FREQ);
6278 
6279         ExtendedMockito.verify(() -> WifiStatsLog.write(
6280                 eq(WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED), anyBoolean(),
6281                 anyInt(), anyInt(), anyInt(), anyInt(), anyInt(),
6282                 eq(WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__TRIGGER__RECONNECT_SAME_NETWORK),
6283                 anyBoolean(), eq(20)));
6284 
6285         mWifiMetrics.reportNetworkDisconnect(TEST_IFACE_NAME, 0, 0, 0);
6286     }
6287 
6288     @Test
testWifiScanEmittedOnSuccess()6289     public void testWifiScanEmittedOnSuccess() {
6290         WifiMetrics.ScanMetrics scanMetrics = mWifiMetrics.getScanMetrics();
6291 
6292         scanMetrics.setImportance(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
6293         scanMetrics.logScanStarted(WifiMetrics.ScanMetrics.SCAN_TYPE_SINGLE);
6294         scanMetrics.logScanSucceeded(WifiMetrics.ScanMetrics.SCAN_TYPE_SINGLE, 4);
6295 
6296         ExtendedMockito.verify(() -> WifiStatsLog.write(
6297                 WifiStatsLog.WIFI_SCAN_REPORTED,
6298                 WifiStatsLog.WIFI_SCAN_REPORTED__TYPE__TYPE_SINGLE,
6299                 WifiStatsLog.WIFI_SCAN_REPORTED__RESULT__RESULT_SUCCESS,
6300                 WifiStatsLog.WIFI_SCAN_REPORTED__SOURCE__SOURCE_NO_WORK_SOURCE,
6301                 WifiStatsLog.WIFI_SCAN_REPORTED__IMPORTANCE__IMPORTANCE_FOREGROUND,
6302                 0, 4));
6303     }
6304 
6305     @Test
testWifiScanEmittedOnFailedToStart()6306     public void testWifiScanEmittedOnFailedToStart() {
6307         WifiMetrics.ScanMetrics scanMetrics = mWifiMetrics.getScanMetrics();
6308 
6309         scanMetrics.logScanFailedToStart(WifiMetrics.ScanMetrics.SCAN_TYPE_SINGLE);
6310 
6311         ExtendedMockito.verify(() -> WifiStatsLog.write(
6312                 WifiStatsLog.WIFI_SCAN_REPORTED,
6313                 WifiStatsLog.WIFI_SCAN_REPORTED__TYPE__TYPE_SINGLE,
6314                 WifiStatsLog.WIFI_SCAN_REPORTED__RESULT__RESULT_FAILED_TO_START,
6315                 WifiStatsLog.WIFI_SCAN_REPORTED__SOURCE__SOURCE_NO_WORK_SOURCE,
6316                 WifiStatsLog.WIFI_SCAN_REPORTED__IMPORTANCE__IMPORTANCE_UNKNOWN,
6317                 0, 0));
6318     }
6319 
6320     @Test
testWifiScanEmittedOnFailure()6321     public void testWifiScanEmittedOnFailure() {
6322         WifiMetrics.ScanMetrics scanMetrics = mWifiMetrics.getScanMetrics();
6323 
6324         scanMetrics.logScanStarted(WifiMetrics.ScanMetrics.SCAN_TYPE_SINGLE);
6325         scanMetrics.logScanFailed(WifiMetrics.ScanMetrics.SCAN_TYPE_SINGLE);
6326 
6327         ExtendedMockito.verify(() -> WifiStatsLog.write(
6328                 WifiStatsLog.WIFI_SCAN_REPORTED,
6329                 WifiStatsLog.WIFI_SCAN_REPORTED__TYPE__TYPE_SINGLE,
6330                 WifiStatsLog.WIFI_SCAN_REPORTED__RESULT__RESULT_FAILED_TO_SCAN,
6331                 WifiStatsLog.WIFI_SCAN_REPORTED__SOURCE__SOURCE_NO_WORK_SOURCE,
6332                 WifiStatsLog.WIFI_SCAN_REPORTED__IMPORTANCE__IMPORTANCE_UNKNOWN,
6333                 0, 0));
6334     }
6335 
6336     @Test
testWifiScanNotEmittedWithNoStart()6337     public void testWifiScanNotEmittedWithNoStart() {
6338         WifiMetrics.ScanMetrics scanMetrics = mWifiMetrics.getScanMetrics();
6339 
6340         scanMetrics.logScanSucceeded(WifiMetrics.ScanMetrics.SCAN_TYPE_SINGLE, 4);
6341 
6342         ExtendedMockito.verify(() -> WifiStatsLog.write(
6343                 eq(WifiStatsLog.WIFI_SCAN_REPORTED),
6344                 anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt()), times(0));
6345     }
6346 
6347     @Test
testWifiScanEmittedOnlyOnce()6348     public void testWifiScanEmittedOnlyOnce() {
6349         WifiMetrics.ScanMetrics scanMetrics = mWifiMetrics.getScanMetrics();
6350 
6351         scanMetrics.logScanStarted(WifiMetrics.ScanMetrics.SCAN_TYPE_SINGLE);
6352         scanMetrics.logScanSucceeded(WifiMetrics.ScanMetrics.SCAN_TYPE_SINGLE, 4);
6353         scanMetrics.logScanSucceeded(WifiMetrics.ScanMetrics.SCAN_TYPE_SINGLE, 5);
6354         scanMetrics.logScanSucceeded(WifiMetrics.ScanMetrics.SCAN_TYPE_SINGLE, 6);
6355 
6356         ExtendedMockito.verify(() -> WifiStatsLog.write(
6357                 eq(WifiStatsLog.WIFI_SCAN_REPORTED),
6358                 anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), eq(4)), times(1));
6359     }
6360 
6361     @Test
testWifiScanStatePreservedAfterStart()6362     public void testWifiScanStatePreservedAfterStart() {
6363         WifiMetrics.ScanMetrics scanMetrics = mWifiMetrics.getScanMetrics();
6364 
6365         scanMetrics.setImportance(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
6366         scanMetrics.logScanStarted(WifiMetrics.ScanMetrics.SCAN_TYPE_SINGLE);
6367         scanMetrics.setImportance(ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE);
6368         scanMetrics.logScanSucceeded(WifiMetrics.ScanMetrics.SCAN_TYPE_SINGLE, 4);
6369 
6370         ExtendedMockito.verify(() -> WifiStatsLog.write(
6371                 WifiStatsLog.WIFI_SCAN_REPORTED,
6372                 WifiStatsLog.WIFI_SCAN_REPORTED__TYPE__TYPE_SINGLE,
6373                 WifiStatsLog.WIFI_SCAN_REPORTED__RESULT__RESULT_SUCCESS,
6374                 WifiStatsLog.WIFI_SCAN_REPORTED__SOURCE__SOURCE_NO_WORK_SOURCE,
6375                 WifiStatsLog.WIFI_SCAN_REPORTED__IMPORTANCE__IMPORTANCE_FOREGROUND,
6376                 0, 4));
6377     }
6378 
6379     @Test
testWifiScanOverlappingRequestsOverwriteStateForSameType()6380     public void testWifiScanOverlappingRequestsOverwriteStateForSameType() {
6381         WifiMetrics.ScanMetrics scanMetrics = mWifiMetrics.getScanMetrics();
6382 
6383         scanMetrics.setImportance(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
6384         scanMetrics.logScanStarted(WifiMetrics.ScanMetrics.SCAN_TYPE_SINGLE);
6385 
6386         scanMetrics.setImportance(ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE);
6387         scanMetrics.logScanStarted(WifiMetrics.ScanMetrics.SCAN_TYPE_SINGLE);
6388 
6389         scanMetrics.logScanSucceeded(WifiMetrics.ScanMetrics.SCAN_TYPE_SINGLE, 42);
6390         scanMetrics.logScanSucceeded(WifiMetrics.ScanMetrics.SCAN_TYPE_SINGLE, 21);
6391 
6392         ExtendedMockito.verify(() -> WifiStatsLog.write(
6393                 WifiStatsLog.WIFI_SCAN_REPORTED,
6394                 WifiStatsLog.WIFI_SCAN_REPORTED__TYPE__TYPE_SINGLE,
6395                 WifiStatsLog.WIFI_SCAN_REPORTED__RESULT__RESULT_SUCCESS,
6396                 WifiStatsLog.WIFI_SCAN_REPORTED__SOURCE__SOURCE_NO_WORK_SOURCE,
6397                 WifiStatsLog.WIFI_SCAN_REPORTED__IMPORTANCE__IMPORTANCE_BACKGROUND,
6398                 0, 42));
6399     }
6400 
6401     @Test
testWifiScanOverlappingRequestsSeparateStatesForDifferentTypes()6402     public void testWifiScanOverlappingRequestsSeparateStatesForDifferentTypes() {
6403         WifiMetrics.ScanMetrics scanMetrics = mWifiMetrics.getScanMetrics();
6404 
6405         scanMetrics.setImportance(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
6406         scanMetrics.logScanStarted(WifiMetrics.ScanMetrics.SCAN_TYPE_SINGLE);
6407 
6408         scanMetrics.setImportance(ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE);
6409         scanMetrics.logScanStarted(WifiMetrics.ScanMetrics.SCAN_TYPE_BACKGROUND);
6410 
6411         scanMetrics.logScanSucceeded(WifiMetrics.ScanMetrics.SCAN_TYPE_SINGLE, 42);
6412         scanMetrics.logScanSucceeded(WifiMetrics.ScanMetrics.SCAN_TYPE_BACKGROUND, 21);
6413 
6414         ExtendedMockito.verify(() -> WifiStatsLog.write(
6415                 WifiStatsLog.WIFI_SCAN_REPORTED,
6416                 WifiStatsLog.WIFI_SCAN_REPORTED__TYPE__TYPE_SINGLE,
6417                 WifiStatsLog.WIFI_SCAN_REPORTED__RESULT__RESULT_SUCCESS,
6418                 WifiStatsLog.WIFI_SCAN_REPORTED__SOURCE__SOURCE_NO_WORK_SOURCE,
6419                 WifiStatsLog.WIFI_SCAN_REPORTED__IMPORTANCE__IMPORTANCE_FOREGROUND,
6420                 0, 42));
6421 
6422         ExtendedMockito.verify(() -> WifiStatsLog.write(
6423                 WifiStatsLog.WIFI_SCAN_REPORTED,
6424                 WifiStatsLog.WIFI_SCAN_REPORTED__TYPE__TYPE_BACKGROUND,
6425                 WifiStatsLog.WIFI_SCAN_REPORTED__RESULT__RESULT_SUCCESS,
6426                 WifiStatsLog.WIFI_SCAN_REPORTED__SOURCE__SOURCE_NO_WORK_SOURCE,
6427                 WifiStatsLog.WIFI_SCAN_REPORTED__IMPORTANCE__IMPORTANCE_BACKGROUND,
6428                 0, 21));
6429     }
6430 
setScreenState(boolean screenOn)6431     private void setScreenState(boolean screenOn) {
6432         BroadcastReceiver broadcastReceiver = mBroadcastReceiverCaptor.getValue();
6433         assertNotNull(broadcastReceiver);
6434         Intent intent = new Intent(screenOn  ? ACTION_SCREEN_ON : ACTION_SCREEN_OFF);
6435         broadcastReceiver.onReceive(mContext, intent);
6436     }
6437 
6438     @Test
testWifiToWifiSwitchMetrics()6439     public void testWifiToWifiSwitchMetrics() throws Exception {
6440         // initially all 0
6441         dumpProtoAndDeserialize();
6442 
6443         assertFalse(mDecodedProto.wifiToWifiSwitchStats.isMakeBeforeBreakSupported);
6444         assertEquals(0, mDecodedProto.wifiToWifiSwitchStats.wifiToWifiSwitchTriggerCount);
6445         assertEquals(0, mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakTriggerCount);
6446         assertEquals(0, mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakNoInternetCount);
6447         assertEquals(0, mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakRecoverPrimaryCount);
6448         assertEquals(0, mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakInternetValidatedCount);
6449         assertEquals(0, mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakSuccessCount);
6450         assertEquals(0, mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakLingerCompletedCount);
6451         assertEquals(0,
6452                 mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakLingerDurationSeconds.length);
6453 
6454         // increment everything
6455         mWifiMetrics.setIsMakeBeforeBreakSupported(true);
6456         mWifiMetrics.incrementWifiToWifiSwitchTriggerCount();
6457         mWifiMetrics.incrementMakeBeforeBreakTriggerCount();
6458         mWifiMetrics.incrementMakeBeforeBreakNoInternetCount();
6459         mWifiMetrics.incrementMakeBeforeBreakRecoverPrimaryCount();
6460         mWifiMetrics.incrementMakeBeforeBreakInternetValidatedCount();
6461         mWifiMetrics.incrementMakeBeforeBreakSuccessCount();
6462         mWifiMetrics.incrementMakeBeforeBreakLingerCompletedCount(1000);
6463 
6464         dumpProtoAndDeserialize();
6465 
6466         // should be all 1
6467         assertTrue(mDecodedProto.wifiToWifiSwitchStats.isMakeBeforeBreakSupported);
6468         assertEquals(1, mDecodedProto.wifiToWifiSwitchStats.wifiToWifiSwitchTriggerCount);
6469         assertEquals(1, mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakTriggerCount);
6470         assertEquals(1, mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakNoInternetCount);
6471         assertEquals(1, mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakRecoverPrimaryCount);
6472         assertEquals(1, mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakInternetValidatedCount);
6473         assertEquals(1, mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakSuccessCount);
6474         assertEquals(1, mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakLingerCompletedCount);
6475         assertEquals(1,
6476                 mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakLingerDurationSeconds.length);
6477         assertEquals(1,
6478                 mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakLingerDurationSeconds[0].key);
6479         assertEquals(1,
6480                 mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakLingerDurationSeconds[0].count);
6481 
6482         // dump again
6483         dumpProtoAndDeserialize();
6484 
6485         // everything should be reset
6486         assertFalse(mDecodedProto.wifiToWifiSwitchStats.isMakeBeforeBreakSupported);
6487         assertEquals(0, mDecodedProto.wifiToWifiSwitchStats.wifiToWifiSwitchTriggerCount);
6488         assertEquals(0, mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakTriggerCount);
6489         assertEquals(0, mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakNoInternetCount);
6490         assertEquals(0, mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakRecoverPrimaryCount);
6491         assertEquals(0, mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakInternetValidatedCount);
6492         assertEquals(0, mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakSuccessCount);
6493         assertEquals(0, mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakLingerCompletedCount);
6494         assertEquals(0,
6495                 mDecodedProto.wifiToWifiSwitchStats.makeBeforeBreakLingerDurationSeconds.length);
6496     }
6497 
6498     @Test
testPasspointConnectionMetrics()6499     public void testPasspointConnectionMetrics() throws Exception {
6500         // initially all 0
6501         dumpProtoAndDeserialize();
6502 
6503         assertEquals(0, mDecodedProto.totalNumberOfPasspointConnectionsWithVenueUrl);
6504         assertEquals(0, mDecodedProto.totalNumberOfPasspointConnectionsWithTermsAndConditionsUrl);
6505         assertEquals(0, mDecodedProto.totalNumberOfPasspointAcceptanceOfTermsAndConditions);
6506         assertEquals(0, mDecodedProto.totalNumberOfPasspointProfilesWithDecoratedIdentity);
6507         assertEquals(0, mDecodedProto.passpointDeauthImminentScope.length);
6508 
6509         // increment everything
6510         mWifiMetrics.incrementTotalNumberOfPasspointConnectionsWithVenueUrl();
6511         mWifiMetrics.incrementTotalNumberOfPasspointConnectionsWithTermsAndConditionsUrl();
6512         mWifiMetrics.incrementTotalNumberOfPasspointAcceptanceOfTermsAndConditions();
6513         mWifiMetrics.incrementTotalNumberOfPasspointProfilesWithDecoratedIdentity();
6514         mWifiMetrics.incrementPasspointDeauthImminentScope(true);
6515         mWifiMetrics.incrementPasspointDeauthImminentScope(false);
6516         mWifiMetrics.incrementPasspointDeauthImminentScope(false);
6517 
6518         dumpProtoAndDeserialize();
6519 
6520         Int32Count[] expectedDeauthImminentScope = {
6521                 buildInt32Count(WifiMetrics.PASSPOINT_DEAUTH_IMMINENT_SCOPE_ESS, 1),
6522                 buildInt32Count(WifiMetrics.PASSPOINT_DEAUTH_IMMINENT_SCOPE_BSS, 2),
6523         };
6524 
6525         assertEquals(1, mDecodedProto.totalNumberOfPasspointConnectionsWithVenueUrl);
6526         assertEquals(1, mDecodedProto.totalNumberOfPasspointConnectionsWithTermsAndConditionsUrl);
6527         assertEquals(1, mDecodedProto.totalNumberOfPasspointAcceptanceOfTermsAndConditions);
6528         assertEquals(1, mDecodedProto.totalNumberOfPasspointProfilesWithDecoratedIdentity);
6529         assertKeyCountsEqual(expectedDeauthImminentScope,
6530                 mDecodedProto.passpointDeauthImminentScope);
6531 
6532         // dump again
6533         dumpProtoAndDeserialize();
6534 
6535         // everything should be reset
6536         assertEquals(0, mDecodedProto.totalNumberOfPasspointConnectionsWithVenueUrl);
6537         assertEquals(0, mDecodedProto.totalNumberOfPasspointConnectionsWithTermsAndConditionsUrl);
6538         assertEquals(0, mDecodedProto.totalNumberOfPasspointAcceptanceOfTermsAndConditions);
6539         assertEquals(0, mDecodedProto.totalNumberOfPasspointProfilesWithDecoratedIdentity);
6540         assertEquals(0, mDecodedProto.passpointDeauthImminentScope.length);
6541     }
6542 
6543     @Test
testWifiStatsHealthStatWrite()6544     public void testWifiStatsHealthStatWrite() throws Exception {
6545         WifiInfo wifiInfo = mock(WifiInfo.class);
6546         when(wifiInfo.getFrequency()).thenReturn(5810);
6547         mWifiMetrics.incrementWifiScoreCount("",  60);
6548         mWifiMetrics.handlePollResult(TEST_IFACE_NAME, wifiInfo);
6549         mWifiMetrics.incrementConnectionDuration(3000, true, true);
6550         ExtendedMockito.verify(() -> WifiStatsLog.write(
6551                 WifiStatsLog.WIFI_HEALTH_STAT_REPORTED, 3000, true, true,
6552                 WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__BAND_5G_HIGH));
6553 
6554         when(wifiInfo.getFrequency()).thenReturn(2412);
6555         mWifiMetrics.incrementWifiScoreCount("",  30);
6556         mWifiMetrics.handlePollResult(TEST_IFACE_NAME, wifiInfo);
6557         mWifiMetrics.incrementConnectionDuration(2000, false, true);
6558         ExtendedMockito.verify(() -> WifiStatsLog.write(
6559                 WifiStatsLog.WIFI_HEALTH_STAT_REPORTED, 2000, true, true,
6560                 WifiStatsLog.WIFI_HEALTH_STAT_REPORTED__BAND__BAND_2G));
6561     }
6562 
6563     /**
6564      * Test number of times connection failure status reported per
6565      * WifiConfiguration.RecentFailureReason
6566      */
6567     @Test
testRecentFailureAssociationStatusCount()6568     public void testRecentFailureAssociationStatusCount() throws Exception {
6569         mWifiMetrics.incrementRecentFailureAssociationStatusCount(
6570                 WifiConfiguration.RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA);
6571         mWifiMetrics.incrementRecentFailureAssociationStatusCount(
6572                 WifiConfiguration.RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA);
6573         mWifiMetrics.incrementRecentFailureAssociationStatusCount(
6574                 WifiConfiguration.RECENT_FAILURE_OCE_RSSI_BASED_ASSOCIATION_REJECTION);
6575         mWifiMetrics.incrementRecentFailureAssociationStatusCount(
6576                 WifiConfiguration.RECENT_FAILURE_MBO_ASSOC_DISALLOWED_AIR_INTERFACE_OVERLOADED);
6577         mWifiMetrics.incrementRecentFailureAssociationStatusCount(
6578                 WifiConfiguration.RECENT_FAILURE_MBO_ASSOC_DISALLOWED_AIR_INTERFACE_OVERLOADED);
6579 
6580         dumpProtoAndDeserialize();
6581 
6582         Int32Count[] expectedRecentFailureAssociationStatus = {
6583                 buildInt32Count(WifiConfiguration.RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA,
6584                         2),
6585                 buildInt32Count(
6586                         WifiConfiguration
6587                                 .RECENT_FAILURE_MBO_ASSOC_DISALLOWED_AIR_INTERFACE_OVERLOADED, 2),
6588                 buildInt32Count(
6589                         WifiConfiguration.RECENT_FAILURE_OCE_RSSI_BASED_ASSOCIATION_REJECTION, 1),
6590         };
6591 
6592         assertKeyCountsEqual(expectedRecentFailureAssociationStatus,
6593                 mDecodedProto.recentFailureAssociationStatus);
6594 
6595     }
6596 }
6597